CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-ecdsa

ECDSA cryptographic signature library (pure python)

Pending
Overview
Eval results
Files

keys-signatures.mddocs/

Core Keys & Signatures

Primary ECDSA/EdDSA functionality for creating and verifying digital signatures. This module provides the main interface for elliptic curve cryptographic operations including key generation, deterministic signing, and signature verification with support for multiple curves and hash functions.

Capabilities

SigningKey Class

The SigningKey class represents a private key for creating digital signatures using ECDSA or EdDSA algorithms.

Key Generation and Loading

class SigningKey:
    @classmethod
    def generate(cls, curve=NIST192p, entropy=None, hashfunc=sha1):
        """
        Generate a new random signing key.

        Parameters:
        - curve: Curve object (default NIST192p)
        - entropy: callable returning random bytes, or None for os.urandom
        - hashfunc: hash function for signatures (default sha1)

        Returns:
        SigningKey object
        """

    @classmethod
    def from_secret_exponent(cls, secexp, curve=NIST192p, hashfunc=sha1):
        """
        Create SigningKey from integer secret exponent.

        Parameters:
        - secexp: int, secret exponent (private key value)
        - curve: Curve object (default NIST192p)
        - hashfunc: hash function for signatures (default sha1)

        Returns:
        SigningKey object
        """

    @classmethod
    def from_string(cls, string, curve=NIST192p, hashfunc=sha1):
        """
        Create SigningKey from raw byte string.

        Parameters:
        - string: bytes, raw private key bytes
        - curve: Curve object (default NIST192p)
        - hashfunc: hash function for signatures (default sha1)

        Returns:
        SigningKey object
        """

    @classmethod
    def from_pem(cls, string, hashfunc=sha1, valid_curve_encodings=None):
        """
        Create SigningKey from PEM-encoded private key.

        Parameters:
        - string: str or bytes, PEM-encoded private key
        - hashfunc: hash function for signatures (default sha1)
        - valid_curve_encodings: list of acceptable curve encodings or None

        Returns:
        SigningKey object
        """

    @classmethod
    def from_der(cls, string, hashfunc=sha1, valid_curve_encodings=None):
        """
        Create SigningKey from DER-encoded private key.

        Parameters:
        - string: bytes, DER-encoded private key
        - hashfunc: hash function for signatures (default sha1)
        - valid_curve_encodings: list of acceptable curve encodings or None

        Returns:
        SigningKey object
        """

Signing Operations

def sign(self, data, entropy=None, hashfunc=None, sigencode=sigencode_string, k=None, allow_truncate=True):
        """
        Sign data using ECDSA/EdDSA.

        Parameters:
        - data: bytes, data to sign
        - entropy: callable returning random bytes, or None for default
        - hashfunc: hash function, or None for default
        - sigencode: signature encoding function (default sigencode_string)
        - k: int, specific k value for signature (for testing only)
        - allow_truncate: bool, allow hash truncation for curve compatibility

        Returns:
        bytes, encoded signature
        """

    def sign_deterministic(self, data, hashfunc=None, sigencode=sigencode_string, extra_entropy=b""):
        """
        Sign data using RFC 6979 deterministic ECDSA.

        Parameters:
        - data: bytes, data to sign
        - hashfunc: hash function, or None for default
        - sigencode: signature encoding function (default sigencode_string)
        - extra_entropy: bytes, additional entropy for deterministic generation

        Returns:
        bytes, encoded signature
        """

    def sign_digest(self, digest, entropy=None, sigencode=sigencode_string, k=None, allow_truncate=False):
        """
        Sign a pre-computed hash digest.

        Parameters:
        - digest: bytes, hash digest to sign
        - entropy: callable returning random bytes, or None for default
        - sigencode: signature encoding function (default sigencode_string)
        - k: int, specific k value for signature (for testing only)
        - allow_truncate: bool, allow hash truncation for curve compatibility

        Returns:
        bytes, encoded signature
        """

    def sign_digest_deterministic(self, digest, hashfunc=None, sigencode=sigencode_string, extra_entropy=b"", allow_truncate=False):
        """
        Sign a pre-computed hash digest using RFC 6979 deterministic ECDSA.

        Parameters:
        - digest: bytes, hash digest to sign
        - hashfunc: hash function used to create digest (required for RFC 6979)
        - sigencode: signature encoding function (default sigencode_string)
        - extra_entropy: bytes, additional entropy for deterministic generation
        - allow_truncate: bool, allow hash truncation for curve compatibility

        Returns:
        bytes, encoded signature  
        """

    def sign_number(self, number, entropy=None, k=None):
        """
        Sign a number directly (low-level interface).

        Parameters:
        - number: int, number to sign
        - entropy: callable returning random bytes, or None for default
        - k: int, specific k value for signature (for testing only)

        Returns:
        tuple[int, int], (r, s) signature pair
        """

Key Access and Export

