CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-py-ecc

Elliptic curve crypto in python including secp256k1, alt_bn128, and bls12_381

Pending
Overview
Eval results
Files

bls-signatures.mddocs/

BLS Signatures

BLS (Boneh-Lynn-Shacham) signature schemes according to IETF standards, providing digital signatures with aggregation capabilities. These schemes are particularly important for blockchain applications where signature aggregation can significantly reduce data size and verification costs.

Capabilities

G2Basic Signature Scheme

The basic BLS signature scheme using G2 elements for signatures. This is the most commonly used BLS signature variant.

class G2Basic:
    DST: bytes  # Domain separation tag
    
    @classmethod
    def SkToPk(cls, sk: int) -> bytes:
        """
        Convert a secret key to a public key.
        
        Args:
            sk (int): Secret key as integer
            
        Returns:
            bytes: 48-byte compressed public key
        """
    
    @staticmethod
    def KeyValidate(pk: bytes) -> bool:
        """
        Validate a public key.
        
        Args:
            pk (bytes): 48-byte public key to validate
            
        Returns:
            bool: True if key is valid, False otherwise
        """
    
    @classmethod
    def Sign(cls, sk: int, message: bytes) -> bytes:
        """
        Sign a message with a secret key.
        
        Args:
            sk (int): Secret key as integer
            message (bytes): Message to sign
            
        Returns:
            bytes: 96-byte signature
        """
    
    @classmethod
    def Verify(cls, pk: bytes, message: bytes, signature: bytes) -> bool:
        """
        Verify a signature.
        
        Args:
            pk (bytes): 48-byte public key
            message (bytes): Original message
            signature (bytes): 96-byte signature to verify
            
        Returns:
            bool: True if signature is valid, False otherwise
        """
    
    @classmethod
    def Aggregate(cls, signatures: Sequence[bytes]) -> bytes:
        """
        Aggregate multiple signatures into one.
        
        Args:
            signatures (Sequence[bytes]): List of 96-byte signatures
            
        Returns:
            bytes: 96-byte aggregated signature
        """
    
    @classmethod
    def AggregateVerify(cls, pks: Sequence[bytes], messages: Sequence[bytes], signature: bytes) -> bool:
        """
        Verify an aggregated signature against multiple public keys and messages.
        
        Args:
            pks (Sequence[bytes]): List of 48-byte public keys
            messages (Sequence[bytes]): List of messages (one per public key)
            signature (bytes): 96-byte aggregated signature
            
        Returns:
            bool: True if aggregated signature is valid, False otherwise
        """
    
    @classmethod
    def FastAggregateVerify(cls, pks: Sequence[bytes], message: bytes, signature: bytes) -> bool:
        """
        Fast verification of aggregated signature when all messages are identical.
        
        Args:
            pks (Sequence[bytes]): List of 48-byte public keys
            message (bytes): Single message signed by all keys
            signature (bytes): 96-byte aggregated signature
            
        Returns:
            bool: True if aggregated signature is valid, False otherwise
        """

G2MessageAugmentation Signature Scheme

BLS signature scheme with message augmentation to prevent rogue key attacks without requiring proof of possession.

class G2MessageAugmentation:
    DST: bytes  # Domain separation tag
    
    @classmethod
    def SkToPk(cls, sk: int) -> bytes:
        """Convert secret key to public key."""
    
    @staticmethod
    def KeyValidate(pk: bytes) -> bool:
        """Validate a public key."""
    
    @classmethod
    def Sign(cls, sk: int, message: bytes) -> bytes:
        """Sign a message with message augmentation."""
    
    @classmethod
    def Verify(cls, pk: bytes, message: bytes, signature: bytes) -> bool:
        """Verify a signature with message augmentation."""
    
    @classmethod
    def Aggregate(cls, signatures: Sequence[bytes]) -> bytes:
        """Aggregate multiple signatures."""
    
    @classmethod
    def AggregateVerify(cls, pks: Sequence[bytes], messages: Sequence[bytes], signature: bytes) -> bool:
        """Verify aggregated signature with message augmentation."""

G2ProofOfPossession Signature Scheme

BLS signature scheme with proof of possession, providing the most secure aggregation capabilities.

