{"id":26933539,"url":"https://github.com/ppad-tech/secp256k1","last_synced_at":"2025-04-02T09:19:32.034Z","repository":{"id":261557526,"uuid":"884225852","full_name":"ppad-tech/secp256k1","owner":"ppad-tech","description":"Pure Haskell Schnorr, ECDSA, ECDH on the elliptic curve secp256k1","archived":false,"fork":false,"pushed_at":"2025-03-14T11:03:32.000Z","size":628,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-14T11:25:39.916Z","etag":null,"topics":["ecdh","ecdsa","elliptic-curve-cryptography","haskell","schnorr","secp256k1"],"latest_commit_sha":null,"homepage":"","language":"Haskell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ppad-tech.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-11-06T11:27:17.000Z","updated_at":"2025-03-14T11:03:36.000Z","dependencies_parsed_at":"2024-11-07T07:37:42.612Z","dependency_job_id":"656429b6-9426-466b-8310-0cdb621be7a3","html_url":"https://github.com/ppad-tech/secp256k1","commit_stats":null,"previous_names":["ppad-tech/secp256k1"],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ppad-tech%2Fsecp256k1","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ppad-tech%2Fsecp256k1/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ppad-tech%2Fsecp256k1/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ppad-tech%2Fsecp256k1/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ppad-tech","download_url":"https://codeload.github.com/ppad-tech/secp256k1/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246785456,"owners_count":20833498,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ecdh","ecdsa","elliptic-curve-cryptography","haskell","schnorr","secp256k1"],"created_at":"2025-04-02T09:19:31.509Z","updated_at":"2025-04-02T09:19:32.020Z","avatar_url":"https://github.com/ppad-tech.png","language":"Haskell","funding_links":[],"categories":[],"sub_categories":[],"readme":"# secp256k1\n\n[![](https://img.shields.io/hackage/v/ppad-secp256k1?color=blue)](https://hackage.haskell.org/package/ppad-secp256k1)\n![](https://img.shields.io/badge/license-MIT-brightgreen)\n[![](https://img.shields.io/badge/haddock-secp256k1-lightblue)](https://docs.ppad.tech/secp256k1)\n\nA pure Haskell implementation of [BIP0340][bp340] Schnorr signatures,\ndeterministic [RFC6979][r6979] ECDSA (with [BIP0146][bp146]-style\n\"low-S\" signatures), ECDH, and various primitives on the elliptic curve\nsecp256k1.\n\n(See also [ppad-csecp256k1][csecp] for FFI bindings to\nbitcoin-core/secp256k1.)\n\n## Usage\n\nA sample GHCi session:\n\n```\n  \u003e -- pragmas and b16 import for illustration only; not required\n  \u003e :set -XOverloadedStrings\n  \u003e :set -XBangPatterns\n  \u003e import qualified Data.ByteString.Base16 as B16\n  \u003e\n  \u003e -- import qualified\n  \u003e import qualified Crypto.Curve.Secp256k1 as Secp256k1\n  \u003e\n  \u003e -- secret, public keys\n  \u003e let sec = 0xB7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF\n  :{\n  ghci| let Just pub = Secp256k1.parse_point . B16.decodeLenient $\n  ghci|       \"DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659\"\n  ghci| :}\n  \u003e\n  \u003e let msg = \"i approve of this message\"\n  \u003e\n  \u003e -- create and verify a schnorr signature for the message\n  \u003e let sig0 = Secp256k1.sign_schnorr sec msg mempty\n  \u003e Secp256k1.verify_schnorr msg pub sig0\n  True\n  \u003e\n  \u003e -- create and verify a low-S ECDSA signature for the message\n  \u003e let sig1 = Secp256k1.sign_ecdsa sec msg\n  \u003e Secp256k1.verify_ecdsa msg pub sig1\n  True\n  \u003e\n  \u003e -- for faster signs (especially w/ECDSA) and verifies, use a context\n  \u003e let !tex = Secp256k1.precompute\n  \u003e Secp256k1.verify_schnorr' tex msg pub sig0\n  True\n```\n\n## Documentation\n\nHaddocks (API documentation, etc.) are hosted at\n[docs.ppad.tech/secp256k1][hadoc].\n\n## Performance\n\nThe aim is best-in-class performance for pure, highly-auditable Haskell\ncode.\n\nCurrent benchmark figures on a relatively-beefy NixOS VPS look like\n(use `cabal bench` to run the benchmark suite):\n\n```\n  benchmarking schnorr/sign_schnorr'\n  time                 2.584 ms   (2.491 ms .. 2.646 ms)\n                       0.994 R²   (0.991 R² .. 0.997 R²)\n  mean                 2.459 ms   (2.426 ms .. 2.492 ms)\n  std dev              114.5 μs   (95.32 μs .. 142.8 μs)\n\n  benchmarking schnorr/verify_schnorr'\n  time                 1.283 ms   (1.263 ms .. 1.301 ms)\n                       0.999 R²   (0.998 R² .. 0.999 R²)\n  mean                 1.273 ms   (1.260 ms .. 1.284 ms)\n  std dev              41.56 μs   (31.12 μs .. 54.35 μs)\n\n  benchmarking ecdsa/sign_ecdsa'\n  time                 222.6 μs   (219.9 μs .. 224.9 μs)\n                       0.999 R²   (0.999 R² .. 1.000 R²)\n  mean                 219.1 μs   (217.8 μs .. 220.5 μs)\n  std dev              4.523 μs   (3.525 μs .. 6.158 μs)\n\n  benchmarking ecdsa/verify_ecdsa'\n  time                 1.267 ms   (1.260 ms .. 1.276 ms)\n                       1.000 R²   (1.000 R² .. 1.000 R²)\n  mean                 1.278 ms   (1.273 ms .. 1.286 ms)\n  std dev              21.32 μs   (15.43 μs .. 30.82 μs)\n```\n\nIn terms of allocations, we get:\n\n```\nschnorr\n\n  Case                   Allocated  GCs\n  sign_schnorr'          3,273,824    0\n  verify_schnorr'        1,667,360    0\n\necdsa\n\n  Case                 Allocated  GCs\n  sign_ecdsa'            324,672    0\n  verify_ecdsa'        3,796,328    0\n\necdh\n\n  Case          Allocated  GCs\n  ecdh (small)  2,141,736    0\n  ecdh (large)  2,145,464    0\n```\n\n## Security\n\nThis library aims at the maximum security achievable in a\ngarbage-collected language under an optimizing compiler such as GHC, in\nwhich strict constant-timeness can be [challenging to achieve][const].\n\nThe Schnorr implementation within has been tested against the [official\nBIP0340 vectors][ut340], and ECDSA and ECDH have been tested against\nthe relevant [Wycheproof vectors][wyche], so their implementations\nare likely to be accurate and safe from attacks targeting e.g. faulty\nnonce generation or malicious inputs for signature or public key\nparameters. Timing-sensitive operations, e.g. elliptic curve scalar\nmultiplication, have been explicitly written so as to execute\n*algorithmically* in time constant with respect to secret data, and\nevidence from benchmarks supports this:\n\n```\n  benchmarking derive_pub/sk = 2\n  time                 1.513 ms   (1.468 ms .. 1.565 ms)\n                       0.994 R²   (0.991 R² .. 0.997 R²)\n  mean                 1.579 ms   (1.557 ms .. 1.600 ms)\n  std dev              74.25 μs   (60.33 μs .. 93.80 μs)\n\n  benchmarking derive_pub/sk = 2 ^ 255 - 19\n  time                 1.571 ms   (1.530 ms .. 1.599 ms)\n                       0.997 R²   (0.995 R² .. 0.998 R²)\n  mean                 1.574 ms   (1.553 ms .. 1.589 ms)\n  std dev              57.72 μs   (45.29 μs .. 71.48 μs)\n\n  benchmarking schnorr/sign_schnorr' (small)\n  time                 2.436 ms   (2.357 ms .. 2.516 ms)\n                       0.995 R²   (0.994 R² .. 0.998 R²)\n  mean                 2.563 ms   (2.532 ms .. 2.588 ms)\n  std dev              95.87 μs   (71.98 μs .. 127.2 μs)\n\n  benchmarking schnorr/sign_schnorr' (large)\n  time                 2.470 ms   (2.372 ms .. 2.543 ms)\n                       0.993 R²   (0.989 R² .. 0.997 R²)\n  mean                 2.407 ms   (2.374 ms .. 2.443 ms)\n  std dev              123.7 μs   (110.7 μs .. 144.9 μs)\n\n  benchmarking ecdsa/sign_ecdsa' (small)\n  time                 206.9 μs   (202.7 μs .. 211.8 μs)\n                       0.997 R²   (0.996 R² .. 0.999 R²)\n  mean                 213.8 μs   (211.5 μs .. 215.9 μs)\n  std dev              7.476 μs   (5.572 μs .. 9.698 μs)\n\n  benchmarking ecdsa/sign_ecdsa' (large)\n  time                 216.7 μs   (211.6 μs .. 221.7 μs)\n                       0.997 R²   (0.995 R² .. 0.999 R²)\n  mean                 221.8 μs   (219.5 μs .. 224.1 μs)\n  std dev              7.673 μs   (6.124 μs .. 10.69 μs)\n\n  benchmarking ecdh/ecdh (small)\n  time                 1.623 ms   (1.605 ms .. 1.639 ms)\n                       0.999 R²   (0.998 R² .. 1.000 R²)\n  mean                 1.617 ms   (1.603 ms .. 1.624 ms)\n  std dev              32.52 μs   (20.66 μs .. 55.97 μs)\n\n  benchmarking ecdh/ecdh (large)\n  time                 1.623 ms   (1.580 ms .. 1.661 ms)\n                       0.996 R²   (0.992 R² .. 0.998 R²)\n  mean                 1.625 ms   (1.606 ms .. 1.641 ms)\n  std dev              58.38 μs   (44.31 μs .. 78.23 μs)\n```\n\nDue to the use of arbitrary-precision integers, integer division modulo\nthe elliptic curve group order does display persistent substantial\ntiming differences on the order of 2 nanoseconds when the inputs differ\ndramatically in size (here 2 bits vs 255 bits):\n\n```\n  benchmarking remQ (remainder modulo _CURVE_Q)/remQ 2\n  time                 27.44 ns   (27.19 ns .. 27.72 ns)\n                       1.000 R²   (0.999 R² .. 1.000 R²)\n  mean                 27.23 ns   (27.03 ns .. 27.43 ns)\n  std dev              669.1 ps   (539.9 ps .. 860.2 ps)\n\n  benchmarking remQ (remainder modulo _CURVE_Q)/remQ (2 ^ 255 - 19)\n  time                 29.11 ns   (28.87 ns .. 29.33 ns)\n                       0.999 R²   (0.999 R² .. 1.000 R²)\n  mean                 29.04 ns   (28.82 ns .. 29.40 ns)\n  std dev              882.9 ps   (647.8 ps .. 1.317 ns)\n```\n\nThis represents the worst-case scenario (real-world private keys will\nnever differ so extraordinarily) and is likely to be well within\nacceptable limits for all but the most extreme security requirements.\nBut because we don't make \"hard\" guarantees of constant-time execution,\ntake reasonable security precautions as appropriate. You shouldn't\ndeploy the implementations within in any situation where they could\neasily be used as an oracle to construct a [timing attack][timea],\nand you shouldn't give sophisticated malicious actors [access to your\ncomputer][flurl].\n\nIf you discover any vulnerabilities, please disclose them via\nsecurity@ppad.tech.\n\n## Development\n\nYou'll require [Nix][nixos] with [flake][flake] support enabled. Enter a\ndevelopment shell with:\n\n```\n$ nix develop\n```\n\nThen do e.g.:\n\n```\n$ cabal repl ppad-secp256k1\n```\n\nto get a REPL for the main library.\n\n[bp340]: https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki\n[ut340]: https://github.com/bitcoin/bips/blob/master/bip-0340/test-vectors.csv\n[bp146]: https://github.com/bitcoin/bips/blob/master/bip-0146.mediawiki\n[r6979]: https://www.rfc-editor.org/rfc/rfc6979\n[nixos]: https://nixos.org/\n[flake]: https://nixos.org/manual/nix/unstable/command-ref/new-cli/nix3-flake.html\n[hadoc]: https://docs.ppad.tech/secp256k1\n[wyche]: https://github.com/C2SP/wycheproof\n[timea]: https://en.wikipedia.org/wiki/Timing_attack\n[flurl]: https://eprint.iacr.org/2014/140.pdf\n[const]: https://www.chosenplaintext.ca/articles/beginners-guide-constant-time-cryptography.html\n[csecp]: https://git.ppad.tech/csecp256k1\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fppad-tech%2Fsecp256k1","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fppad-tech%2Fsecp256k1","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fppad-tech%2Fsecp256k1/lists"}