@noble/curves 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -2,15 +2,21 @@
2
2
 
3
3
  Minimal, zero-dependency JS implementation of elliptic curve cryptography.
4
4
 
5
- Implements Short Weierstrass curves with ECDSA signature scheme.
5
+ - Short Weierstrass curve with ECDSA signatures
6
+ - Twisted Edwards curve with EdDSA signatures
7
+ - Montgomery curve for ECDH key agreement
6
8
 
7
- To keep the package minimal, no curve definitions are provided out-of-box.
8
- Main reason for that is the fact hashing library is usually required for full functionality. Use separate package that defines popular curves: `micro-curve-definitions` for P192, P224, P256, P384, P521, secp256k1, stark curve, bn254, pasta (pallas/vesta) - it depends on `@noble/hashes`.
9
+ To keep the package minimal, no curve definitions are provided out-of-box. Use `micro-curve-definitions` module:
10
+
11
+ - It provides P192, P224, P256, P384, P521, secp256k1, stark curve, bn254, pasta (pallas/vesta) short weierstrass curves
12
+ - It also provides ed25519 and ed448 twisted edwards curves
13
+ - Main reason for separate package is the fact hashing library (like `@noble/hashes`) is required for full functionality
14
+ - We may reconsider merging packages in future, when a stable version would be ready
9
15
 
10
16
  Future plans:
11
17
 
12
- - Edwards, Twisted Edwards & Montgomery curves
13
- - hash-to-curve standard
18
+ - hash to curve standard
19
+ - point indistinguishability
14
20
  - pairings
15
21
 
16
22
  ### This library belongs to _noble_ crypto
@@ -40,30 +46,108 @@ npm install @noble/curves
40
46
  ```
41
47
 
42
48
  ```ts
43
- // Short Weierstrass curve
44
- import shortw from '@noble/curves/shortw';
49
+ import { weierstrass } from '@noble/curves/weierstrass'; // Short Weierstrass curve
45
50
  import { sha256 } from '@noble/hashes/sha256';
46
51
  import { hmac } from '@noble/hashes/hmac';
47
52
  import { concatBytes, randomBytes } from '@noble/hashes/utils';
48
53
 
