Skip to content

ppad-tech/csecp256k1

Repository files navigation

ppad-csecp256k1

Bindings to bitcoin-core/secp256k1, which provides digital signatures and other cryptographic primitives on the secp256k1 elliptic curve.

This library exposes a minimal subset of the underlying library, mainly supporting ECDSA/Schnorr signatures and ECDH secret computation, as well as utilities for public key manipulation.

For a pure Haskell secp256k1 implementation, see ppad-secp256k1.

Documentation

API documentation and examples are hosted at docs.ppad.tech/csecp256k1.

Performance

As we bind to libsecp256k1, the resulting functions are very fast:

  benchmarking csecp256k1/ecdsa/sign
  time                 13.31 μs   (13.30 μs .. 13.31 μs)
                       1.000 R²   (1.000 R² .. 1.000 R²)
  mean                 13.33 μs   (13.32 μs .. 13.33 μs)
  std dev              11.15 ns   (8.932 ns .. 15.01 ns)

  benchmarking csecp256k1/ecdsa/verify
  time                 12.35 μs   (12.34 μs .. 12.38 μs)
                       1.000 R²   (1.000 R² .. 1.000 R²)
  mean                 12.35 μs   (12.35 μs .. 12.36 μs)
  std dev              21.83 ns   (9.273 ns .. 47.76 ns)

  benchmarking csecp256k1/schnorr/sign
  time                 18.35 μs   (18.35 μs .. 18.36 μs)
                       1.000 R²   (1.000 R² .. 1.000 R²)
  mean                 18.35 μs   (18.35 μs .. 18.35 μs)
  std dev              5.990 ns   (4.283 ns .. 9.131 ns)

  benchmarking csecp256k1/schnorr/verify
  time                 14.15 μs   (14.14 μs .. 14.15 μs)
                       1.000 R²   (1.000 R² .. 1.000 R²)
  mean                 14.14 μs   (14.13 μs .. 14.15 μs)
  std dev              30.51 ns   (14.54 ns .. 57.66 ns)

  benchmarking csecp256k1/ecdh/ecdh
  time                 15.02 μs   (15.02 μs .. 15.03 μs)
                       1.000 R²   (1.000 R² .. 1.000 R²)
  mean                 15.02 μs   (15.00 μs .. 15.03 μs)
  std dev              34.78 ns   (10.81 ns .. 71.53 ns)

Security

These bindings aim at the maximum security achievable in a garbage-collected language under an optimizing compiler such as GHC, in which strict constant-timeness can be challenging to achieve.

The Schnorr implementation within has been tested against the official BIP0340 vectors (sans those using arbitrary-size messages, which we're not at present supporting), and ECDSA has been tested against the relevant Wycheproof vectors.

If you discover any vulnerabilities, please disclose them via security@ppad.tech.

Development

You'll require Nix with flake support enabled. Enter a development shell with:

$ nix develop

Then do e.g.:

$ cabal repl ppad-csecp256k1

to get a REPL for the main library, or:

$ cabal repl secp256k1-sys-tests

to get one for the internal test suite. You can run all tests via:

$ cabal test

and the benchmarks via:

$ cabal bench

Attribution

This implementation has benefited greatly and uses modified versions of code from both secp256k1-haskell (test cases, FFI/bytestring manipulation) and rust-secp256k1 (dependency vendoring).