BSV.Crypto.ECDSA (bsv_sdk v2.0.1)

Copy Markdown View Source

Pure-Elixir ECDSA signing on secp256k1 with RFC 6979 deterministic nonces.

Security Note — Timing Side-Channel

The scalar multiplication uses a standard double-and-add algorithm that is not constant-time. The BEAM's non-deterministic scheduling provides incidental protection, but this should not be relied upon for HSM-grade or hardware-adjacent signing. For high-value use cases, consider a NIF wrapping libsecp256k1 which provides constant-time scalar multiplication.

This implementation is suitable for application-layer Bitcoin signing.

Summary

Functions

EC point addition on secp256k1.

EC point doubling on secp256k1.

EC point multiplication (double-and-add) on secp256k1.

DER-encode an ECDSA signature from r, s integers.

Encode an integer as a DER integer (with leading 0x00 if high bit set).

Modular inverse using extended Euclidean algorithm.

Sign a 32-byte hash with a 32-byte private key. Returns {:ok, der_binary}.

ECDSA sign with given k, private key integer, hash integer. Returns {r, s} with low-S.

Functions

ec_point_add(p, p)

EC point addition on secp256k1.

ec_point_double(arg1)

EC point doubling on secp256k1.

ec_point_mul(k, point)

EC point multiplication (double-and-add) on secp256k1.

encode_der(r, s)

@spec encode_der(integer(), integer()) :: binary()

DER-encode an ECDSA signature from r, s integers.

encode_der_integer(n)

@spec encode_der_integer(integer()) :: binary()

Encode an integer as a DER integer (with leading 0x00 if high bit set).

mod_inverse(a, m)

Modular inverse using extended Euclidean algorithm.

sign(arg1, arg2)

@spec sign(binary(), binary()) :: {:ok, binary()}

Sign a 32-byte hash with a 32-byte private key. Returns {:ok, der_binary}.

sign_with_k(k, d, z)

@spec sign_with_k(integer(), integer(), integer()) :: {integer(), integer()}

ECDSA sign with given k, private key integer, hash integer. Returns {r, s} with low-S.