49
- export const secp256k1 = shortw({
54
+ const secp256k1 = weierstrass({
50
55
  a: 0n,
51
56
  b: 7n,
52
- // Field over which we'll do calculations
53
- P: 2n ** 256n - 2n ** 32n - 2n ** 9n - 2n ** 8n - 2n ** 7n - 2n ** 6n - 2n ** 4n - 1n,
54
- // Curve order, total count of valid points in the field
57
+ P: 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2fn,
55
58
  n: 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141n,
56
- // Base point (x, y) aka generator point
57
59
  Gx: 55066263022277343669578718895168534326250603453777594175500187360389116729240n,
58
60
  Gy: 32670510020758816978083085130507043184471273380659243275938904335757337482424n,
59
61
  hash: sha256,
60
62
  hmac: (k: Uint8Array, ...msgs: Uint8Array[]) => hmac(sha256, key, concatBytes(...msgs)),
61
- randomBytes: randomBytes
63
+ randomBytes
62
64
  });
63
65
 
64
- // secp256k1.getPublicKey(priv)
65
- // secp256k1.sign(msg, priv)
66
+ secp256k1.getPublicKey(secp256k1.utils.randomPrivateKey());
67
+ secp256k1.sign(randomBytes(32), secp256k1.utils.randomPrivateKey());
66
68
  // secp256k1.verify(sig, msg, pub)
69
+
70
+ import { twistedEdwards } from '@noble/curves/edwards'; // Twisted Edwards curve
71
+ import { sha512 } from '@noble/hashes/sha512';
72
+
73
+ const ed25519 = twistedEdwards({
74
+ a: -1n,
75
+ d: 37095705934669439343138083508754565189542113879843219016388785533085940283555n,
76
+ P: 57896044618658097711785492504343953926634992332820282019728792003956564819949n,
77
+ n: 7237005577332262213973186563042994240857116359379907606001950938285454250989n,
78
+ h: 8n,
79
+ Gx: 15112221349535400772501151409588531511454012693041857206046113283949847762202n,
80
+ Gy: 46316835694926478169428394003475163141307993866256225615783033603165251855960n,
81
+ hash: sha512,
82
+ randomBytes,
83
+ adjustScalarBytes(bytes) { // could be no-op
84
+ bytes[0] &= 248;
85
+ bytes[31] &= 127;
86
+ bytes[31] |= 64;
87
+ return bytes;
88
+ },
89
+ } as const);
90
+ ed25519.getPublicKey(ed25519.utils.randomPrivateKey());
91
+ ```
92
+
93
+ ## Performance
94
+
95
+ Benchmark results on Apple M2 with node v18.10:
96
+
97
+ ```
98
+ ==== secp256k1 ====
99
+ - getPublicKey1 (samples: 10000)
100
+ noble_old x 8,131 ops/sec @ 122μs/op
101
+ secp256k1 x 7,374 ops/sec @ 135μs/op
102
+ - getPublicKey255 (samples: 10000)
103
+ noble_old x 7,894 ops/sec @ 126μs/op
104
+ secp256k1 x 7,327 ops/sec @ 136μs/op
105
+ - sign (samples: 5000)
106
+ noble_old x 5,243 ops/sec @ 190μs/op
107
+ secp256k1 x 4,834 ops/sec @ 206μs/op
108
+ - getSharedSecret (samples: 1000)
109
+ noble_old x 653 ops/sec @ 1ms/op
110
+ secp256k1 x 634 ops/sec @ 1ms/op
111
+ - verify (samples: 1000)
112
+ secp256k1_old x 1,038 ops/sec @ 962μs/op
113
+ secp256k1 x 1,009 ops/sec @ 990μs/op
114
+ ==== ed25519 ====
115
+ - getPublicKey (samples: 10000)
116
+ old x 8,632 ops/sec @ 115μs/op
117
+ noble x 8,390 ops/sec @ 119μs/op
118
+ - sign (samples: 5000)
119
+ old x 4,376 ops/sec @ 228μs/op
120
+ noble x 4,233 ops/sec @ 236μs/op
121
+ - verify (samples: 1000)
122
+ old x 865 ops/sec @ 1ms/op
123
+ noble x 860 ops/sec @ 1ms/op
124
+ ==== ed448 ====
125
+ - getPublicKey (samples: 5000)
126
+ noble x 3,224 ops/sec @ 310μs/op
127
+ - sign (samples: 2500)
128
+ noble x 1,561 ops/sec @ 640μs/op
129
+ - verify (samples: 500)
130
+ noble x 313 ops/sec @ 3ms/op
131
+ ==== nist ====
132
+ - getPublicKey (samples: 2500)
133
+ P256 x 7,993 ops/sec @ 125μs/op
134
+ P384 x 3,819 ops/sec @ 261μs/op
135
+ P521 x 2,074 ops/sec @ 481μs/op
136
+ - sign (samples: 1000)
137
+ P256 x 5,327 ops/sec @ 187μs/op
138
+ P384 x 2,728 ops/sec @ 366μs/op
139
+ P521 x 1,594 ops/sec @ 626μs/op
140
+ - verify (samples: 250)
141
+ P256 x 806 ops/sec @ 1ms/op
142
+ P384 x 353 ops/sec @ 2ms/op
143
+ P521 x 171 ops/sec @ 5ms/op
144
+ ==== stark ====
145
+ - pedersen (samples: 500)
146
+ old x 85 ops/sec @ 11ms/op
147
+ noble x 1,216 ops/sec @ 822μs/op
148
+ - verify (samples: 500)
149
+ old x 302 ops/sec @ 3ms/op
150
+ noble x 698 ops/sec @ 1ms/op
67
151
  ```
68
152
 
69
153
  ## License
@@ -0,0 +1,108 @@
1
+ /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
2
+ import { BasicCurve, Hex, PrivKey } from './utils.js';
3
+ import { Group, GroupConstructor } from './group.js';
4
+ export declare type CHash = {
5
+ (message: Uint8Array | string): Uint8Array;
6
+ blockLen: number;
7
+ outputLen: number;
8
+ create(): any;
9
+ };
10
+ export declare type CurveType = BasicCurve & {
11
+ a: bigint;
12
+ d: bigint;
13
+ hash: CHash;
14
+ randomBytes: (bytesLength?: number) => Uint8Array;
15
+ adjustScalarBytes?: (bytes: Uint8Array) => Uint8Array;
16
+ domain?: (data: Uint8Array, ctx: Uint8Array, phflag: boolean) => Uint8Array;
17
+ uvRatio?: (u: bigint, v: bigint) => {
18
+ isValid: boolean;
19
+ value: bigint;
20
+ };
21
+ preHash?: CHash;
22
+ };
23
+ declare function validateOpts(curve: CurveType): Readonly<{
24
+ readonly nBitLength: number;
25
+ readonly nByteLength: number;
26
+ readonly P: bigint;
27
+ readonly n: bigint;
28
+ readonly h: bigint;
29
+ readonly Gx: bigint;
30
+ readonly Gy: bigint;
31
+ readonly a: bigint;
32
+ readonly d: bigint;
33
+ readonly hash: CHash;
34
+ readonly randomBytes: (bytesLength?: number | undefined) => Uint8Array;
35
+ readonly adjustScalarBytes?: ((bytes: Uint8Array) => Uint8Array) | undefined;
36
+ readonly domain?: ((data: Uint8Array, ctx: Uint8Array, phflag: boolean) => Uint8Array) | undefined;
37
+ readonly uvRatio?: ((u: bigint, v: bigint) => {
38
+ isValid: boolean;
39
+ value: bigint;
40
+ }) | undefined;
41
+ readonly preHash?: CHash | undefined;
42
+ }>;
43
+ export interface SignatureType {
44
+ readonly r: PointType;
45
+ readonly s: bigint;
46
+ assertValidity(): SignatureType;
47
+ toRawBytes(): Uint8Array;
48
+ toHex(): string;
49
+ }
50
+ export declare type SignatureConstructor = {
51
+ new (r: PointType, s: bigint): SignatureType;
52
+ fromHex(hex: Hex): SignatureType;
53
+ };
54
+ export interface ExtendedPointType extends Group<ExtendedPointType> {
55
+ readonly x: bigint;
56
+ readonly y: bigint;
57
+ readonly z: bigint;
58
+ readonly t: bigint;
59
+ multiply(scalar: number | bigint, affinePoint?: PointType): ExtendedPointType;
60
+ multiplyUnsafe(scalar: number | bigint): ExtendedPointType;
61
+ isSmallOrder(): boolean;
62
+ isTorsionFree(): boolean;
63
+ toAffine(invZ?: bigint): PointType;
64
+ }
65
+ export interface ExtendedPointConstructor extends GroupConstructor<ExtendedPointType> {
66
+ new (x: bigint, y: bigint, z: bigint, t: bigint): ExtendedPointType;
67
+ fromAffine(p: PointType): ExtendedPointType;
68
+ toAffineBatch(points: ExtendedPointType[]): PointType[];
69
+ normalizeZ(points: ExtendedPointType[]): ExtendedPointType[];
70
+ }
71
+ export interface PointType extends Group<PointType> {
72
+ readonly x: bigint;
73
+ readonly y: bigint;
74
+ _setWindowSize(windowSize: number): void;
75
+ toRawBytes(isCompressed?: boolean): Uint8Array;
76
+ toHex(isCompressed?: boolean): string;
77
+ isTorsionFree(): boolean;
78
+ }
79
+ export interface PointConstructor extends GroupConstructor<PointType> {
80
+ new (x: bigint, y: bigint): PointType;
81
+ fromHex(hex: Hex): PointType;
82
+ fromPrivateKey(privateKey: PrivKey): PointType;
83
+ }
84
+ export declare type PubKey = Hex | PointType;
85
+ export declare type SigType = Hex | SignatureType;
86
+ export declare type CurveFn = {
87
+ CURVE: ReturnType<typeof validateOpts>;
88
+ getPublicKey: (privateKey: PrivKey, isCompressed?: boolean) => Uint8Array;
89
+ sign: (message: Hex, privateKey: Hex) => Uint8Array;
90
+ verify: (sig: SigType, message: Hex, publicKey: PubKey) => boolean;
91
+ Point: PointConstructor;
92
+ ExtendedPoint: ExtendedPointConstructor;
93
+ Signature: SignatureConstructor;
94
+ utils: {
95
+ mod: (a: bigint, b?: bigint) => bigint;
96
+ invert: (number: bigint, modulo?: bigint) => bigint;
97
+ randomPrivateKey: () => Uint8Array;
98
+ getExtendedPublicKey: (key: PrivKey) => {
99
+ head: Uint8Array;
100
+ prefix: Uint8Array;
101
+ scalar: bigint;
102
+ point: PointType;
103
+ pointBytes: Uint8Array;
104
+ };
105
+ };
106
+ };
107
+ export declare function twistedEdwards(curveDef: CurveType): CurveFn;
108
+ export {};