@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.
Files changed (211) hide show
  1. package/README.md +267 -421
  2. package/abstract/bls.d.ts +49 -111
  3. package/abstract/bls.d.ts.map +1 -1
  4. package/abstract/bls.js +108 -152
  5. package/abstract/bls.js.map +1 -1
  6. package/abstract/curve.d.ts +7 -48
  7. package/abstract/curve.d.ts.map +1 -1
  8. package/abstract/curve.js +22 -47
  9. package/abstract/curve.js.map +1 -1
  10. package/abstract/edwards.d.ts +17 -68
  11. package/abstract/edwards.d.ts.map +1 -1
  12. package/abstract/edwards.js +98 -175
  13. package/abstract/edwards.js.map +1 -1
  14. package/abstract/fft.js +14 -27
  15. package/abstract/fft.js.map +1 -1
  16. package/abstract/hash-to-curve.d.ts +11 -24
  17. package/abstract/hash-to-curve.d.ts.map +1 -1
  18. package/abstract/hash-to-curve.js +30 -35
  19. package/abstract/hash-to-curve.js.map +1 -1
  20. package/abstract/modular.d.ts +5 -17
  21. package/abstract/modular.d.ts.map +1 -1
  22. package/abstract/modular.js +166 -167
  23. package/abstract/modular.js.map +1 -1
  24. package/abstract/montgomery.d.ts +4 -9
  25. package/abstract/montgomery.d.ts.map +1 -1
  26. package/abstract/montgomery.js +17 -20
  27. package/abstract/montgomery.js.map +1 -1
  28. package/abstract/oprf.d.ts +282 -0
  29. package/abstract/oprf.d.ts.map +1 -0
  30. package/abstract/oprf.js +297 -0
  31. package/abstract/oprf.js.map +1 -0
  32. package/abstract/poseidon.js +20 -24
  33. package/abstract/poseidon.js.map +1 -1
  34. package/abstract/tower.d.ts +9 -7
  35. package/abstract/tower.d.ts.map +1 -1
  36. package/abstract/tower.js +600 -364
  37. package/abstract/tower.js.map +1 -1
  38. package/abstract/weierstrass.d.ts +12 -145
  39. package/abstract/weierstrass.d.ts.map +1 -1
  40. package/abstract/weierstrass.js +153 -377
  41. package/abstract/weierstrass.js.map +1 -1
  42. package/bls12-381.d.ts +2 -2
  43. package/bls12-381.d.ts.map +1 -1
  44. package/bls12-381.js +174 -216
  45. package/bls12-381.js.map +1 -1
  46. package/bn254.d.ts +58 -10
  47. package/bn254.d.ts.map +1 -1
  48. package/bn254.js +70 -130
  49. package/bn254.js.map +1 -1
  50. package/ed25519.d.ts +12 -31
  51. package/ed25519.d.ts.map +1 -1
  52. package/ed25519.js +104 -146
  53. package/ed25519.js.map +1 -1
  54. package/ed448.d.ts +14 -33
  55. package/ed448.d.ts.map +1 -1
  56. package/ed448.js +105 -132
  57. package/ed448.js.map +1 -1
  58. package/index.js +1 -1
  59. package/misc.d.ts +10 -14
  60. package/misc.d.ts.map +1 -1
  61. package/misc.js +51 -60
  62. package/misc.js.map +1 -1
  63. package/nist.d.ts +11 -14
  64. package/nist.d.ts.map +1 -1
  65. package/nist.js +46 -55
  66. package/nist.js.map +1 -1
  67. package/package.json +9 -224
  68. package/secp256k1.d.ts +7 -23
  69. package/secp256k1.d.ts.map +1 -1
  70. package/secp256k1.js +72 -83
  71. package/secp256k1.js.map +1 -1
  72. package/src/abstract/bls.ts +197 -344
  73. package/src/abstract/curve.ts +10 -83
  74. package/src/abstract/edwards.ts +96 -223
  75. package/src/abstract/hash-to-curve.ts +32 -45
  76. package/src/abstract/modular.ts +144 -130
  77. package/src/abstract/montgomery.ts +21 -22
  78. package/src/abstract/oprf.ts +600 -0
  79. package/src/abstract/tower.ts +627 -382
  80. package/src/abstract/weierstrass.ts +101 -482
  81. package/src/bls12-381.ts +148 -176
  82. package/src/bn254.ts +67 -122
  83. package/src/ed25519.ts +65 -118
  84. package/src/ed448.ts +63 -113
  85. package/src/index.ts +1 -1
  86. package/src/misc.ts +66 -49
  87. package/src/nist.ts +48 -57
  88. package/src/secp256k1.ts +56 -88
  89. package/src/utils.ts +41 -61
  90. package/src/webcrypto.ts +362 -0
  91. package/utils.d.ts +28 -19
  92. package/utils.d.ts.map +1 -1
  93. package/utils.js +45 -121
  94. package/utils.js.map +1 -1
  95. package/webcrypto.d.ts +47 -0
  96. package/webcrypto.d.ts.map +1 -0
  97. package/webcrypto.js +231 -0
  98. package/webcrypto.js.map +1 -0
  99. package/esm/_shortw_utils.d.ts +0 -19
  100. package/esm/_shortw_utils.d.ts.map +0 -1
  101. package/esm/_shortw_utils.js +0 -16
  102. package/esm/_shortw_utils.js.map +0 -1
  103. package/esm/abstract/bls.d.ts +0 -190
  104. package/esm/abstract/bls.d.ts.map +0 -1
  105. package/esm/abstract/bls.js +0 -408
  106. package/esm/abstract/bls.js.map +0 -1
  107. package/esm/abstract/curve.d.ts +0 -231
  108. package/esm/abstract/curve.d.ts.map +0 -1
  109. package/esm/abstract/curve.js +0 -465
  110. package/esm/abstract/curve.js.map +0 -1
  111. package/esm/abstract/edwards.d.ts +0 -237
  112. package/esm/abstract/edwards.d.ts.map +0 -1
  113. package/esm/abstract/edwards.js +0 -632
  114. package/esm/abstract/edwards.js.map +0 -1
  115. package/esm/abstract/fft.d.ts +0 -122
  116. package/esm/abstract/fft.d.ts.map +0 -1
  117. package/esm/abstract/fft.js +0 -425
  118. package/esm/abstract/fft.js.map +0 -1
  119. package/esm/abstract/hash-to-curve.d.ts +0 -102
  120. package/esm/abstract/hash-to-curve.d.ts.map +0 -1
  121. package/esm/abstract/hash-to-curve.js +0 -203
  122. package/esm/abstract/hash-to-curve.js.map +0 -1
  123. package/esm/abstract/modular.d.ts +0 -171
  124. package/esm/abstract/modular.d.ts.map +0 -1
  125. package/esm/abstract/modular.js +0 -530
  126. package/esm/abstract/modular.js.map +0 -1
  127. package/esm/abstract/montgomery.d.ts +0 -30
  128. package/esm/abstract/montgomery.d.ts.map +0 -1
  129. package/esm/abstract/montgomery.js +0 -157
  130. package/esm/abstract/montgomery.js.map +0 -1
  131. package/esm/abstract/poseidon.d.ts +0 -68
  132. package/esm/abstract/poseidon.d.ts.map +0 -1
  133. package/esm/abstract/poseidon.js +0 -296
  134. package/esm/abstract/poseidon.js.map +0 -1
  135. package/esm/abstract/tower.d.ts +0 -93
  136. package/esm/abstract/tower.d.ts.map +0 -1
  137. package/esm/abstract/tower.js +0 -502
  138. package/esm/abstract/tower.js.map +0 -1
  139. package/esm/abstract/utils.d.ts +0 -5
  140. package/esm/abstract/utils.d.ts.map +0 -1
  141. package/esm/abstract/utils.js +0 -7
  142. package/esm/abstract/utils.js.map +0 -1
  143. package/esm/abstract/weierstrass.d.ts +0 -412
  144. package/esm/abstract/weierstrass.d.ts.map +0 -1
  145. package/esm/abstract/weierstrass.js +0 -1428
  146. package/esm/abstract/weierstrass.js.map +0 -1
  147. package/esm/bls12-381.d.ts +0 -16
  148. package/esm/bls12-381.d.ts.map +0 -1
  149. package/esm/bls12-381.js +0 -738
  150. package/esm/bls12-381.js.map +0 -1
  151. package/esm/bn254.d.ts +0 -18
  152. package/esm/bn254.d.ts.map +0 -1
  153. package/esm/bn254.js +0 -246
  154. package/esm/bn254.js.map +0 -1
  155. package/esm/ed25519.d.ts +0 -106
  156. package/esm/ed25519.d.ts.map +0 -1
  157. package/esm/ed25519.js +0 -467
  158. package/esm/ed25519.js.map +0 -1
  159. package/esm/ed448.d.ts +0 -101
  160. package/esm/ed448.d.ts.map +0 -1
  161. package/esm/ed448.js +0 -448
  162. package/esm/ed448.js.map +0 -1
  163. package/esm/index.d.ts +0 -2
  164. package/esm/index.d.ts.map +0 -1
  165. package/esm/index.js +0 -17
  166. package/esm/index.js.map +0 -1
  167. package/esm/jubjub.d.ts +0 -12
  168. package/esm/jubjub.d.ts.map +0 -1
  169. package/esm/jubjub.js +0 -12
  170. package/esm/jubjub.js.map +0 -1
  171. package/esm/misc.d.ts +0 -19
  172. package/esm/misc.d.ts.map +0 -1
  173. package/esm/misc.js +0 -109
  174. package/esm/misc.js.map +0 -1
  175. package/esm/nist.d.ts +0 -21
  176. package/esm/nist.d.ts.map +0 -1
  177. package/esm/nist.js +0 -132
  178. package/esm/nist.js.map +0 -1
  179. package/esm/p256.d.ts +0 -16
  180. package/esm/p256.d.ts.map +0 -1
  181. package/esm/p256.js +0 -16
  182. package/esm/p256.js.map +0 -1
  183. package/esm/p384.d.ts +0 -16
  184. package/esm/p384.d.ts.map +0 -1
  185. package/esm/p384.js +0 -16
  186. package/esm/p384.js.map +0 -1
  187. package/esm/p521.d.ts +0 -16
  188. package/esm/p521.d.ts.map +0 -1
  189. package/esm/p521.js +0 -16
  190. package/esm/p521.js.map +0 -1
  191. package/esm/package.json +0 -4
  192. package/esm/pasta.d.ts +0 -10
  193. package/esm/pasta.d.ts.map +0 -1
  194. package/esm/pasta.js +0 -10
  195. package/esm/pasta.js.map +0 -1
  196. package/esm/secp256k1.d.ts +0 -89
  197. package/esm/secp256k1.d.ts.map +0 -1
  198. package/esm/secp256k1.js +0 -292
  199. package/esm/secp256k1.js.map +0 -1
  200. package/esm/utils.d.ts +0 -110
  201. package/esm/utils.d.ts.map +0 -1
  202. package/esm/utils.js +0 -322
  203. package/esm/utils.js.map +0 -1
  204. package/src/_shortw_utils.ts +0 -21
  205. package/src/abstract/utils.ts +0 -7
  206. package/src/jubjub.ts +0 -12
  207. package/src/p256.ts +0 -15
  208. package/src/p384.ts +0 -15
  209. package/src/p521.ts +0 -15
  210. package/src/package.json +0 -3
  211. 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
