@noble/curves 1.9.5 → 2.0.0-beta.1
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 +267 -421
- package/abstract/bls.d.ts +49 -111
- package/abstract/bls.d.ts.map +1 -1
- package/abstract/bls.js +108 -152
- package/abstract/bls.js.map +1 -1
- package/abstract/curve.d.ts +7 -48
- package/abstract/curve.d.ts.map +1 -1
- package/abstract/curve.js +22 -47
- package/abstract/curve.js.map +1 -1
- package/abstract/edwards.d.ts +17 -68
- package/abstract/edwards.d.ts.map +1 -1
- package/abstract/edwards.js +98 -175
- package/abstract/edwards.js.map +1 -1
- package/abstract/fft.js +14 -27
- package/abstract/fft.js.map +1 -1
- package/abstract/hash-to-curve.d.ts +11 -24
- package/abstract/hash-to-curve.d.ts.map +1 -1
- package/abstract/hash-to-curve.js +30 -35
- package/abstract/hash-to-curve.js.map +1 -1
- package/abstract/modular.d.ts +5 -17
- package/abstract/modular.d.ts.map +1 -1
- package/abstract/modular.js +166 -167
- package/abstract/modular.js.map +1 -1
- package/abstract/montgomery.d.ts +4 -9
- package/abstract/montgomery.d.ts.map +1 -1
- package/abstract/montgomery.js +17 -20
- package/abstract/montgomery.js.map +1 -1
- package/abstract/oprf.d.ts +282 -0
- package/abstract/oprf.d.ts.map +1 -0
- package/abstract/oprf.js +297 -0
- package/abstract/oprf.js.map +1 -0
- package/abstract/poseidon.js +20 -24
- package/abstract/poseidon.js.map +1 -1
- package/abstract/tower.d.ts +9 -7
- package/abstract/tower.d.ts.map +1 -1
- package/abstract/tower.js +600 -364
- package/abstract/tower.js.map +1 -1
- package/abstract/weierstrass.d.ts +12 -145
- package/abstract/weierstrass.d.ts.map +1 -1
- package/abstract/weierstrass.js +153 -377
- package/abstract/weierstrass.js.map +1 -1
- package/bls12-381.d.ts +2 -2
- package/bls12-381.d.ts.map +1 -1
- package/bls12-381.js +174 -216
- package/bls12-381.js.map +1 -1
- package/bn254.d.ts +58 -10
- package/bn254.d.ts.map +1 -1
- package/bn254.js +70 -130
- package/bn254.js.map +1 -1
- package/ed25519.d.ts +12 -31
- package/ed25519.d.ts.map +1 -1
- package/ed25519.js +104 -146
- package/ed25519.js.map +1 -1
- package/ed448.d.ts +14 -33
- package/ed448.d.ts.map +1 -1
- package/ed448.js +105 -132
- package/ed448.js.map +1 -1
- package/index.js +1 -1
- package/misc.d.ts +10 -14
- package/misc.d.ts.map +1 -1
- package/misc.js +51 -60
- package/misc.js.map +1 -1
- package/nist.d.ts +11 -14
- package/nist.d.ts.map +1 -1
- package/nist.js +46 -55
- package/nist.js.map +1 -1
- package/package.json +9 -224
- package/secp256k1.d.ts +7 -23
- package/secp256k1.d.ts.map +1 -1
- package/secp256k1.js +72 -83
- package/secp256k1.js.map +1 -1
- package/src/abstract/bls.ts +197 -344
- package/src/abstract/curve.ts +10 -83
- package/src/abstract/edwards.ts +96 -223
- package/src/abstract/hash-to-curve.ts +32 -45
- package/src/abstract/modular.ts +144 -130
- package/src/abstract/montgomery.ts +21 -22
- package/src/abstract/oprf.ts +600 -0
- package/src/abstract/tower.ts +627 -382
- package/src/abstract/weierstrass.ts +101 -482
- package/src/bls12-381.ts +148 -176
- package/src/bn254.ts +67 -122
- package/src/ed25519.ts +65 -118
- package/src/ed448.ts +63 -113
- package/src/index.ts +1 -1
- package/src/misc.ts +66 -49
- package/src/nist.ts +48 -57
- package/src/secp256k1.ts +56 -88
- package/src/utils.ts +41 -61
- package/src/webcrypto.ts +362 -0
- package/utils.d.ts +28 -19
- package/utils.d.ts.map +1 -1
- package/utils.js +45 -121
- package/utils.js.map +1 -1
- package/webcrypto.d.ts +47 -0
- package/webcrypto.d.ts.map +1 -0
- package/webcrypto.js +231 -0
- package/webcrypto.js.map +1 -0
- package/esm/_shortw_utils.d.ts +0 -19
- package/esm/_shortw_utils.d.ts.map +0 -1
- package/esm/_shortw_utils.js +0 -16
- package/esm/_shortw_utils.js.map +0 -1
- package/esm/abstract/bls.d.ts +0 -190
- package/esm/abstract/bls.d.ts.map +0 -1
- package/esm/abstract/bls.js +0 -408
- package/esm/abstract/bls.js.map +0 -1
- package/esm/abstract/curve.d.ts +0 -231
- package/esm/abstract/curve.d.ts.map +0 -1
- package/esm/abstract/curve.js +0 -465
- package/esm/abstract/curve.js.map +0 -1
- package/esm/abstract/edwards.d.ts +0 -237
- package/esm/abstract/edwards.d.ts.map +0 -1
- package/esm/abstract/edwards.js +0 -632
- package/esm/abstract/edwards.js.map +0 -1
- package/esm/abstract/fft.d.ts +0 -122
- package/esm/abstract/fft.d.ts.map +0 -1
- package/esm/abstract/fft.js +0 -425
- package/esm/abstract/fft.js.map +0 -1
- package/esm/abstract/hash-to-curve.d.ts +0 -102
- package/esm/abstract/hash-to-curve.d.ts.map +0 -1
- package/esm/abstract/hash-to-curve.js +0 -203
- package/esm/abstract/hash-to-curve.js.map +0 -1
- package/esm/abstract/modular.d.ts +0 -171
- package/esm/abstract/modular.d.ts.map +0 -1
- package/esm/abstract/modular.js +0 -530
- package/esm/abstract/modular.js.map +0 -1
- package/esm/abstract/montgomery.d.ts +0 -30
- package/esm/abstract/montgomery.d.ts.map +0 -1
- package/esm/abstract/montgomery.js +0 -157
- package/esm/abstract/montgomery.js.map +0 -1
- package/esm/abstract/poseidon.d.ts +0 -68
- package/esm/abstract/poseidon.d.ts.map +0 -1
- package/esm/abstract/poseidon.js +0 -296
- package/esm/abstract/poseidon.js.map +0 -1
- package/esm/abstract/tower.d.ts +0 -93
- package/esm/abstract/tower.d.ts.map +0 -1
- package/esm/abstract/tower.js +0 -502
- package/esm/abstract/tower.js.map +0 -1
- package/esm/abstract/utils.d.ts +0 -5
- package/esm/abstract/utils.d.ts.map +0 -1
- package/esm/abstract/utils.js +0 -7
- package/esm/abstract/utils.js.map +0 -1
- package/esm/abstract/weierstrass.d.ts +0 -412
- package/esm/abstract/weierstrass.d.ts.map +0 -1
- package/esm/abstract/weierstrass.js +0 -1428
- package/esm/abstract/weierstrass.js.map +0 -1
- package/esm/bls12-381.d.ts +0 -16
- package/esm/bls12-381.d.ts.map +0 -1
- package/esm/bls12-381.js +0 -738
- package/esm/bls12-381.js.map +0 -1
- package/esm/bn254.d.ts +0 -18
- package/esm/bn254.d.ts.map +0 -1
- package/esm/bn254.js +0 -246
- package/esm/bn254.js.map +0 -1
- package/esm/ed25519.d.ts +0 -106
- package/esm/ed25519.d.ts.map +0 -1
- package/esm/ed25519.js +0 -467
- package/esm/ed25519.js.map +0 -1
- package/esm/ed448.d.ts +0 -101
- package/esm/ed448.d.ts.map +0 -1
- package/esm/ed448.js +0 -448
- package/esm/ed448.js.map +0 -1
- package/esm/index.d.ts +0 -2
- package/esm/index.d.ts.map +0 -1
- package/esm/index.js +0 -17
- package/esm/index.js.map +0 -1
- package/esm/jubjub.d.ts +0 -12
- package/esm/jubjub.d.ts.map +0 -1
- package/esm/jubjub.js +0 -12
- package/esm/jubjub.js.map +0 -1
- package/esm/misc.d.ts +0 -19
- package/esm/misc.d.ts.map +0 -1
- package/esm/misc.js +0 -109
- package/esm/misc.js.map +0 -1
- package/esm/nist.d.ts +0 -21
- package/esm/nist.d.ts.map +0 -1
- package/esm/nist.js +0 -132
- package/esm/nist.js.map +0 -1
- package/esm/p256.d.ts +0 -16
- package/esm/p256.d.ts.map +0 -1
- package/esm/p256.js +0 -16
- package/esm/p256.js.map +0 -1
- package/esm/p384.d.ts +0 -16
- package/esm/p384.d.ts.map +0 -1
- package/esm/p384.js +0 -16
- package/esm/p384.js.map +0 -1
- package/esm/p521.d.ts +0 -16
- package/esm/p521.d.ts.map +0 -1
- package/esm/p521.js +0 -16
- package/esm/p521.js.map +0 -1
- package/esm/package.json +0 -4
- package/esm/pasta.d.ts +0 -10
- package/esm/pasta.d.ts.map +0 -1
- package/esm/pasta.js +0 -10
- package/esm/pasta.js.map +0 -1
- package/esm/secp256k1.d.ts +0 -89
- package/esm/secp256k1.d.ts.map +0 -1
- package/esm/secp256k1.js +0 -292
- package/esm/secp256k1.js.map +0 -1
- package/esm/utils.d.ts +0 -110
- package/esm/utils.d.ts.map +0 -1
- package/esm/utils.js +0 -322
- package/esm/utils.js.map +0 -1
- package/src/_shortw_utils.ts +0 -21
- package/src/abstract/utils.ts +0 -7
- package/src/jubjub.ts +0 -12
- package/src/p256.ts +0 -15
- package/src/p384.ts +0 -15
- package/src/p521.ts +0 -15
- package/src/package.json +0 -3
- package/src/pasta.ts +0 -9
package/src/nist.ts
CHANGED
|
@@ -5,11 +5,14 @@
|
|
|
5
5
|
*/
|
|
6
6
|
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
7
7
|
import { sha256, sha384, sha512 } from '@noble/hashes/sha2.js';
|
|
8
|
-
import { createCurve, type CurveFnWithCreate } from './_shortw_utils.ts';
|
|
9
8
|
import { createHasher, type H2CHasher } from './abstract/hash-to-curve.ts';
|
|
10
9
|
import { Field } from './abstract/modular.ts';
|
|
10
|
+
import { createORPF, type OPRF } from './abstract/oprf.ts';
|
|
11
11
|
import {
|
|
12
|
+
ecdsa,
|
|
12
13
|
mapToCurveSimpleSWU,
|
|
14
|
+
weierstrass,
|
|
15
|
+
type ECDSA,
|
|
13
16
|
type WeierstrassOpts,
|
|
14
17
|
type WeierstrassPointCons,
|
|
15
18
|
} from './abstract/weierstrass.ts';
|
|
@@ -72,9 +75,6 @@ const p521_CURVE: WeierstrassOpts<bigint> = {
|
|
|
72
75
|
),
|
|
73
76
|
};
|
|
74
77
|
|
|
75
|
-
const Fp256 = Field(p256_CURVE.p);
|
|
76
|
-
const Fp384 = Field(p384_CURVE.p);
|
|
77
|
-
const Fp521 = Field(p521_CURVE.p);
|
|
78
78
|
type SwuOpts = {
|
|
79
79
|
A: bigint;
|
|
80
80
|
B: bigint;
|
|
@@ -86,18 +86,17 @@ function createSWU(Point: WeierstrassPointCons<bigint>, opts: SwuOpts) {
|
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
/** NIST P256 (aka secp256r1, prime256v1) curve, ECDSA and ECDH methods. */
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
);
|
|
89
|
+
|
|
90
|
+
const p256_Point = /* @__PURE__ */ weierstrass(p256_CURVE);
|
|
91
|
+
export const p256: ECDSA = /* @__PURE__ */ ecdsa(p256_Point, sha256);
|
|
93
92
|
/** Hashing / encoding to p256 points / field. RFC 9380 methods. */
|
|
94
|
-
export const p256_hasher: H2CHasher<bigint
|
|
93
|
+
export const p256_hasher: H2CHasher<WeierstrassPointCons<bigint>> = /* @__PURE__ */ (() => {
|
|
95
94
|
return createHasher(
|
|
96
|
-
|
|
97
|
-
createSWU(
|
|
95
|
+
p256_Point,
|
|
96
|
+
createSWU(p256_Point, {
|
|
98
97
|
A: p256_CURVE.a,
|
|
99
98
|
B: p256_CURVE.b,
|
|
100
|
-
Z:
|
|
99
|
+
Z: p256_Point.Fp.create(BigInt('-10')),
|
|
101
100
|
}),
|
|
102
101
|
{
|
|
103
102
|
DST: 'P256_XMD:SHA-256_SSWU_RO_',
|
|
@@ -111,27 +110,26 @@ export const p256_hasher: H2CHasher<bigint> = /* @__PURE__ */ (() => {
|
|
|
111
110
|
);
|
|
112
111
|
})();
|
|
113
112
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
113
|
+
export const p256_oprf: OPRF = /* @__PURE__ */ (() =>
|
|
114
|
+
createORPF({
|
|
115
|
+
name: 'P256-SHA256',
|
|
116
|
+
Point: p256_Point,
|
|
117
|
+
hash: sha256,
|
|
118
|
+
hashToGroup: p256_hasher.hashToCurve,
|
|
119
|
+
hashToScalar: p256_hasher.hashToScalar,
|
|
120
|
+
}))();
|
|
121
121
|
|
|
122
|
+
const p384_Point = /* @__PURE__ */ weierstrass(p384_CURVE);
|
|
122
123
|
/** NIST P384 (aka secp384r1) curve, ECDSA and ECDH methods. */
|
|
123
|
-
export const p384:
|
|
124
|
-
{ ...p384_CURVE, Fp: Fp384, lowS: false },
|
|
125
|
-
sha384
|
|
126
|
-
);
|
|
124
|
+
export const p384: ECDSA = /* @__PURE__ */ ecdsa(p384_Point, sha384);
|
|
127
125
|
/** Hashing / encoding to p384 points / field. RFC 9380 methods. */
|
|
128
|
-
export const p384_hasher: H2CHasher<bigint
|
|
126
|
+
export const p384_hasher: H2CHasher<WeierstrassPointCons<bigint>> = /* @__PURE__ */ (() => {
|
|
129
127
|
return createHasher(
|
|
130
|
-
|
|
131
|
-
createSWU(
|
|
128
|
+
p384_Point,
|
|
129
|
+
createSWU(p384_Point, {
|
|
132
130
|
A: p384_CURVE.a,
|
|
133
131
|
B: p384_CURVE.b,
|
|
134
|
-
Z:
|
|
132
|
+
Z: p384_Point.Fp.create(BigInt('-12')),
|
|
135
133
|
}),
|
|
136
134
|
{
|
|
137
135
|
DST: 'P384_XMD:SHA-384_SSWU_RO_',
|
|
@@ -145,36 +143,28 @@ export const p384_hasher: H2CHasher<bigint> = /* @__PURE__ */ (() => {
|
|
|
145
143
|
);
|
|
146
144
|
})();
|
|
147
145
|
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
146
|
+
export const p384_oprf: OPRF = /* @__PURE__ */ (() =>
|
|
147
|
+
createORPF({
|
|
148
|
+
name: 'P384-SHA384',
|
|
149
|
+
Point: p384_Point,
|
|
150
|
+
hash: sha384,
|
|
151
|
+
hashToGroup: p384_hasher.hashToCurve,
|
|
152
|
+
hashToScalar: p384_hasher.hashToScalar,
|
|
153
|
+
}))();
|
|
155
154
|
|
|
156
|
-
|
|
155
|
+
const Fn521 = /* @__PURE__ */ Field(p521_CURVE.n, { allowedLengths: [65, 66] });
|
|
156
|
+
const p521_Point = /* @__PURE__ */ weierstrass(p521_CURVE, { Fn: Fn521 });
|
|
157
157
|
/** NIST P521 (aka secp521r1) curve, ECDSA and ECDH methods. */
|
|
158
|
-
export const p521:
|
|
159
|
-
{ ...p521_CURVE, Fp: Fp521, lowS: false, allowedPrivateKeyLengths: [130, 131, 132] },
|
|
160
|
-
sha512
|
|
161
|
-
);
|
|
162
|
-
|
|
163
|
-
/** @deprecated use `p256` for consistency with `p256_hasher` */
|
|
164
|
-
export const secp256r1: typeof p256 = p256;
|
|
165
|
-
/** @deprecated use `p384` for consistency with `p384_hasher` */
|
|
166
|
-
export const secp384r1: typeof p384 = p384;
|
|
167
|
-
/** @deprecated use `p521` for consistency with `p521_hasher` */
|
|
168
|
-
export const secp521r1: typeof p521 = p521;
|
|
158
|
+
export const p521: ECDSA = /* @__PURE__ */ ecdsa(p521_Point, sha512);
|
|
169
159
|
|
|
170
160
|
/** Hashing / encoding to p521 points / field. RFC 9380 methods. */
|
|
171
|
-
export const p521_hasher: H2CHasher<bigint
|
|
161
|
+
export const p521_hasher: H2CHasher<WeierstrassPointCons<bigint>> = /* @__PURE__ */ (() => {
|
|
172
162
|
return createHasher(
|
|
173
|
-
|
|
174
|
-
createSWU(
|
|
163
|
+
p521_Point,
|
|
164
|
+
createSWU(p521_Point, {
|
|
175
165
|
A: p521_CURVE.a,
|
|
176
166
|
B: p521_CURVE.b,
|
|
177
|
-
Z:
|
|
167
|
+
Z: p521_Point.Fp.create(BigInt('-4')),
|
|
178
168
|
}),
|
|
179
169
|
{
|
|
180
170
|
DST: 'P521_XMD:SHA-512_SSWU_RO_',
|
|
@@ -188,10 +178,11 @@ export const p521_hasher: H2CHasher<bigint> = /* @__PURE__ */ (() => {
|
|
|
188
178
|
);
|
|
189
179
|
})();
|
|
190
180
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
//
|
|
181
|
+
export const p521_oprf: OPRF = /* @__PURE__ */ (() =>
|
|
182
|
+
createORPF({
|
|
183
|
+
name: 'P521-SHA512',
|
|
184
|
+
Point: p521_Point,
|
|
185
|
+
hash: sha512,
|
|
186
|
+
hashToGroup: p521_hasher.hashToCurve,
|
|
187
|
+
hashToScalar: p521_hasher.hashToScalar, // produces L=98 just like in RFC
|
|
188
|
+
}))();
|
package/src/secp256k1.ts
CHANGED
|
@@ -8,36 +8,23 @@
|
|
|
8
8
|
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
9
9
|
import { sha256 } from '@noble/hashes/sha2.js';
|
|
10
10
|
import { randomBytes } from '@noble/hashes/utils.js';
|
|
11
|
-
import { createCurve, type CurveFnWithCreate } from './_shortw_utils.ts';
|
|
12
11
|
import type { CurveLengths } from './abstract/curve.ts';
|
|
12
|
+
import { createHasher, type H2CHasher, isogenyMap } from './abstract/hash-to-curve.ts';
|
|
13
|
+
import { Field, mapHashToField, pow2 } from './abstract/modular.ts';
|
|
13
14
|
import {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
type H2CMethod,
|
|
17
|
-
isogenyMap,
|
|
18
|
-
} from './abstract/hash-to-curve.ts';
|
|
19
|
-
import { Field, mapHashToField, mod, pow2 } from './abstract/modular.ts';
|
|
20
|
-
import {
|
|
21
|
-
_normFnElement,
|
|
15
|
+
type ECDSA,
|
|
16
|
+
ecdsa,
|
|
22
17
|
type EndomorphismOpts,
|
|
23
18
|
mapToCurveSimpleSWU,
|
|
24
19
|
type WeierstrassPoint as PointType,
|
|
20
|
+
weierstrass,
|
|
25
21
|
type WeierstrassOpts,
|
|
26
22
|
type WeierstrassPointCons,
|
|
27
23
|
} from './abstract/weierstrass.ts';
|
|
28
|
-
import
|
|
29
|
-
import {
|
|
30
|
-
aInRange,
|
|
31
|
-
bytesToNumberBE,
|
|
32
|
-
concatBytes,
|
|
33
|
-
ensureBytes,
|
|
34
|
-
inRange,
|
|
35
|
-
numberToBytesBE,
|
|
36
|
-
utf8ToBytes,
|
|
37
|
-
} from './utils.ts';
|
|
24
|
+
import { abytes, asciiToBytes, bytesToNumberBE, concatBytes, inRange } from './utils.ts';
|
|
38
25
|
|
|
39
26
|
// Seems like generator was produced from some seed:
|
|
40
|
-
// `
|
|
27
|
+
// `Pointk1.BASE.multiply(Pointk1.Fn.inv(2n, N)).toAffine().x`
|
|
41
28
|
// // gives short x 0x3b78ce563f89a0ed9414f5aa28ad0d96d6795f9c63n
|
|
42
29
|
const secp256k1_CURVE: WeierstrassOpts<bigint> = {
|
|
43
30
|
p: BigInt('0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2f'),
|
|
@@ -90,6 +77,10 @@ function sqrtMod(y: bigint): bigint {
|
|
|
90
77
|
}
|
|
91
78
|
|
|
92
79
|
const Fpk1 = Field(secp256k1_CURVE.p, { sqrt: sqrtMod });
|
|
80
|
+
const Pointk1 = /* @__PURE__ */ weierstrass(secp256k1_CURVE, {
|
|
81
|
+
Fp: Fpk1,
|
|
82
|
+
endo: secp256k1_ENDO,
|
|
83
|
+
});
|
|
93
84
|
|
|
94
85
|
/**
|
|
95
86
|
* secp256k1 curve, ECDSA and ECDH methods.
|
|
@@ -105,10 +96,8 @@ const Fpk1 = Field(secp256k1_CURVE.p, { sqrt: sqrtMod });
|
|
|
105
96
|
* const isValid = secp256k1.verify(sig, msg, publicKey) === true;
|
|
106
97
|
* ```
|
|
107
98
|
*/
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
sha256
|
|
111
|
-
);
|
|
99
|
+
|
|
100
|
+
export const secp256k1: ECDSA = /* @__PURE__ */ ecdsa(Pointk1, sha256);
|
|
112
101
|
|
|
113
102
|
// Schnorr signatures are superior to ECDSA from above. Below is Schnorr-specific BIP0340 code.
|
|
114
103
|
// https://github.com/bitcoin/bips/blob/master/bip-0340.mediawiki
|
|
@@ -117,7 +106,7 @@ const TAGGED_HASH_PREFIXES: { [tag: string]: Uint8Array } = {};
|
|
|
117
106
|
function taggedHash(tag: string, ...messages: Uint8Array[]): Uint8Array {
|
|
118
107
|
let tagP = TAGGED_HASH_PREFIXES[tag];
|
|
119
108
|
if (tagP === undefined) {
|
|
120
|
-
const tagH = sha256(
|
|
109
|
+
const tagH = sha256(asciiToBytes(tag));
|
|
121
110
|
tagP = concatBytes(tagH, tagH);
|
|
122
111
|
TAGGED_HASH_PREFIXES[tag] = tagP;
|
|
123
112
|
}
|
|
@@ -126,18 +115,14 @@ function taggedHash(tag: string, ...messages: Uint8Array[]): Uint8Array {
|
|
|
126
115
|
|
|
127
116
|
// ECDSA compact points are 33-byte. Schnorr is 32: we strip first byte 0x02 or 0x03
|
|
128
117
|
const pointToBytes = (point: PointType<bigint>) => point.toBytes(true).slice(1);
|
|
129
|
-
const numTo32b = (n: bigint) => numberToBytesBE(n, 32);
|
|
130
|
-
const modP = (x: bigint) => mod(x, secp256k1_CURVE.p);
|
|
131
|
-
const modN = (x: bigint) => mod(x, secp256k1_CURVE.n);
|
|
132
|
-
const Point = /* @__PURE__ */ (() => secp256k1.Point)();
|
|
133
118
|
const hasEven = (y: bigint) => y % _2n === _0n;
|
|
134
119
|
|
|
135
120
|
// Calculate point, scalar and bytes
|
|
136
|
-
function schnorrGetExtPubKey(priv:
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
const scalar = hasEven(p.y) ? d_ :
|
|
121
|
+
function schnorrGetExtPubKey(priv: Uint8Array) {
|
|
122
|
+
const { Fn, BASE } = Pointk1;
|
|
123
|
+
const d_ = Fn.fromBytes(priv);
|
|
124
|
+
const p = BASE.multiply(d_); // P = d'⋅G; 0 < d' < n check is done inside
|
|
125
|
+
const scalar = hasEven(p.y) ? d_ : Fn.neg(d_);
|
|
141
126
|
return { scalar, bytes: pointToBytes(p) };
|
|
142
127
|
}
|
|
143
128
|
/**
|
|
@@ -145,12 +130,15 @@ function schnorrGetExtPubKey(priv: PrivKey) {
|
|
|
145
130
|
* @returns valid point checked for being on-curve
|
|
146
131
|
*/
|
|
147
132
|
function lift_x(x: bigint): PointType<bigint> {
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
const
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
133
|
+
const Fp = Fpk1;
|
|
134
|
+
if (!Fp.isValidNot0(x)) throw new Error('invalid x: Fail if x ≥ p');
|
|
135
|
+
const xx = Fp.create(x * x);
|
|
136
|
+
const c = Fp.create(xx * x + BigInt(7)); // Let c = x³ + 7 mod p.
|
|
137
|
+
let y = Fp.sqrt(c); // Let y = c^(p+1)/4 mod p. Same as sqrt().
|
|
138
|
+
// Return the unique point P such that x(P) = x and
|
|
139
|
+
// y(P) = y if y mod 2 = 0 or y(P) = p-y otherwise.
|
|
140
|
+
if (!hasEven(y)) y = Fp.neg(y);
|
|
141
|
+
const p = Pointk1.fromAffine({ x, y });
|
|
154
142
|
p.assertValidity();
|
|
155
143
|
return p;
|
|
156
144
|
}
|
|
@@ -159,13 +147,13 @@ const num = bytesToNumberBE;
|
|
|
159
147
|
* Create tagged hash, convert it to bigint, reduce modulo-n.
|
|
160
148
|
*/
|
|
161
149
|
function challenge(...args: Uint8Array[]): bigint {
|
|
162
|
-
return
|
|
150
|
+
return Pointk1.Fn.create(num(taggedHash('BIP0340/challenge', ...args)));
|
|
163
151
|
}
|
|
164
152
|
|
|
165
153
|
/**
|
|
166
154
|
* Schnorr public key is just `x` coordinate of Point as per BIP340.
|
|
167
155
|
*/
|
|
168
|
-
function schnorrGetPublicKey(secretKey:
|
|
156
|
+
function schnorrGetPublicKey(secretKey: Uint8Array): Uint8Array {
|
|
169
157
|
return schnorrGetExtPubKey(secretKey).bytes; // d'=int(sk). Fail if d'=0 or d'≥n. Ret bytes(d'⋅G)
|
|
170
158
|
}
|
|
171
159
|
|
|
@@ -173,19 +161,23 @@ function schnorrGetPublicKey(secretKey: Hex): Uint8Array {
|
|
|
173
161
|
* Creates Schnorr signature as per BIP340. Verifies itself before returning anything.
|
|
174
162
|
* auxRand is optional and is not the sole source of k generation: bad CSPRNG won't be dangerous.
|
|
175
163
|
*/
|
|
176
|
-
function schnorrSign(
|
|
177
|
-
|
|
164
|
+
function schnorrSign(
|
|
165
|
+
message: Uint8Array,
|
|
166
|
+
secretKey: Uint8Array,
|
|
167
|
+
auxRand: Uint8Array = randomBytes(32)
|
|
168
|
+
): Uint8Array {
|
|
169
|
+
const { Fn } = Pointk1;
|
|
170
|
+
const m = abytes(message, undefined, 'message');
|
|
178
171
|
const { bytes: px, scalar: d } = schnorrGetExtPubKey(secretKey); // checks for isWithinCurveOrder
|
|
179
|
-
const a =
|
|
180
|
-
const t =
|
|
172
|
+
const a = abytes(auxRand, 32, 'auxRand'); // Auxiliary random data a: a 32-byte array
|
|
173
|
+
const t = Fn.toBytes(d ^ num(taggedHash('BIP0340/aux', a))); // Let t be the byte-wise xor of bytes(d) and hash/aux(a)
|
|
181
174
|
const rand = taggedHash('BIP0340/nonce', t, px, m); // Let rand = hash/nonce(t || bytes(P) || m)
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
const { bytes: rx, scalar: k } = schnorrGetExtPubKey(k_); // Let R = k'⋅G.
|
|
175
|
+
// Let k' = int(rand) mod n. Fail if k' = 0. Let R = k'⋅G
|
|
176
|
+
const { bytes: rx, scalar: k } = schnorrGetExtPubKey(rand);
|
|
185
177
|
const e = challenge(rx, px, m); // Let e = int(hash/challenge(bytes(R) || bytes(P) || m)) mod n.
|
|
186
178
|
const sig = new Uint8Array(64); // Let sig = bytes(R) || bytes((k + ed) mod n).
|
|
187
179
|
sig.set(rx, 0);
|
|
188
|
-
sig.set(
|
|
180
|
+
sig.set(Fn.toBytes(Fn.create(k + e * d)), 32);
|
|
189
181
|
// If Verify(bytes(P), m, sig) (see below) returns failure, abort
|
|
190
182
|
if (!schnorrVerify(sig, m, px)) throw new Error('sign: Invalid signature produced');
|
|
191
183
|
return sig;
|
|
@@ -195,19 +187,20 @@ function schnorrSign(message: Hex, secretKey: PrivKey, auxRand: Hex = randomByte
|
|
|
195
187
|
* Verifies Schnorr signature.
|
|
196
188
|
* Will swallow errors & return false except for initial type validation of arguments.
|
|
197
189
|
*/
|
|
198
|
-
function schnorrVerify(signature:
|
|
199
|
-
const
|
|
200
|
-
const
|
|
201
|
-
const
|
|
190
|
+
function schnorrVerify(signature: Uint8Array, message: Uint8Array, publicKey: Uint8Array): boolean {
|
|
191
|
+
const { Fn, BASE } = Pointk1;
|
|
192
|
+
const sig = abytes(signature, 64, 'signature');
|
|
193
|
+
const m = abytes(message, undefined, 'message');
|
|
194
|
+
const pub = abytes(publicKey, 32, 'publicKey');
|
|
202
195
|
try {
|
|
203
196
|
const P = lift_x(num(pub)); // P = lift_x(int(pk)); fail if that fails
|
|
204
197
|
const r = num(sig.subarray(0, 32)); // Let r = int(sig[0:32]); fail if r ≥ p.
|
|
205
198
|
if (!inRange(r, _1n, secp256k1_CURVE.p)) return false;
|
|
206
199
|
const s = num(sig.subarray(32, 64)); // Let s = int(sig[32:64]); fail if s ≥ n.
|
|
207
200
|
if (!inRange(s, _1n, secp256k1_CURVE.n)) return false;
|
|
208
|
-
const e = challenge(
|
|
201
|
+
const e = challenge(Fn.toBytes(r), pointToBytes(P), m); // int(challenge(bytes(r)||bytes(P)||m))%n
|
|
209
202
|
// R = s⋅G - e⋅P, where -eP == (n-e)P
|
|
210
|
-
const R =
|
|
203
|
+
const R = BASE.multiplyUnsafe(s).add(P.multiplyUnsafe(Fn.neg(e)));
|
|
211
204
|
const { x, y } = R.toAffine();
|
|
212
205
|
// Fail if is_infinite(R) / not has_even_y(R) / x(R) ≠ r.
|
|
213
206
|
if (R.is0() || !hasEven(y) || x !== r) return false;
|
|
@@ -228,15 +221,6 @@ export type SecpSchnorr = {
|
|
|
228
221
|
pointToBytes: (point: PointType<bigint>) => Uint8Array;
|
|
229
222
|
lift_x: typeof lift_x;
|
|
230
223
|
taggedHash: typeof taggedHash;
|
|
231
|
-
|
|
232
|
-
/** @deprecated use `randomSecretKey` */
|
|
233
|
-
randomPrivateKey: (seed?: Uint8Array) => Uint8Array;
|
|
234
|
-
/** @deprecated use `utils` */
|
|
235
|
-
numberToBytesBE: typeof numberToBytesBE;
|
|
236
|
-
/** @deprecated use `utils` */
|
|
237
|
-
bytesToNumberBE: typeof bytesToNumberBE;
|
|
238
|
-
/** @deprecated use `modular` */
|
|
239
|
-
mod: typeof mod;
|
|
240
224
|
};
|
|
241
225
|
lengths: CurveLengths;
|
|
242
226
|
};
|
|
@@ -259,8 +243,6 @@ export const schnorr: SecpSchnorr = /* @__PURE__ */ (() => {
|
|
|
259
243
|
const randomSecretKey = (seed = randomBytes(seedLength)): Uint8Array => {
|
|
260
244
|
return mapHashToField(seed, secp256k1_CURVE.n);
|
|
261
245
|
};
|
|
262
|
-
// TODO: remove
|
|
263
|
-
secp256k1.utils.randomSecretKey;
|
|
264
246
|
function keygen(seed?: Uint8Array) {
|
|
265
247
|
const secretKey = randomSecretKey(seed);
|
|
266
248
|
return { secretKey, publicKey: schnorrGetPublicKey(secretKey) };
|
|
@@ -270,25 +252,19 @@ export const schnorr: SecpSchnorr = /* @__PURE__ */ (() => {
|
|
|
270
252
|
getPublicKey: schnorrGetPublicKey,
|
|
271
253
|
sign: schnorrSign,
|
|
272
254
|
verify: schnorrVerify,
|
|
273
|
-
Point,
|
|
255
|
+
Point: Pointk1,
|
|
274
256
|
utils: {
|
|
275
|
-
randomSecretKey
|
|
276
|
-
randomPrivateKey: randomSecretKey,
|
|
257
|
+
randomSecretKey,
|
|
277
258
|
taggedHash,
|
|
278
|
-
|
|
279
|
-
// TODO: remove
|
|
280
259
|
lift_x,
|
|
281
260
|
pointToBytes,
|
|
282
|
-
numberToBytesBE,
|
|
283
|
-
bytesToNumberBE,
|
|
284
|
-
mod,
|
|
285
261
|
},
|
|
286
262
|
lengths: {
|
|
287
|
-
|
|
288
|
-
|
|
263
|
+
secretKey: size,
|
|
264
|
+
publicKey: size,
|
|
265
|
+
publicKeyHasPrefix: false,
|
|
289
266
|
signature: size * 2,
|
|
290
267
|
seed: seedLength,
|
|
291
|
-
publicKeyHasPrefix: false,
|
|
292
268
|
},
|
|
293
269
|
};
|
|
294
270
|
})();
|
|
@@ -334,9 +310,9 @@ const mapSWU = /* @__PURE__ */ (() =>
|
|
|
334
310
|
}))();
|
|
335
311
|
|
|
336
312
|
/** Hashing / encoding to secp256k1 points / field. RFC 9380 methods. */
|
|
337
|
-
export const secp256k1_hasher: H2CHasher<bigint
|
|
313
|
+
export const secp256k1_hasher: H2CHasher<WeierstrassPointCons<bigint>> = /* @__PURE__ */ (() =>
|
|
338
314
|
createHasher(
|
|
339
|
-
|
|
315
|
+
Pointk1,
|
|
340
316
|
(scalars: bigint[]) => {
|
|
341
317
|
const { x, y } = mapSWU(Fpk1.create(scalars[0]));
|
|
342
318
|
return isoMap(x, y);
|
|
@@ -351,11 +327,3 @@ export const secp256k1_hasher: H2CHasher<bigint> = /* @__PURE__ */ (() =>
|
|
|
351
327
|
hash: sha256,
|
|
352
328
|
}
|
|
353
329
|
))();
|
|
354
|
-
|
|
355
|
-
/** @deprecated use `import { secp256k1_hasher } from '@noble/curves/secp256k1.js';` */
|
|
356
|
-
export const hashToCurve: H2CMethod<bigint> = /* @__PURE__ */ (() =>
|
|
357
|
-
secp256k1_hasher.hashToCurve)();
|
|
358
|
-
|
|
359
|
-
/** @deprecated use `import { secp256k1_hasher } from '@noble/curves/secp256k1.js';` */
|
|
360
|
-
export const encodeToCurve: H2CMethod<bigint> = /* @__PURE__ */ (() =>
|
|
361
|
-
secp256k1_hasher.encodeToCurve)();
|
package/src/utils.ts
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
/*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
|
|
6
6
|
import {
|
|
7
7
|
abytes as abytes_,
|
|
8
|
+
anumber,
|
|
8
9
|
bytesToHex as bytesToHex_,
|
|
9
10
|
concatBytes as concatBytes_,
|
|
10
11
|
hexToBytes as hexToBytes_,
|
|
@@ -19,26 +20,19 @@ export {
|
|
|
19
20
|
hexToBytes,
|
|
20
21
|
isBytes,
|
|
21
22
|
randomBytes,
|
|
22
|
-
utf8ToBytes
|
|
23
|
+
utf8ToBytes
|
|
23
24
|
} from '@noble/hashes/utils.js';
|
|
24
25
|
const _0n = /* @__PURE__ */ BigInt(0);
|
|
25
26
|
const _1n = /* @__PURE__ */ BigInt(1);
|
|
26
|
-
|
|
27
|
-
export type PrivKey = Hex | bigint; // bigints are accepted to ease learning curve
|
|
27
|
+
|
|
28
28
|
export type CHash = {
|
|
29
|
-
(message: Uint8Array
|
|
29
|
+
(message: Uint8Array): Uint8Array;
|
|
30
30
|
blockLen: number;
|
|
31
31
|
outputLen: number;
|
|
32
32
|
create(opts?: { dkLen?: number }): any; // For shake
|
|
33
33
|
};
|
|
34
|
-
export type FHash = (message: Uint8Array
|
|
35
|
-
|
|
36
|
-
export function abool(title: string, value: boolean): void {
|
|
37
|
-
if (typeof value !== 'boolean') throw new Error(title + ' boolean expected, got ' + value);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// tmp name until v2
|
|
41
|
-
export function _abool2(value: boolean, title: string = ''): boolean {
|
|
34
|
+
export type FHash = (message: Uint8Array) => Uint8Array;
|
|
35
|
+
export function abool(value: boolean, title: string = ''): boolean {
|
|
42
36
|
if (typeof value !== 'boolean') {
|
|
43
37
|
const prefix = title && `"${title}"`;
|
|
44
38
|
throw new Error(prefix + 'expected boolean, got type=' + typeof value);
|
|
@@ -46,24 +40,16 @@ export function _abool2(value: boolean, title: string = ''): boolean {
|
|
|
46
40
|
return value;
|
|
47
41
|
}
|
|
48
42
|
|
|
49
|
-
//
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
if (!bytes || (needsLen && len !== length)) {
|
|
56
|
-
const prefix = title && `"${title}"`;
|
|
57
|
-
const ofLen = needsLen ? ` of length ${length}` : '';
|
|
58
|
-
const got = bytes ? `length=${len}` : `type=${typeof value}`;
|
|
59
|
-
throw new Error(prefix + 'expected Uint8Array' + ofLen + ', got ' + got);
|
|
60
|
-
}
|
|
61
|
-
return value;
|
|
43
|
+
// Used in weierstrass, der
|
|
44
|
+
function abignumer(n: number | bigint) {
|
|
45
|
+
if (typeof n === 'bigint') {
|
|
46
|
+
if (!isPosBig(n)) throw new Error('positive bigint expected, got ' + n);
|
|
47
|
+
} else anumber(n);
|
|
48
|
+
return n;
|
|
62
49
|
}
|
|
63
50
|
|
|
64
|
-
// Used in weierstrass, der
|
|
65
51
|
export function numberToHexUnpadded(num: number | bigint): string {
|
|
66
|
-
const hex = num.toString(16);
|
|
52
|
+
const hex = abignumer(num).toString(16);
|
|
67
53
|
return hex.length & 1 ? '0' + hex : hex;
|
|
68
54
|
}
|
|
69
55
|
|
|
@@ -77,49 +63,22 @@ export function bytesToNumberBE(bytes: Uint8Array): bigint {
|
|
|
77
63
|
return hexToNumber(bytesToHex_(bytes));
|
|
78
64
|
}
|
|
79
65
|
export function bytesToNumberLE(bytes: Uint8Array): bigint {
|
|
80
|
-
abytes_(bytes);
|
|
81
|
-
return hexToNumber(bytesToHex_(Uint8Array.from(bytes).reverse()));
|
|
66
|
+
return hexToNumber(bytesToHex_(copyBytes(abytes_(bytes)).reverse()));
|
|
82
67
|
}
|
|
83
68
|
|
|
84
69
|
export function numberToBytesBE(n: number | bigint, len: number): Uint8Array {
|
|
85
|
-
|
|
70
|
+
anumber(len);
|
|
71
|
+
n = abignumer(n);
|
|
72
|
+
const res = hexToBytes_(n.toString(16).padStart(len * 2, '0'));
|
|
73
|
+
if (res.length !== len) throw new Error('number too large');
|
|
74
|
+
return res;
|
|
86
75
|
}
|
|
87
76
|
export function numberToBytesLE(n: number | bigint, len: number): Uint8Array {
|
|
88
77
|
return numberToBytesBE(n, len).reverse();
|
|
89
78
|
}
|
|
90
79
|
// Unpadded, rarely used
|
|
91
80
|
export function numberToVarBytesBE(n: number | bigint): Uint8Array {
|
|
92
|
-
return hexToBytes_(numberToHexUnpadded(n));
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Takes hex string or Uint8Array, converts to Uint8Array.
|
|
97
|
-
* Validates output length.
|
|
98
|
-
* Will throw error for other types.
|
|
99
|
-
* @param title descriptive title for an error e.g. 'secret key'
|
|
100
|
-
* @param hex hex string or Uint8Array
|
|
101
|
-
* @param expectedLength optional, will compare to result array's length
|
|
102
|
-
* @returns
|
|
103
|
-
*/
|
|
104
|
-
export function ensureBytes(title: string, hex: Hex, expectedLength?: number): Uint8Array {
|
|
105
|
-
let res: Uint8Array;
|
|
106
|
-
if (typeof hex === 'string') {
|
|
107
|
-
try {
|
|
108
|
-
res = hexToBytes_(hex);
|
|
109
|
-
} catch (e) {
|
|
110
|
-
throw new Error(title + ' must be hex string or Uint8Array, cause: ' + e);
|
|
111
|
-
}
|
|
112
|
-
} else if (isBytes_(hex)) {
|
|
113
|
-
// Uint8Array.from() instead of hash.slice() because node.js Buffer
|
|
114
|
-
// is instance of Uint8Array, and its slice() creates **mutable** copy
|
|
115
|
-
res = Uint8Array.from(hex);
|
|
116
|
-
} else {
|
|
117
|
-
throw new Error(title + ' must be hex string or Uint8Array');
|
|
118
|
-
}
|
|
119
|
-
const len = res.length;
|
|
120
|
-
if (typeof expectedLength === 'number' && len !== expectedLength)
|
|
121
|
-
throw new Error(title + ' of length ' + expectedLength + ' expected, got ' + len);
|
|
122
|
-
return res;
|
|
81
|
+
return hexToBytes_(numberToHexUnpadded(abignumer(n)));
|
|
123
82
|
}
|
|
124
83
|
|
|
125
84
|
// Compares 2 u8a-s in kinda constant time
|
|
@@ -129,6 +88,7 @@ export function equalBytes(a: Uint8Array, b: Uint8Array): boolean {
|
|
|
129
88
|
for (let i = 0; i < a.length; i++) diff |= a[i] ^ b[i];
|
|
130
89
|
return diff === 0;
|
|
131
90
|
}
|
|
91
|
+
|
|
132
92
|
/**
|
|
133
93
|
* Copies Uint8Array. We can't use u8a.slice(), because u8a can be Buffer,
|
|
134
94
|
* and Buffer#slice creates mutable copy. Never use Buffers!
|
|
@@ -374,3 +334,23 @@ export function memoized<T extends object, R, O extends any[]>(
|
|
|
374
334
|
return computed;
|
|
375
335
|
};
|
|
376
336
|
}
|
|
337
|
+
|
|
338
|
+
export interface CryptoKeys {
|
|
339
|
+
lengths: { seed?: number; public?: number; secret?: number };
|
|
340
|
+
keygen: (seed?: Uint8Array) => { secretKey: Uint8Array; publicKey: Uint8Array };
|
|
341
|
+
getPublicKey: (secretKey: Uint8Array) => Uint8Array;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/** Generic interface for signatures. Has keygen, sign and verify. */
|
|
345
|
+
export interface Signer extends CryptoKeys {
|
|
346
|
+
// Interfaces are fun. We cannot just add new fields without copying old ones.
|
|
347
|
+
lengths: {
|
|
348
|
+
seed?: number;
|
|
349
|
+
public?: number;
|
|
350
|
+
secret?: number;
|
|
351
|
+
signRand?: number;
|
|
352
|
+
signature?: number;
|
|
353
|
+
};
|
|
354
|
+
sign: (msg: Uint8Array, secretKey: Uint8Array) => Uint8Array;
|
|
355
|
+
verify: (sig: Uint8Array, msg: Uint8Array, publicKey: Uint8Array) => boolean;
|
|
356
|
+
}
|