Crate secp256k1

source ·
Expand description

Rust bindings for Pieter Wuille’s secp256k1 library, which is used for fast and accurate manipulation of ECDSA signatures on the secp256k1 curve. Such signatures are used extensively by the Bitcoin network and its derivatives.

To minimize dependencies, some functions are feature-gated. To generate random keys or to re-randomize a context object, compile with the rand-std feature. If you are willing to use the rand-std feature, we have enabled an additional defense-in-depth sidechannel protection for our context objects, which re-blinds certain operations on secret key data. To de/serialize objects with serde, compile with “serde”. Important: serde encoding is not the same as consensus encoding!

Where possible, the bindings use the Rust type system to ensure that API usage errors are impossible. For example, the library uses context objects that contain precomputation tables which are created on object construction. Since this is a slow operation (10+ milliseconds, vs ~50 microseconds for typical crypto operations, on a 2.70 Ghz i7-6820HQ) the tables are optional, giving a performance boost for users who only care about signing, only care about verification, or only care about parsing. In the upstream library, if you attempt to sign a message using a context that does not support this, it will trigger an assertion failure and terminate the program. In rust-secp256k1, this is caught at compile-time; in fact, it is impossible to compile code that will trigger any assertion failures in the upstream library.

use secp256k1::rand::rngs::OsRng;
use secp256k1::{Secp256k1, Message};
use secp256k1::hashes::{sha256, Hash};

let secp = Secp256k1::new();
let (secret_key, public_key) = secp.generate_keypair(&mut OsRng);
let digest = sha256::Hash::hash("Hello World!".as_bytes());
let message = Message::from_digest(digest.to_byte_array());

let sig = secp.sign_ecdsa(&message, &secret_key);
assert!(secp.verify_ecdsa(&message, &sig, &public_key).is_ok());

If the “global-context” feature is enabled you have access to an alternate API.

use secp256k1::{generate_keypair, Message};
use secp256k1::hashes::{sha256, Hash};

let (secret_key, public_key) = generate_keypair(&mut rand::thread_rng());
let digest = sha256::Hash::hash("Hello World!".as_bytes());
let message = Message::from_digest(digest.to_byte_array());

let sig = secret_key.sign_ecdsa(message);
assert!(sig.verify(&message, &public_key).is_ok());

The above code requires rust-secp256k1 to be compiled with the rand-std and hashes-std feature enabled, to get access to generate_keypair Alternately, keys and messages can be parsed from slices, like

use secp256k1::{Secp256k1, Message, SecretKey, PublicKey};

let secp = Secp256k1::new();
let secret_key = SecretKey::from_slice(&[0xcd; 32]).expect("32 bytes, within curve order");
let public_key = PublicKey::from_secret_key(&secp, &secret_key);
// This is unsafe unless the supplied byte slice is the output of a cryptographic hash function.
// See the above example for how to use this library together with `hashes-std`.
let message = Message::from_digest_slice(&[0xab; 32]).expect("32 bytes");

let sig = secp.sign_ecdsa(&message, &secret_key);
assert!(secp.verify_ecdsa(&message, &sig, &public_key).is_ok());

Users who only want to verify signatures can use a cheaper context, like so:

use secp256k1::{Secp256k1, Message, ecdsa, PublicKey};

let secp = Secp256k1::verification_only();

let public_key = PublicKey::from_slice(&[
    0x02,
    0xc6, 0x6e, 0x7d, 0x89, 0x66, 0xb5, 0xc5, 0x55,
    0xaf, 0x58, 0x05, 0x98, 0x9d, 0xa9, 0xfb, 0xf8,
    0xdb, 0x95, 0xe1, 0x56, 0x31, 0xce, 0x35, 0x8c,
    0x3a, 0x17, 0x10, 0xc9, 0x62, 0x67, 0x90, 0x63,
]).expect("public keys must be 33 or 65 bytes, serialized according to SEC 2");

let message = Message::from_digest_slice(&[
    0xaa, 0xdf, 0x7d, 0xe7, 0x82, 0x03, 0x4f, 0xbe,
    0x3d, 0x3d, 0xb2, 0xcb, 0x13, 0xc0, 0xcd, 0x91,
    0xbf, 0x41, 0xcb, 0x08, 0xfa, 0xc7, 0xbd, 0x61,
    0xd5, 0x44, 0x53, 0xcf, 0x6e, 0x82, 0xb4, 0x50,
]).expect("messages must be 32 bytes and are expected to be hashes");

