Spaces:
Sleeping
Sleeping
| """ | |
| ECDSA Signing Module | |
| ===================== | |
| Provides ECDSA signature functionality for ledger blocks. | |
| """ | |
| import hashlib | |
| from typing import Optional, Tuple | |
| from dataclasses import dataclass | |
| from cryptography.hazmat.primitives import hashes, serialization | |
| from cryptography.hazmat.primitives.asymmetric import ec | |
| from cryptography.hazmat.backends import default_backend | |
| from cryptography.exceptions import InvalidSignature | |
| class KeyPair: | |
| """Holds ECDSA key pair.""" | |
| private_key: ec.EllipticCurvePrivateKey | |
| public_key: ec.EllipticCurvePublicKey | |
| def get_public_key_hex(self) -> str: | |
| """Get public key as hex string.""" | |
| public_bytes = self.public_key.public_bytes( | |
| encoding=serialization.Encoding.X962, | |
| format=serialization.PublicFormat.CompressedPoint | |
| ) | |
| return public_bytes.hex() | |
| def get_private_key_pem(self) -> bytes: | |
| """Get private key as PEM bytes (for secure storage).""" | |
| return self.private_key.private_bytes( | |
| encoding=serialization.Encoding.PEM, | |
| format=serialization.PrivateFormat.PKCS8, | |
| encryption_algorithm=serialization.NoEncryption() | |
| ) | |
| class ECDSASigner: | |
| """ | |
| ECDSA signer for creating and verifying signatures. | |
| Uses secp256k1 curve (same as Bitcoin/Ethereum). | |
| """ | |
| CURVE = ec.SECP256K1() | |
| def __init__(self, private_key: Optional[ec.EllipticCurvePrivateKey] = None): | |
| """ | |
| Initialize the signer. | |
| Args: | |
| private_key: Existing private key. If None, generates a new one. | |
| """ | |
| if private_key: | |
| self.private_key = private_key | |
| else: | |
| self.private_key = ec.generate_private_key(self.CURVE, default_backend()) | |
| self.public_key = self.private_key.public_key() | |
| def generate_keypair(cls) -> KeyPair: | |
| """Generate a new ECDSA key pair.""" | |
| private_key = ec.generate_private_key(cls.CURVE, default_backend()) | |
| public_key = private_key.public_key() | |
| return KeyPair(private_key=private_key, public_key=public_key) | |
| def from_private_key_pem(cls, pem_data: bytes) -> 'ECDSASigner': | |
| """ | |
| Create a signer from PEM-encoded private key. | |
| Args: | |
| pem_data: PEM-encoded private key bytes | |
| Returns: | |
| ECDSASigner instance | |
| """ | |
| private_key = serialization.load_pem_private_key( | |
| pem_data, | |
| password=None, | |
| backend=default_backend() | |
| ) | |
| return cls(private_key=private_key) | |
| def sign(self, data: str) -> str: | |
| """ | |
| Sign data and return signature as hex string. | |
| Args: | |
| data: Data string to sign (typically a block hash) | |
| Returns: | |
| Signature as hex string | |
| """ | |
| data_bytes = data.encode('utf-8') | |
| signature = self.private_key.sign( | |
| data_bytes, | |
| ec.ECDSA(hashes.SHA256()) | |
| ) | |
| return signature.hex() | |
| def verify(self, data: str, signature_hex: str) -> bool: | |
| """ | |
| Verify a signature. | |
| Args: | |
| data: Original data string | |
| signature_hex: Signature as hex string | |
| Returns: | |
| True if signature is valid | |
| """ | |
| try: | |
| data_bytes = data.encode('utf-8') | |
| signature = bytes.fromhex(signature_hex) | |
| self.public_key.verify( | |
| signature, | |
| data_bytes, | |
| ec.ECDSA(hashes.SHA256()) | |
| ) | |
| return True | |
| except (InvalidSignature, ValueError): | |
| return False | |
| def get_public_key_hex(self) -> str: | |
| """Get public key as hex string.""" | |
| public_bytes = self.public_key.public_bytes( | |
| encoding=serialization.Encoding.X962, | |
| format=serialization.PublicFormat.CompressedPoint | |
| ) | |
| return public_bytes.hex() | |
| class SignatureVerifier: | |
| """ | |
| Verifier for ECDSA signatures using only public key. | |
| Use this when you only need to verify signatures, not create them. | |
| """ | |
| def __init__(self, public_key_hex: str): | |
| """ | |
| Initialize verifier with public key. | |
| Args: | |
| public_key_hex: Public key as hex string (compressed X962 format) | |
| """ | |
| public_bytes = bytes.fromhex(public_key_hex) | |
| self.public_key = ec.EllipticCurvePublicKey.from_encoded_point( | |
| ec.SECP256K1(), | |
| public_bytes | |
| ) | |
| def verify(self, data: str, signature_hex: str) -> bool: | |
| """ | |
| Verify a signature. | |
| Args: | |
| data: Original data string | |
| signature_hex: Signature as hex string | |
| Returns: | |
| True if signature is valid | |
| """ | |
| try: | |
| data_bytes = data.encode('utf-8') | |
| signature = bytes.fromhex(signature_hex) | |
| self.public_key.verify( | |
| signature, | |
| data_bytes, | |
| ec.ECDSA(hashes.SHA256()) | |
| ) | |
| return True | |
| except (InvalidSignature, ValueError): | |
| return False | |
| def sign_block(block_hash: str, signer: ECDSASigner) -> str: | |
| """ | |
| Convenience function to sign a block hash. | |
| Args: | |
| block_hash: The block hash to sign | |
| signer: ECDSASigner instance | |
| Returns: | |
| Signature as hex string | |
| """ | |
| return signer.sign(block_hash) | |
| def verify_block_signature( | |
| block_hash: str, | |
| signature_hex: str, | |
| public_key_hex: str | |
| ) -> bool: | |
| """ | |
| Convenience function to verify a block signature. | |
| Args: | |
| block_hash: The block hash that was signed | |
| signature_hex: The signature to verify | |
| public_key_hex: Public key of the signer | |
| Returns: | |
| True if signature is valid | |
| """ | |
| verifier = SignatureVerifier(public_key_hex) | |
| return verifier.verify(block_hash, signature_hex) | |