README.md (9145B)
1 # secp256k1 2 3 [](https://hackage.haskell.org/package/ppad-secp256k1) 4  5 [](https://docs.ppad.tech/secp256k1) 6 7 A pure Haskell implementation of [BIP0340][bp340] Schnorr signatures, 8 deterministic [RFC6979][r6979] ECDSA (with [BIP0146][bp146]-style 9 "low-S" signatures), ECDH, and various primitives on the elliptic curve 10 secp256k1. 11 12 (See also [ppad-csecp256k1][csecp] for FFI bindings to 13 bitcoin-core/secp256k1.) 14 15 ## Usage 16 17 A sample GHCi session: 18 19 ``` 20 > -- pragmas and b16 import for illustration only; not required 21 > :set -XOverloadedStrings 22 > :set -XBangPatterns 23 > import qualified Data.ByteString.Base16 as B16 24 > 25 > -- import qualified 26 > import qualified Crypto.Curve.Secp256k1 as Secp256k1 27 > 28 > -- secret, public keys 29 > let sec = 0xB7E151628AED2A6ABF7158809CF4F3C762E7160F38B4DA56A784D9045190CFEF 30 :{ 31 ghci| let Just pub = Secp256k1.parse_point . B16.decodeLenient $ 32 ghci| "DFF1D77F2A671C5F36183726DB2341BE58FEAE1DA2DECED843240F7B502BA659" 33 ghci| :} 34 > 35 > let msg = "i approve of this message" 36 > 37 > -- create and verify a schnorr signature for the message 38 > let Just sig0 = Secp256k1.sign_schnorr sec msg mempty 39 > Secp256k1.verify_schnorr msg pub sig0 40 True 41 > 42 > -- create and verify a low-S ECDSA signature for the message 43 > let Just sig1 = Secp256k1.sign_ecdsa sec msg 44 > Secp256k1.verify_ecdsa msg pub sig1 45 True 46 > 47 > -- for faster signs (especially w/ECDSA) and verifies, use a context 48 > let !tex = Secp256k1.precompute 49 > Secp256k1.verify_schnorr' tex msg pub sig0 50 True 51 ``` 52 53 ## Documentation 54 55 Haddocks (API documentation, etc.) are hosted at 56 [docs.ppad.tech/secp256k1][hadoc]. 57 58 ## Performance 59 60 The aim is best-in-class performance for pure, highly-auditable Haskell 61 code. 62 63 Current benchmark figures on an M4 MacBook Air look like (use `cabal 64 bench` to run the benchmark suite): 65 66 ``` 67 benchmarking schnorr/sign_schnorr' (large) 68 time 1.400 ms (1.399 ms .. 1.402 ms) 69 1.000 R² (1.000 R² .. 1.000 R²) 70 mean 1.406 ms (1.404 ms .. 1.408 ms) 71 std dev 5.989 μs (5.225 μs .. 7.317 μs) 72 73 benchmarking schnorr/verify_schnorr' 74 time 720.2 μs (716.7 μs .. 724.8 μs) 75 1.000 R² (1.000 R² .. 1.000 R²) 76 mean 724.6 μs (722.0 μs .. 730.4 μs) 77 std dev 12.68 μs (6.334 μs .. 26.31 μs) 78 79 benchmarking ecdsa/sign_ecdsa' (large) 80 time 115.3 μs (115.1 μs .. 115.7 μs) 81 1.000 R² (1.000 R² .. 1.000 R²) 82 mean 116.0 μs (115.6 μs .. 116.4 μs) 83 std dev 1.367 μs (1.039 μs .. 1.839 μs) 84 85 benchmarking ecdsa/verify_ecdsa' 86 time 702.3 μs (699.9 μs .. 704.9 μs) 87 1.000 R² (1.000 R² .. 1.000 R²) 88 mean 704.9 μs (702.7 μs .. 708.4 μs) 89 std dev 9.641 μs (6.638 μs .. 14.04 μs) 90 ``` 91 92 In terms of allocations, we get: 93 94 ``` 95 schnorr 96 97 Case Allocated GCs 98 sign_schnorr' 3,273,824 0 99 verify_schnorr' 1,667,360 0 100 101 ecdsa 102 103 Case Allocated GCs 104 sign_ecdsa' 324,672 0 105 verify_ecdsa' 3,796,328 0 106 107 ecdh 108 109 Case Allocated GCs 110 ecdh (small) 2,141,736 0 111 ecdh (large) 2,145,464 0 112 ``` 113 114 ## Security 115 116 This library aims at the maximum security achievable in a 117 garbage-collected language under an optimizing compiler such as GHC, in 118 which strict constant-timeness can be [challenging to achieve][const]. 119 120 The Schnorr implementation within has been tested against the [official 121 BIP0340 vectors][ut340], and ECDSA and ECDH have been tested against 122 the relevant [Wycheproof vectors][wyche], so their implementations 123 are likely to be accurate and safe from attacks targeting e.g. faulty 124 nonce generation or malicious inputs for signature or public key 125 parameters. Timing-sensitive operations, e.g. elliptic curve scalar 126 multiplication, have been explicitly written so as to execute 127 *algorithmically* in time constant with respect to secret data, and 128 evidence from benchmarks supports this: 129 130 ``` 131 benchmarking derive_pub/wnaf, sk = 2 132 time 76.20 μs (75.62 μs .. 77.33 μs) 133 0.999 R² (0.998 R² .. 1.000 R²) 134 mean 75.87 μs (75.61 μs .. 76.48 μs) 135 std dev 1.218 μs (614.3 ns .. 2.291 μs) 136 variance introduced by outliers: 11% (moderately inflated) 137 138 benchmarking derive_pub/wnaf, sk = 2 ^ 255 - 19 139 time 76.50 μs (75.88 μs .. 77.37 μs) 140 0.999 R² (0.998 R² .. 1.000 R²) 141 mean 76.26 μs (75.99 μs .. 76.93 μs) 142 std dev 1.317 μs (570.7 ns .. 2.583 μs) 143 variance introduced by outliers: 12% (moderately inflated) 144 145 benchmarking schnorr/sign_schnorr' (small) 146 time 1.430 ms (1.424 ms .. 1.438 ms) 147 1.000 R² (1.000 R² .. 1.000 R²) 148 mean 1.429 ms (1.425 ms .. 1.433 ms) 149 std dev 13.71 μs (10.48 μs .. 18.85 μs) 150 151 benchmarking schnorr/sign_schnorr' (large) 152 time 1.400 ms (1.399 ms .. 1.402 ms) 153 1.000 R² (1.000 R² .. 1.000 R²) 154 mean 1.406 ms (1.404 ms .. 1.408 ms) 155 std dev 5.989 μs (5.225 μs .. 7.317 μs) 156 157 benchmarking ecdsa/sign_ecdsa' (small) 158 time 114.5 μs (114.0 μs .. 115.3 μs) 159 1.000 R² (0.999 R² .. 1.000 R²) 160 mean 115.2 μs (114.8 μs .. 115.8 μs) 161 std dev 1.650 μs (1.338 μs .. 2.062 μs) 162 163 benchmarking ecdsa/sign_ecdsa' (large) 164 time 115.3 μs (115.1 μs .. 115.7 μs) 165 1.000 R² (1.000 R² .. 1.000 R²) 166 mean 116.0 μs (115.6 μs .. 116.4 μs) 167 std dev 1.367 μs (1.039 μs .. 1.839 μs) 168 169 benchmarking ecdh/ecdh (small) 170 time 907.0 μs (902.8 μs .. 912.0 μs) 171 1.000 R² (0.999 R² .. 1.000 R²) 172 mean 909.5 μs (907.0 μs .. 913.0 μs) 173 std dev 10.05 μs (6.943 μs .. 17.11 μs) 174 175 benchmarking ecdh/ecdh (large) 176 time 922.9 μs (911.0 μs .. 937.4 μs) 177 0.999 R² (0.998 R² .. 1.000 R²) 178 mean 915.8 μs (911.9 μs .. 922.5 μs) 179 std dev 16.84 μs (9.830 μs .. 26.48 μs) 180 ``` 181 182 Due to the use of arbitrary-precision integers, integer division modulo 183 the elliptic curve group order does display persistent substantial 184 timing differences on the order of 1-2 nanoseconds when the inputs 185 differ dramatically in size (here 2 bits vs 255 bits): 186 187 ``` 188 benchmarking remQ (remainder modulo _CURVE_Q)/remQ 2 189 time 11.13 ns (11.12 ns .. 11.14 ns) 190 1.000 R² (1.000 R² .. 1.000 R²) 191 mean 11.10 ns (11.09 ns .. 11.11 ns) 192 std dev 33.75 ps (30.27 ps .. 38.31 ps) 193 194 benchmarking remQ (remainder modulo _CURVE_Q)/remQ (2 ^ 255 - 19) 195 time 12.50 ns (12.49 ns .. 12.51 ns) 196 1.000 R² (1.000 R² .. 1.000 R²) 197 mean 12.51 ns (12.51 ns .. 12.52 ns) 198 std dev 26.72 ps (14.45 ps .. 45.87 ps) 199 ``` 200 201 This represents the worst-case scenario (real-world private keys will 202 never differ so extraordinarily) and is likely to be well within 203 acceptable limits for all but the most extreme security requirements. 204 But because we don't make "hard" guarantees of constant-time execution, 205 take reasonable security precautions as appropriate. You shouldn't 206 deploy the implementations within in any situation where they could 207 easily be used as an oracle to construct a [timing attack][timea], 208 and you shouldn't give sophisticated malicious actors [access to your 209 computer][flurl]. 210 211 If you discover any vulnerabilities, please disclose them via 212 security@ppad.tech. 213 214 ## Development 215 216 You'll require [Nix][nixos] with [flake][flake] support enabled. Enter a 217 development shell with: 218 219 ``` 220 $ nix develop 221 ``` 222 223 Then do e.g.: 224 225 ``` 226 $ cabal repl ppad-secp256k1 227 ``` 228 229 to get a REPL for the main library. 230 231 [bp340]: https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki 232 [ut340]: https://github.com/bitcoin/bips/blob/master/bip-0340/test-vectors.csv 233 [bp146]: https://github.com/bitcoin/bips/blob/master/bip-0146.mediawiki 234 [r6979]: https://www.rfc-editor.org/rfc/rfc6979 235 [nixos]: https://nixos.org/ 236 [flake]: https://nixos.org/manual/nix/unstable/command-ref/new-cli/nix3-flake.html 237 [hadoc]: https://docs.ppad.tech/secp256k1 238 [wyche]: https://github.com/C2SP/wycheproof 239 [timea]: https://en.wikipedia.org/wiki/Timing_attack 240 [flurl]: https://eprint.iacr.org/2014/140.pdf 241 [const]: https://www.chosenplaintext.ca/articles/beginners-guide-constant-time-cryptography.html 242 [csecp]: https://git.ppad.tech/csecp256k1