def get_verifying_key(self):
        """
        Get the corresponding public key.

        Returns:
        VerifyingKey object
        """

    def to_string(self):
        """
        Export private key as raw bytes.

        Returns:
        bytes, raw private key
        """

    def to_pem(self, point_encoding="uncompressed", format="ssleay", curve_parameters_encoding=None):
        """
        Export private key in PEM format.

        Parameters:
        - point_encoding: str, point encoding format ("uncompressed", "compressed", "hybrid")
        - format: str, PEM format variant ("ssleay", "pkcs8")
        - curve_parameters_encoding: str or None, curve parameter encoding

        Returns:
        bytes, PEM-encoded private key
        """

    def to_der(self, point_encoding="uncompressed", format="ssleay", curve_parameters_encoding=None):
        """
        Export private key in DER format.

        Parameters:
        - point_encoding: str, point encoding format ("uncompressed", "compressed", "hybrid")
        - format: str, DER format variant ("ssleay", "pkcs8")
        - curve_parameters_encoding: str or None, curve parameter encoding

        Returns:
        bytes, DER-encoded private key
        """

    def to_ssh(self):
        """
        Export private key in SSH format.

        Returns:
        bytes, SSH-encoded private key
        """

Key Attributes

curve: Curve                 # The elliptic curve object
    default_hashfunc: callable   # Default hash function
    baselen: int                 # Length of raw key encoding in bytes
    verifying_key: VerifyingKey  # Associated public key

VerifyingKey Class

The VerifyingKey class represents a public key for verifying digital signatures created with ECDSA or EdDSA algorithms.

Key Loading and Creation

class VerifyingKey:
    @classmethod
    def from_public_point(cls, point, curve=NIST192p, hashfunc=sha1, validate_point=True):
        """
        Create VerifyingKey from elliptic curve point.

        Parameters:
        - point: Point object, public key point on curve
        - curve: Curve object (default NIST192p)
        - hashfunc: hash function for signatures (default sha1)
        - validate_point: bool, validate point is on curve

        Returns:
        VerifyingKey object
        """

    @classmethod
    def from_string(cls, string, curve=NIST192p, hashfunc=sha1, validate_point=True, valid_encodings=None):
        """
        Create VerifyingKey from raw byte string.

        Parameters:
        - string: bytes, raw public key bytes
        - curve: Curve object (default NIST192p)
        - hashfunc: hash function for signatures (default sha1)
        - validate_point: bool, validate point is on curve
        - valid_encodings: list of acceptable point encodings or None

        Returns:
        VerifyingKey object
        """

    @classmethod
    def from_pem(cls, string, hashfunc=sha1, valid_encodings=None, valid_curve_encodings=None):
        """
        Create VerifyingKey from PEM-encoded public key.

        Parameters:
        - string: str or bytes, PEM-encoded public key
        - hashfunc: hash function for signatures (default sha1)
        - valid_encodings: list of acceptable point encodings or None
        - valid_curve_encodings: list of acceptable curve encodings or None

        Returns:
        VerifyingKey object
        """

    @classmethod
    def from_der(cls, string, hashfunc=sha1, valid_encodings=None, valid_curve_encodings=None):
        """
        Create VerifyingKey from DER-encoded public key.

        Parameters:
        - string: bytes, DER-encoded public key
        - hashfunc: hash function for signatures (default sha1)
        - valid_encodings: list of acceptable point encodings or None
        - valid_curve_encodings: list of acceptable curve encodings or None

        Returns:
        VerifyingKey object
        """

    @classmethod
    def from_public_key_recovery(cls, signature, data, curve, hashfunc=sha1, sigdecode=sigdecode_string, allow_truncate=True):
        """
        Recover public key(s) from signature and original data.

        Parameters:
        - signature: bytes, encoded signature
        - data: bytes, original signed data
        - curve: Curve object
        - hashfunc: hash function used for signing (default sha1)
        - sigdecode: signature decoding function (default sigdecode_string)
        - allow_truncate: bool, allow hash truncation for curve compatibility

        Returns:
        list[VerifyingKey], possible public keys (usually 2 or 4 options)
        """

    @classmethod
    def from_public_key_recovery_with_digest(cls, signature, digest, curve, hashfunc=sha1, sigdecode=sigdecode_string, allow_truncate=False):
        """
        Recover public key(s) from signature and pre-computed digest.

        Parameters:
        - signature: bytes, encoded signature
        - digest: bytes, hash digest of original data
        - curve: Curve object
        - hashfunc: hash function used to create digest (default sha1)
        - sigdecode: signature decoding function (default sigdecode_string)
        - allow_truncate: bool, allow hash truncation for curve compatibility

        Returns:
        list[VerifyingKey], possible public keys (usually 2 or 4 options)
        """

Signature Verification

