libcrypto.secp256k1

Pure-Python secp256k1 elliptic-curve operations. Public key derivation uses a precomputed fixed-base comb table, so k*G is a sum of point additions with no doublings.

Functions

private_key_to_public_key(private_key, compressed=True) -> bytes

Derive a public key from a private key integer in [1, N-1]. Returns a 33-byte compressed key (prefix 0x02/0x03) or a 65-byte uncompressed key (prefix 0x04). Raises Secp256k1Error for out-of-range keys.

public_key_to_point_coords(public_key) -> tuple[int, int]

Convert a compressed or uncompressed public key to affine (x, y) coordinates, verifying the point is on the curve.

compress_public_key(public_key) -> bytes

Return the 33-byte compressed form of any public key.

decompress_public_key(public_key) -> bytes

Return the 65-byte uncompressed form of any public key.

Exceptions

Exception Meaning
Secp256k1Error Invalid key range, malformed public key, or off-curve point (subclass of ValueError).

Example

from libcrypto.secp256k1 import (
    private_key_to_public_key, public_key_to_point_coords,
    compress_public_key, decompress_public_key,
)

pub = private_key_to_public_key(1, compressed=True)
assert pub.hex() == \
    "0279be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798"

x, y = public_key_to_point_coords(pub)
assert decompress_public_key(pub) == b"\x04" + x.to_bytes(32, "big") + y.to_bytes(32, "big")

Performance

The fixed-base comb table (64 nibble positions × 16 values) is built once and cached on first use. After warm-up, deterministic public-key derivation is several times faster than the previous double-and-add window while producing identical output. This benefits batch/scanning workloads where many keys are derived in a loop.

The internal helpers _scalar_multiply_base(k) (fast k*G) and _point_multiply(k, x, y) (general k*P) are reused by the signing and bip32 modules.