let sig = ecdsa::Signature::from_compact(&[
    0xdc, 0x4d, 0xc2, 0x64, 0xa9, 0xfe, 0xf1, 0x7a,
    0x3f, 0x25, 0x34, 0x49, 0xcf, 0x8c, 0x39, 0x7a,
    0xb6, 0xf1, 0x6f, 0xb3, 0xd6, 0x3d, 0x86, 0x94,
    0x0b, 0x55, 0x86, 0x82, 0x3d, 0xfd, 0x02, 0xae,
    0x3b, 0x46, 0x1b, 0xb4, 0x33, 0x6b, 0x5e, 0xcb,
    0xae, 0xfd, 0x66, 0x27, 0xaa, 0x92, 0x2e, 0xfc,
    0x04, 0x8f, 0xec, 0x0c, 0x88, 0x1c, 0x10, 0xc4,
    0xc9, 0x42, 0x8f, 0xca, 0x69, 0xc1, 0x32, 0xa2,
]).expect("compact signatures are 64 bytes; DER signatures are 68-72 bytes");

assert!(secp.verify_ecdsa(&message, &sig, &public_key).is_ok());

Observe that the same code using, say signing_only to generate a context would simply not compile.

§Crate features/optional dependencies

This crate provides the following opt-in Cargo features:

  • std - use standard Rust library, enabled by default.
  • alloc - use the alloc standard Rust library to provide heap allocations.
  • rand - use rand library to provide random generator (e.g. to generate keys).
  • rand-std - use rand library with its std feature enabled. (Implies rand.)
  • hashes - use the hashes library.
  • hashes-std - use the hashes library with its std feature enabled (implies hashes).
  • recovery - enable functions that can compute the public key from signature.
  • lowmemory - optimize the library for low-memory environments.
  • global-context - enable use of global secp256k1 context (implies std).
  • serde - implements serialization and deserialization for types in this crate using serde. Important: serde encoding is not the same as consensus encoding!

Re-exports§

Modules§

  • Constants related to the API and the underlying curve.
  • Support for shared secret computations.
  • Structs and functionality related to the ECDSA signature algorithm.
  • This module provides an implementation of ElligatorSwift as well as a version of x-only ECDH using it (including compatibility with BIP324).
  • globalglobal-context and std
    Module implementing a singleton pattern for a global Secp256k1 context.
  • Provides Scalar and related types.
  • Support for schnorr signatures.

Macros§

Structs§

  • Represents the set of all capabilities (preallocated memory).
  • Error returned when conversion from an integer to Parity fails.
  • Opaque data structure that holds a keypair consisting of a secret and a public key.
  • A (hashed) message input to an ECDSA signature.
  • Public key - used to verify ECDSA signatures and to do Taproot tweaks.
  • The secp256k1 engine, used to execute all signature operations.
  • Secret key - a 256-bit key used to create ECDSA and Taproot signatures.
  • Represents the set of capabilities needed for signing (preallocated memory).
  • Represents the set of capabilities needed for verification (preallocated memory).
  • An x-only public key, used for verification of Taproot signatures and serialized according to BIP-340.

Enums§

  • Allalloc
    Represents the set of all capabilities.
  • The main error type for this library.
  • Represents the parity passed between FFI function calls.
  • Represents the set of capabilities needed for signing.
  • Represents the set of capabilities needed for verification.

Statics§

  • SECP256K1global-context and std
    A global static context to avoid repeatedly creating contexts.

Traits§

  • A trait for all kinds of contexts that lets you define the exact flags and a function to deallocate memory. It isn’t possible to implement this for types outside this crate.
  • Trait marking that a particular context object internally points to memory that must outlive 'a
  • Marker trait for indicating that an instance of Secp256k1 can be used for signing.
  • Trait describing something that promises to be a 32-byte random number; in particular, it has negligible probability of being zero or overflowing the group order. Such objects may be converted to Messages without any error paths.
  • Marker trait for indicating that an instance of Secp256k1 can be used for verification.

Functions§