def verify(self, signature, data, hashfunc=None, sigdecode=sigdecode_string, allow_truncate=True):
        """
        Verify signature against data.

        Parameters:
        - signature: bytes, encoded signature to verify
        - data: bytes, original data that was signed
        - hashfunc: hash function, or None for default
        - sigdecode: signature decoding function (default sigdecode_string)
        - allow_truncate: bool, allow hash truncation for curve compatibility

        Returns:
        bool, True if signature is valid

        Raises:
        BadSignatureError: if signature is invalid
        """

    def verify_digest(self, signature, digest, sigdecode=sigdecode_string, allow_truncate=False):
        """
        Verify signature against pre-computed hash digest.

        Parameters:
        - signature: bytes, encoded signature to verify
        - digest: bytes, hash digest of original data
        - sigdecode: signature decoding function (default sigdecode_string)
        - allow_truncate: bool, allow hash truncation for curve compatibility

        Returns:
        bool, True if signature is valid

        Raises:
        BadSignatureError: if signature is invalid
        """

Key Export and Optimization

def precompute(self, lazy=False):
        """
        Precompute values for faster signature verification.

        Parameters:
        - lazy: bool, compute values lazily on first use
        """

    def to_string(self, encoding="raw"):
        """
        Export public key as raw bytes.

        Parameters:
        - encoding: str, point encoding format ("raw", "uncompressed", "compressed", "hybrid")

        Returns:
        bytes, encoded public key
        """

    def to_pem(self, point_encoding="uncompressed", curve_parameters_encoding=None):
        """
        Export public key in PEM format.

        Parameters:
        - point_encoding: str, point encoding format ("uncompressed", "compressed", "hybrid")
        - curve_parameters_encoding: str or None, curve parameter encoding

        Returns:
        bytes, PEM-encoded public key
        """

    def to_der(self, point_encoding="uncompressed", curve_parameters_encoding=None):
        """
        Export public key in DER format.

        Parameters:
        - point_encoding: str, point encoding format ("uncompressed", "compressed", "hybrid")
        - curve_parameters_encoding: str or None, curve parameter encoding

        Returns:
        bytes, DER-encoded public key
        """

    def to_ssh(self):
        """
        Export public key in SSH format.

        Returns:
        bytes, SSH-encoded public key
        """

Key Attributes

curve: Curve               # The elliptic curve object
    default_hashfunc: callable # Default hash function
    pubkey: object            # Internal public key object

Exception Classes

class BadSignatureError(Exception):
    """Raised when signature verification fails."""

class BadDigestError(Exception):
    """Raised when hash digest is too large for the curve."""

class MalformedPointError(Exception):
    """Raised when point encoding is invalid or point is not on curve."""

Usage Examples

Basic Key Generation and Signing

from ecdsa import SigningKey, NIST256p
import hashlib

# Generate a new signing key
sk = SigningKey.generate(curve=NIST256p)
vk = sk.verifying_key

# Sign some data
message = b"Hello, cryptographic world!"
signature = sk.sign(message, hashfunc=hashlib.sha256)

# Verify the signature
try:
    vk.verify(signature, message, hashfunc=hashlib.sha256)
    print("Signature verified successfully!")
except BadSignatureError:
    print("Signature verification failed!")

Deterministic Signatures (RFC 6979)

from ecdsa import SigningKey, NIST256p
import hashlib

sk = SigningKey.generate(curve=NIST256p)
message = b"Deterministic signing example"

# Create deterministic signature (same signature every time)
sig1 = sk.sign_deterministic(message, hashfunc=hashlib.sha256)
sig2 = sk.sign_deterministic(message, hashfunc=hashlib.sha256)
assert sig1 == sig2  # Signatures are identical

# Verify deterministic signature
vk = sk.verifying_key
vk.verify(sig1, message, hashfunc=hashlib.sha256)

Key Serialization and Loading

from ecdsa import SigningKey, VerifyingKey, NIST256p

# Generate key pair
sk = SigningKey.generate(curve=NIST256p)
vk = sk.verifying_key

# Export keys in various formats
private_pem = sk.to_pem()
public_pem = vk.to_pem()
private_der = sk.to_der()
public_der = vk.to_der()

# Load keys from serialized formats
loaded_sk = SigningKey.from_pem(private_pem)
loaded_vk = VerifyingKey.from_pem(public_pem)
loaded_sk_der = SigningKey.from_der(private_der)
loaded_vk_der = VerifyingKey.from_der(public_der)

# Verify they work the same
message = b"Test message"
original_sig = sk.sign(message)
loaded_sig = loaded_sk.sign(message)

# Both signatures should verify with both public keys
vk.verify(original_sig, message)
loaded_vk.verify(loaded_sig, message)

Multiple Signature Encodings

from ecdsa import SigningKey, NIST256p
from ecdsa.util import sigencode_der, sigdecode_der, sigencode_string, sigdecode_string

sk = SigningKey.generate(curve=NIST256p)
vk = sk.verifying_key
message = b"Encoding example"

# Sign with different encodings
sig_raw = sk.sign(message, sigencode=sigencode_string)
sig_der = sk.sign(message, sigencode=sigencode_der)

# Verify with corresponding decodings
vk.verify(sig_raw, message, sigdecode=sigdecode_string)
vk.verify(sig_der, message, sigdecode=sigdecode_der)

Install with Tessl CLI

npx tessl i tessl/pypi-ecdsa

docs

curves.md

ecdh.md

eddsa.md

encoding.md

index.md

keys-signatures.md

mathematical-functions.md

tile.json