@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 +99 -15
- package/lib/edwards.d.ts +108 -0
- package/lib/edwards.js +554 -0
- package/lib/esm/edwards.js +550 -0
- package/lib/esm/group.js +107 -0
- package/lib/esm/modular.js +10 -1
- package/lib/esm/montgomery.js +189 -0
- package/lib/esm/utils.js +62 -5
- package/lib/esm/{shortw.js → weierstrass.js} +79 -158
- package/lib/group.d.ts +33 -0
- package/lib/group.js +111 -0
- package/lib/modular.d.ts +2 -1
- package/lib/modular.js +13 -3
- package/lib/montgomery.d.ts +20 -0
- package/lib/montgomery.js +191 -0
- package/lib/utils.d.ts +26 -2
- package/lib/utils.js +71 -7
- package/lib/{shortw.d.ts → weierstrass.d.ts} +22 -35
- package/lib/{shortw.js → weierstrass.js} +78 -157
- package/package.json +23 -11
package/README.md
CHANGED
|
@@ -2,15 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
Minimal, zero-dependency JS implementation of elliptic curve cryptography.
|
|
4
4
|
|
|
5
|
-
|
|
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
|
-
|
|
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
|
-
-
|
|
13
|
-
-
|
|
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
|
-
|
|
54
|
+
const secp256k1 = weierstrass({
|
|
50
55
|
a: 0n,
|
|
51
56
|
b: 7n,
|
|
52
|
-
|
|
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
|
|
63
|
+
randomBytes
|
|
62
64
|
});
|
|
63
65
|
|
|
64
|
-
|
|
65
|
-
|
|
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
|
package/lib/edwards.d.ts
ADDED
|
@@ -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 {};
|