class G2ProofOfPossession:
    DST: bytes  # Domain separation tag
    POP_DST: bytes  # Proof of possession domain separation tag
    
    @staticmethod
    def SkToPk(sk: int) -> bytes:
        """Convert secret key to public key."""
    
    @staticmethod
    def KeyValidate(pk: bytes) -> bool:
        """Validate a public key."""
    
    @classmethod
    def Sign(cls, sk: int, message: bytes) -> bytes:
        """Sign a message."""
    
    @classmethod
    def Verify(cls, pk: bytes, message: bytes, signature: bytes) -> bool:
        """Verify a signature."""
    
    @classmethod
    def Aggregate(cls, signatures: Sequence[bytes]) -> bytes:
        """Aggregate multiple signatures."""
    
    @classmethod
    def AggregateVerify(cls, pks: Sequence[bytes], messages: Sequence[bytes], signature: bytes) -> bool:
        """Verify aggregated signature."""
    
    @staticmethod
    def FastAggregateVerify(pks: Sequence[bytes], message: bytes, signature: bytes) -> bool:
        """Fast verification when all messages are identical."""
    
    @staticmethod
    def PopProve(sk: int) -> bytes:
        """
        Generate proof of possession for a secret key.
        
        Args:
            sk (int): Secret key
            
        Returns:
            bytes: 96-byte proof of possession
        """
    
    @staticmethod
    def PopVerify(pk: bytes, proof: bytes) -> bool:
        """
        Verify proof of possession for a public key.
        
        Args:
            pk (bytes): 48-byte public key
            proof (bytes): 96-byte proof of possession
            
        Returns:
            bool: True if proof is valid, False otherwise
        """

Usage Examples

Basic Signing and Verification

from py_ecc.bls import G2Basic

# Generate key pair
private_key = 12345
public_key = G2Basic.SkToPk(private_key)

# Sign message
message = b"Hello, BLS signatures!"
signature = G2Basic.Sign(private_key, message)

# Verify signature
is_valid = G2Basic.Verify(public_key, message, signature)
assert is_valid

Signature Aggregation

from py_ecc.bls import G2Basic

# Multiple signers
private_keys = [123, 456, 789]
public_keys = [G2Basic.SkToPk(sk) for sk in private_keys]
messages = [b"Message 1", b"Message 2", b"Message 3"]

# Each signer signs their message
signatures = [G2Basic.Sign(sk, msg) for sk, msg in zip(private_keys, messages)]

# Aggregate signatures
aggregated_sig = G2Basic.Aggregate(signatures)

# Verify aggregated signature
is_valid = G2Basic.AggregateVerify(public_keys, messages, aggregated_sig)
assert is_valid

Fast Aggregate Verification

from py_ecc.bls import G2Basic

# Multiple signers signing the same message
private_keys = [111, 222, 333]
public_keys = [G2Basic.SkToPk(sk) for sk in private_keys]
message = b"Same message for all"

# Each signer signs the same message
signatures = [G2Basic.Sign(sk, message) for sk in private_keys]

# Aggregate signatures
aggregated_sig = G2Basic.Aggregate(signatures)

# Fast verification (more efficient when all messages are identical)
is_valid = G2Basic.FastAggregateVerify(public_keys, message, aggregated_sig)
assert is_valid

Proof of Possession

from py_ecc.bls import G2ProofOfPossession

# Generate key pair
private_key = 54321
public_key = G2ProofOfPossession.SkToPk(private_key)

# Generate proof of possession
pop_proof = G2ProofOfPossession.PopProve(private_key)

# Verify proof of possession
is_valid_pop = G2ProofOfPossession.PopVerify(public_key, pop_proof)
assert is_valid_pop

# Now the public key can be safely used in aggregation
message = b"Secure aggregation message"
signature = G2ProofOfPossession.Sign(private_key, message)
is_valid = G2ProofOfPossession.Verify(public_key, message, signature)
assert is_valid

Error Handling

All BLS signature functions may raise ValidationError from eth_utils for invalid inputs:

  • Invalid key formats or lengths
  • Invalid signature formats or lengths
  • Points not in the correct subgroups
  • Invalid curve points

Always validate inputs when working with untrusted data:

from py_ecc.bls import G2Basic
from eth_utils import ValidationError

try:
    is_valid_key = G2Basic.KeyValidate(untrusted_public_key)
    if is_valid_key:
        result = G2Basic.Verify(untrusted_public_key, message, signature)
    else:
        print("Invalid public key")
except ValidationError as e:
    print(f"Validation error: {e}")

Install with Tessl CLI

npx tessl i tessl/pypi-py-ecc

docs

bls-signatures.md

bls12-381.md

bn128.md

fields.md

index.md

optimized.md

secp256k1.md

tile.json