- export const p256: CurveFnWithCreate = createCurve(
90
- { ...p256_CURVE, Fp: Fp256, lowS: false },
91
- sha256
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> = /* @__PURE__ */ (() => {
93
+ export const p256_hasher: H2CHasher<WeierstrassPointCons<bigint>> = /* @__PURE__ */ (() => {
95
94
  return createHasher(
96
- p256.Point,
97
- createSWU(p256.Point, {
95
+ p256_Point,
96
+ createSWU(p256_Point, {
98
97
  A: p256_CURVE.a,
99
98
  B: p256_CURVE.b,
100
- Z: p256.Point.Fp.create(BigInt('-10')),
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
- // export const p256_oprf: OPRF = createORPF({
115
- // name: 'P256-SHA256',
116
- // Point: p256.Point,
117
- // hash: sha256,
118
- // hashToGroup: p256_hasher.hashToCurve,
119
- // hashToScalar: p256_hasher.hashToScalar,
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: CurveFnWithCreate = createCurve(
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> = /* @__PURE__ */ (() => {
126
+ export const p384_hasher: H2CHasher<WeierstrassPointCons<bigint>> = /* @__PURE__ */ (() => {
129
127
  return createHasher(
130
- p384.Point,
131
- createSWU(p384.Point, {
128
+ p384_Point,
129
+ createSWU(p384_Point, {
132
130
  A: p384_CURVE.a,
133
131
  B: p384_CURVE.b,
134
- Z: p384.Point.Fp.create(BigInt('-12')),
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
- // export const p384_oprf: OPRF = createORPF({
149
- // name: 'P384-SHA384',
150
- // Point: p384.Point,
151
- // hash: sha384,
152
- // hashToGroup: p384_hasher.hashToCurve,
153
- // hashToScalar: p384_hasher.hashToScalar,
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
- // const Fn521 = Field(p521_CURVE.n, { allowedScalarLengths: [65, 66] });
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: CurveFnWithCreate = createCurve(
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> = /* @__PURE__ */ (() => {
161
+ export const p521_hasher: H2CHasher<WeierstrassPointCons<bigint>> = /* @__PURE__ */ (() => {
172
162
  return createHasher(
173
- p521.Point,
174
- createSWU(p521.Point, {
163
+ p521_Point,
164
+ createSWU(p521_Point, {
175
165
  A: p521_CURVE.a,
176
166
  B: p521_CURVE.b,
177
- Z: p521.Point.Fp.create(BigInt('-4')),
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
- // export const p521_oprf: OPRF = createORPF({
192
- // name: 'P521-SHA512',
193
- // Point: p521.Point,
194
- // hash: sha512,
195
- // hashToGroup: p521_hasher.hashToCurve,
196
- // hashToScalar: p521_hasher.hashToScalar, // produces L=98 just like in RFC
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
- createHasher,
15
- type H2CHasher,
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 type { Hex, PrivKey } from './utils.ts';
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
- // `Point.BASE.multiply(Point.Fn.inv(2n, N)).toAffine().x`
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
- export const secp256k1: CurveFnWithCreate = createCurve(
109
- { ...secp256k1_CURVE, Fp: Fpk1, lowS: true, endo: secp256k1_ENDO },
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(utf8ToBytes(tag));
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: PrivKey) {
137
- // TODO: replace with Point.Fn.fromBytes(priv)
138
- let d_ = _normFnElement(Point.Fn, priv);
139
- let p = Point.BASE.multiply(d_); // P = d'⋅G; 0 < d' < n check is done inside
140
- const scalar = hasEven(p.y) ? d_ : modN(-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
- aInRange('x', x, _1n, secp256k1_CURVE.p); // Fail if x ≥ p.
149
- const xx = modP(x * x);
150
- const c = modP(xx * x + BigInt(7)); // Let c = x³ + 7 mod p.
151
- let y = sqrtMod(c); // Let y = c^(p+1)/4 mod p.
152
- if (!hasEven(y)) y = modP(-y); // Return the unique point P such that x(P) = x and
153
- const p = Point.fromAffine({ x, y }); // y(P) = y if y mod 2 = 0 or y(P) = p-y otherwise.
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 = + 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 modN(num(taggedHash('BIP0340/challenge', ...args)));
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: Hex): Uint8Array {
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(message: Hex, secretKey: PrivKey, auxRand: Hex = randomBytes(32)): Uint8Array {
177
- const m = ensureBytes('message', message);
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 = ensureBytes('auxRand', auxRand, 32); // Auxiliary random data a: a 32-byte array
180
- const t = numTo32b(d ^ num(taggedHash('BIP0340/aux', a))); // Let t be the byte-wise xor of bytes(d) and hash/aux(a)
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
- const k_ = modN(num(rand)); // Let k' = int(rand) mod n
183
- if (k_ === _0n) throw new Error('sign failed: k is zero'); // Fail if k' = 0.
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(numTo32b(modN(k + e * d)), 32);
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: Hex, message: Hex, publicKey: Hex): boolean {
199
- const sig = ensureBytes('signature', signature, 64);
200
- const m = ensureBytes('message', message);
201
- const pub = ensureBytes('publicKey', publicKey, 32);
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(numTo32b(r), pointToBytes(P), m); // int(challenge(bytes(r)||bytes(P)||m))%n
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 = Point.BASE.multiplyUnsafe(s).add(P.multiplyUnsafe(modN(-e)));
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: 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
- secret: size,
288
- public: size,
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> = /* @__PURE__ */ (() =>
313
+ export const secp256k1_hasher: H2CHasher<WeierstrassPointCons<bigint>> = /* @__PURE__ */ (() =>
338
314
  createHasher(
339
- secp256k1.Point,
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
- export type Hex = Uint8Array | string; // hex strings are accepted for simplicity
27
- export type PrivKey = Hex | bigint; // bigints are accepted to ease learning curve
27
+
28
28
  export type CHash = {
29
- (message: Uint8Array | string): 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 | string) => 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
- // tmp name until v2
50
- /** Asserts something is Uint8Array. */
51
- export function _abytes2(value: Uint8Array, length?: number, title: string = ''): Uint8Array {
52
- const bytes = isBytes_(value);
53
- const len = value?.length;
54
- const needsLen = length !== undefined;
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
- return hexToBytes_(n.toString(16).padStart(len * 2, '0'));
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
+ }