Audited & minimal JS implementation of elliptic curve cryptography.
Go to file
2022-12-15 23:11:40 +01:00
.github Initial commit 2022-12-04 18:19:01 +01:00
curve-definitions Todo in stark 2022-12-15 22:52:46 +01:00
lib/esm Initial commit 2022-12-04 18:19:01 +01:00
src Add modular division 2022-12-15 23:11:40 +01:00
.gitignore Initial commit 2022-12-04 18:19:01 +01:00
.prettierrc.json Initial commit 2022-12-04 18:19:01 +01:00
index.js Initial commit 2022-12-04 18:19:01 +01:00
LICENSE Initial commit 2022-12-04 18:19:01 +01:00
package.json Release 0.2.0. 2022-12-15 22:42:30 +01:00
README.md Add modular division 2022-12-15 23:11:40 +01:00
tsconfig.esm.json Initial commit 2022-12-04 18:19:01 +01:00
tsconfig.json Initial commit 2022-12-04 18:19:01 +01:00

noble-curves

Minimal, zero-dependency JS implementation of elliptic curve cryptography.

  • Short Weierstrass curve with ECDSA signatures
  • Twisted Edwards curve with EdDSA signatures
  • Montgomery curve for ECDH key agreement

To keep the package minimal, no curve definitions are provided out-of-box. Use micro-curve-definitions module:

  • It provides P192, P224, P256, P384, P521, secp256k1, stark curve, bn254, pasta (pallas/vesta) short weierstrass curves
  • It also provides ed25519 and ed448 twisted edwards curves
  • Main reason for separate package is the fact hashing library (like @noble/hashes) is required for full functionality
  • We may reconsider merging packages in future, when a stable version would be ready

Future plans:

  • hash to curve standard
  • point indistinguishability
  • pairings

This library belongs to noble crypto

noble-crypto — high-security, easily auditable set of contained cryptographic libraries and tools.

  • No dependencies, small files
  • Easily auditable TypeScript/JS code
  • Supported in all major browsers and stable node.js versions
  • All releases are signed with PGP keys
  • Check out homepage & all libraries: secp256k1, ed25519, bls12-381, hashes, curves

Usage

Use NPM in node.js / browser, or include single file from GitHub's releases page:

Usage

npm install @noble/curves
import { weierstrass } from '@noble/curves/weierstrass'; // Short Weierstrass curve
import { sha256 } from '@noble/hashes/sha256';
import { hmac } from '@noble/hashes/hmac';
import { concatBytes, randomBytes } from '@noble/hashes/utils';

const secp256k1 = weierstrass({
  a: 0n,
  b: 7n,
  P: 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2fn,
  n: 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141n,
  Gx: 55066263022277343669578718895168534326250603453777594175500187360389116729240n,
  Gy: 32670510020758816978083085130507043184471273380659243275938904335757337482424n,
  hash: sha256,
  hmac: (k: Uint8Array, ...msgs: Uint8Array[]) => hmac(sha256, key, concatBytes(...msgs)),
  randomBytes
});

secp256k1.getPublicKey(secp256k1.utils.randomPrivateKey());
secp256k1.sign(randomBytes(32), secp256k1.utils.randomPrivateKey());
// secp256k1.verify(sig, msg, pub)

import { twistedEdwards } from '@noble/curves/edwards'; // Twisted Edwards curve
import { sha512 } from '@noble/hashes/sha512';
import { div } from '@noble/curves/modular';

const ed25519 = twistedEdwards({
  a: -1n,
  d: div(-121665n, 121666n, 2n ** 255n - 19n), // -121665n/121666n
  P: 2n ** 255n - 19n,
  n: 2n ** 252n + 27742317777372353535851937790883648493n,
  h: 8n,
  Gx: 15112221349535400772501151409588531511454012693041857206046113283949847762202n,
  Gy: 46316835694926478169428394003475163141307993866256225615783033603165251855960n,
  hash: sha512,
  randomBytes,
  adjustScalarBytes(bytes) { // could be no-op
    bytes[0] &= 248;
    bytes[31] &= 127;
    bytes[31] |= 64;
    return bytes;
  },
} as const);
ed25519.getPublicKey(ed25519.utils.randomPrivateKey());

Performance

Benchmark results on Apple M2 with node v18.10:

==== secp256k1 ====
  - getPublicKey1 (samples: 10000)
    noble_old x 8,131 ops/sec @ 122μs/op
    secp256k1 x 7,374 ops/sec @ 135μs/op
  - getPublicKey255 (samples: 10000)
    noble_old x 7,894 ops/sec @ 126μs/op
    secp256k1 x 7,327 ops/sec @ 136μs/op
  - sign (samples: 5000)
    noble_old x 5,243 ops/sec @ 190μs/op
    secp256k1 x 4,834 ops/sec @ 206μs/op
  - getSharedSecret (samples: 1000)
    noble_old x 653 ops/sec @ 1ms/op
    secp256k1 x 634 ops/sec @ 1ms/op
  - verify (samples: 1000)
    secp256k1_old x 1,038 ops/sec @ 962μs/op
    secp256k1 x 1,009 ops/sec @ 990μs/op
==== ed25519 ====
  - getPublicKey (samples: 10000)
    old x 8,632 ops/sec @ 115μs/op
    noble x 8,390 ops/sec @ 119μs/op
  - sign (samples: 5000)
    old x 4,376 ops/sec @ 228μs/op
    noble x 4,233 ops/sec @ 236μs/op
  - verify (samples: 1000)
    old x 865 ops/sec @ 1ms/op
    noble x 860 ops/sec @ 1ms/op
==== ed448 ====
  - getPublicKey (samples: 5000)
    noble x 3,224 ops/sec @ 310μs/op
  - sign (samples: 2500)
    noble x 1,561 ops/sec @ 640μs/op
  - verify (samples: 500)
    noble x 313 ops/sec @ 3ms/op
==== nist ====
  - getPublicKey (samples: 2500)
    P256 x 7,993 ops/sec @ 125μs/op
    P384 x 3,819 ops/sec @ 261μs/op
    P521 x 2,074 ops/sec @ 481μs/op
  - sign (samples: 1000)
    P256 x 5,327 ops/sec @ 187μs/op
    P384 x 2,728 ops/sec @ 366μs/op
    P521 x 1,594 ops/sec @ 626μs/op
  - verify (samples: 250)
    P256 x 806 ops/sec @ 1ms/op
    P384 x 353 ops/sec @ 2ms/op
    P521 x 171 ops/sec @ 5ms/op
==== stark ====
  - pedersen (samples: 500)
    old x 85 ops/sec @ 11ms/op
    noble x 1,216 ops/sec @ 822μs/op
  - verify (samples: 500)
    old x 302 ops/sec @ 3ms/op
    noble x 698 ops/sec @ 1ms/op

License

MIT (c) Paul Miller (https://paulmillr.com), see LICENSE file.