@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
@@ -0,0 +1,362 @@
1
+ /**
2
+ * Friendly wrapper over elliptic curves from built-in WebCrypto. Experimental: API may change.
3
+
4
+ # WebCrypto issues
5
+
6
+ ## No way to get public keys
7
+
8
+ - Export of raw secret key is prohibited by spec:
9
+ - https://w3c.github.io/webcrypto/#ecdsa-operations-export-key
10
+ -> "If format is "raw":" -> "If the [[type]] internal slot of key is not "public",
11
+ then throw an InvalidAccessError."
12
+ - Import of raw secret keys is prohibited by spec:
13
+ - https://w3c.github.io/webcrypto/#ecdsa-operations-import-key
14
+ -> "If format is "raw":" -> "If usages contains a value which is not "verify"
15
+ then throw a SyntaxError."
16
+ - SPKI (Simple public-key infrastructure) is public-key-only
17
+ - PCKS8 is secret-key-only
18
+ - No way to get public key from secret key, but we convert to jwk and then create it manually, since jwk secret key is priv+pub.
19
+ - Noble supports generating keys for both sign, verify & getSharedSecret,
20
+ but JWK key includes usage, which forces us to patch it (non-JWK is ok)
21
+ - We have import/export for 'raw', but it doesn't work in Firefox / Safari
22
+
23
+ ## Point encoding
24
+
25
+ - Raw export of public points returns uncompressed points,
26
+ but this is implementation specific and not much we can do there.
27
+ - `getSharedSecret` differs for p256, p384, p521:
28
+ Noble returns 33-byte output (y-parity + x coordinate),
29
+ while in WebCrypto returns 32-byte output (x coordinate)
30
+ - `getSharedSecret` identical for X25519, X448
31
+
32
+ ## Availability
33
+
34
+ Node.js additionally supports ed448.
35
+ There seems no reasonable way to check for availability, other than actually calling methods.
36
+
37
+ * @module
38
+ */
39
+ /*! noble-curves - MIT License (c) 2022 Paul Miller (paulmillr.com) */
40
+ import { concatBytes, hexToBytes } from './utils.ts';
41
+
42
+ function getWebcryptoSubtle(): any {
43
+ const subtle: any = globalThis?.crypto?.subtle;
44
+ if (typeof subtle === 'object' && subtle != null) return subtle;
45
+ throw new Error('crypto.subtle must be defined');
46
+ }
47
+
48
+ // Trying to do generics here creates hell on conversion and usage
49
+ type JsonWebKey = {
50
+ crv?: string;
51
+ d?: string;
52
+ kty?: string;
53
+ x?: string;
54
+ y?: string;
55
+ [key: string]: unknown;
56
+ };
57
+ type Format = 'raw' | 'jwk' | 'spki' | 'pkcs8';
58
+ type Key = JsonWebKey | Uint8Array;
59
+ type CryptoKey = Awaited<ReturnType<typeof crypto.subtle.importKey>>;
60
+ type KeyUsage = 'deriveBits' | 'deriveKey' | 'sign' | 'verify';
61
+ type Algo = string | { name: string; namedCurve: string };
62
+ type SigAlgo = string | { name: string; hash?: { name: string } };
63
+
64
+ type KeyUtils = {
65
+ import(key: Key, format?: Format): Promise<CryptoKey>;
66
+ export(key: CryptoKey, format?: Format): Promise<Key>;
67
+ convert(key: Key, inFormat?: Format, outFormat?: Format): Promise<Key>;
68
+ };
69
+ export type WebCryptoGetPubOpts = {
70
+ secFormat?: Format;
71
+ pubFormat?: Format;
72
+ };
73
+ const _format = 'raw';
74
+
75
+ function assertType(type: 'private' | 'public', key: any) {
76
+ if (key.type !== type) throw new Error(`invalid key type, expected ${type}`);
77
+ }
78
+
79
+ function createKeyUtils(algo: Algo, derive: boolean, keyLen: number, pcks8header: string) {
80
+ const secUsage: KeyUsage[] = derive ? ['deriveBits'] : ['sign'];
81
+ const pubUsage: KeyUsage[] = derive ? [] : ['verify'];
82
+ // Return Uint8Array instead of ArrayBuffer
83
+ const arrBufToU8 = (res: Key, format: Format) =>
84
+ format === 'jwk' ? res : new Uint8Array(res as ArrayBuffer);
85
+ const pub: KeyUtils = {
86
+ async import(key: Key, format: Format = _format): Promise<CryptoKey> {
87
+ const crypto = getWebcryptoSubtle();
88
+ const keyi: CryptoKey = await crypto.importKey(format, key, algo, true, pubUsage);
89
+ assertType('public', keyi);
90
+ return keyi;
91
+ },
92
+ async export(key: CryptoKey, format: Format = _format): Promise<Key> {
93
+ assertType('public', key);
94
+ const crypto = getWebcryptoSubtle();
95
+ const keyi = await crypto.exportKey(format, key);
96
+ return arrBufToU8(keyi, format);
97
+ },
98
+ async convert(key: Key, inFormat: Format = _format, outFormat: Format = _format): Promise<Key> {
99
+ return pub.export(await pub.import(key, inFormat), outFormat);
100
+ },
101
+ };
102
+ const priv: KeyUtils = {
103
+ async import(key: Key, format: Format = _format): Promise<CryptoKey> {
104
+ const crypto = getWebcryptoSubtle();
105
+ let keyi: CryptoKey;
106
+ if (format === 'raw') {
107
+ // Chrome, node, bun, deno: works
108
+ // Safari, Firefox: Data provided to an operation does not meet requirements
109
+ // This is the best one can do. JWK can't be used: it contains public key component inside.
110
+ keyi = await crypto.importKey(
111
+ 'pkcs8',
112
+ concatBytes(hexToBytes(pcks8header), key as Uint8Array),
113
+ algo,
114
+ true,
115
+ secUsage
116
+ );
117
+ } else {
118
+ // Fix import of ECDSA keys into ECDH, other formats are ok
119
+ if (derive && format === 'jwk') key = { ...key, key_ops: secUsage };
120
+ keyi = await crypto.importKey(format, key, algo, true, secUsage);
121
+ }
122
+ assertType('private', keyi);
123
+ return keyi;
124
+ },
125
+ async export(key: CryptoKey, format: Format = _format): Promise<Key> {
126
+ const crypto = getWebcryptoSubtle();
127
+ assertType('private', key);
128
+ if (format === 'raw') {
129
+ // scure-base base64urlnopad could have been used, but we can't add more deps.
130
+ // pcks8 would be even more fragile
131
+ const jwk = await crypto.exportKey('jwk', key);
132
+ const base64 = jwk.d.replace(/-/g, '+').replace(/_/g, '/'); // base64url
133
+ const pad = base64.length % 4 ? '='.repeat(4 - (base64.length % 4)) : ''; // add padding
134
+ const binary = atob(base64 + pad);
135
+ // This is not ASCII, and not text: this is only semi-safe with atob output
136
+ const raw = Uint8Array.from(binary, (c) => c.charCodeAt(0));
137
+ // Pad key to key len because Bun strips leading zero for P-521 only
138
+ const res = new Uint8Array(keyLen);
139
+ res.set(raw, keyLen - raw.length);
140
+ return res as Key;
141
+ }
142
+ const keyi = await crypto.exportKey(format, key);
143
+ return arrBufToU8(keyi, format);
144
+ },
145
+ async convert(key: Key, inFormat: Format = _format, outFormat: Format = _format): Promise<Key> {
146
+ return priv.export(await priv.import(key, inFormat), outFormat);
147
+ },
148
+ };
149
+ // Key generation could be slow, so we cache result once.
150
+ let available: boolean | undefined;
151
+ return {
152
+ pub: pub as KeyUtils,
153
+ priv: priv as KeyUtils,
154
+ async isAvailable(): Promise<boolean> {
155
+ if (available !== undefined) return available;
156
+ try {
157
+ const crypto = getWebcryptoSubtle();
158
+ const key = await crypto.generateKey(algo, true, secUsage);
159
+ // Deno is broken and generates key for unsupported curves, but then fails on export
160
+ await priv.export(key.privateKey, 'jwk');
161
+ // Bun fails on derive for x25519, but not x448
162
+ if (derive) {
163
+ await crypto.deriveBits(
164
+ { name: typeof algo === 'string' ? algo : algo.name, public: key.publicKey },
165
+ key.privateKey,
166
+ 8
167
+ );
168
+ }
169
+ return (available = true);
170
+ } catch (e) {
171
+ return (available = false);
172
+ }
173
+ },
174
+ // We support different input / output formats since there is no 'spki' secret key
175
+ async getPublicKey(secretKey: Key, opts: WebCryptoGetPubOpts = {}): Promise<Key> {
176
+ const fpriv = opts.secFormat ?? _format;
177
+ const fpub = opts.pubFormat ?? fpriv;
178
+ // Export to jwk, remove private scalar and then convert to format
179
+ const jwk = (
180
+ fpriv === 'jwk' ? { ...secretKey } : await priv.convert(secretKey, fpriv, 'jwk')
181
+ ) as JsonWebKey;
182
+ delete jwk.d;
183
+ jwk.key_ops = pubUsage;
184
+ if (fpub === 'jwk') return jwk;
185
+ return pub.convert(jwk, 'jwk', fpub);
186
+ },
187
+ utils: {
188
+ async randomSecretKey(format: Format = _format): Promise<Key> {
189
+ const crypto = getWebcryptoSubtle();
190
+ const keyPair = await crypto.generateKey(algo, true, secUsage);
191
+ return priv.export(keyPair.privateKey, format);
192
+ },
193
+ convertPublicKey: pub.convert as KeyUtils['convert'],
194
+ convertSecretKey: priv.convert as KeyUtils['convert'],
195
+ },
196
+ };
197
+ }
198
+
199
+ type WebCryptoOpts = { format?: Format };
200
+
201
+ function createSigner(keys: ReturnType<typeof createKeyUtils>, algo: SigAlgo) {
202
+ return {
203
+ async sign(msgHash: Uint8Array, secretKey: Key, opts: WebCryptoOpts = {}): Promise<Uint8Array> {
204
+ const crypto = getWebcryptoSubtle();
205
+ const key = await keys.priv.import(secretKey, opts.format || _format);
206
+ const sig = await crypto.sign(algo, key, msgHash);
207
+ return new Uint8Array(sig);
208
+ },
209
+ async verify(
210
+ signature: Uint8Array,
211
+ msgHash: Uint8Array,
212
+ publicKey: Key,
213
+ opts: WebCryptoOpts = {}
214
+ ): Promise<boolean> {
215
+ const crypto = getWebcryptoSubtle();
216
+ const key = await keys.pub.import(publicKey, opts.format || _format);
217
+ return await crypto.verify(algo, key, signature, msgHash);
218
+ },
219
+ };
220
+ }
221
+
222
+ function createECDH(keys: ReturnType<typeof createKeyUtils>, algo: Algo, keyLen: number) {
223
+ return {
224
+ async getSharedSecret(
225
+ secretKeyA: Uint8Array,
226
+ publicKeyB: Uint8Array,
227
+ opts: WebCryptoOpts = {}
228
+ ): Promise<Uint8Array> {
229
+ // if (_isCompressed !== true) throw new Error('WebCrypto only supports compressed keys');
230
+ const crypto = getWebcryptoSubtle();
231
+ const secKey = await keys.priv.import(secretKeyA, opts.format || _format);
232
+ const pubKey = await keys.pub.import(publicKeyB, opts.format || _format);
233
+ const shared = await crypto.deriveBits(
234
+ { name: typeof algo === 'string' ? algo : algo.name, public: pubKey },
235
+ secKey,
236
+ 8 * keyLen
237
+ );
238
+ return new Uint8Array(shared);
239
+ },
240
+ };
241
+ }
242
+
243
+ type WebCryptoBaseCurve = {
244
+ name: string;
245
+ isAvailable(): Promise<boolean>;
246
+ getPublicKey(secretKey: Key, opts?: WebCryptoGetPubOpts): Promise<Key>;
247
+ utils: {
248
+ randomSecretKey: (format?: Format) => Promise<Key>;
249
+ convertSecretKey: (key: Key, inFormat?: Format, outFormat?: Format) => Promise<Key>;
250
+ convertPublicKey: (key: Key, inFormat?: Format, outFormat?: Format) => Promise<Key>;
251
+ };
252
+ };
253
+
254
+ // Specific per-curve methods - no reason to export them; we can't "add" a new curve
255
+ // export type WebCryptoSigner = ReturnType<typeof createSigner>;
256
+ export type WebCryptoSigner = {
257
+ sign(msgHash: Uint8Array, privateKey: Key, opts?: WebCryptoOpts): Promise<Uint8Array>;
258
+ verify(
259
+ signature: Uint8Array,
260
+ msgHash: Uint8Array,
261
+ publicKey: Key,
262
+ opts?: WebCryptoOpts
263
+ ): Promise<boolean>;
264
+ };
265
+ export type WebCryptoECDH = {
266
+ getSharedSecret(priv: Uint8Array, pub: Uint8Array, opts?: WebCryptoOpts): Promise<Uint8Array>;
267
+ };
268
+ export type WebCryptoNIST = WebCryptoBaseCurve & WebCryptoSigner & WebCryptoECDH;
269
+ export type WebCryptoEdDSA = WebCryptoBaseCurve & WebCryptoSigner;
270
+ export type WebCryptoMontgomery = WebCryptoBaseCurve & WebCryptoECDH;
271
+
272
+ function wrapNIST(
273
+ curve: 'P-256' | 'P-384' | 'P-521',
274
+ hash: string,
275
+ keyLen: number,
276
+ pcks8header: string
277
+ ): WebCryptoNIST {
278
+ const ECDH_ALGO = { name: 'ECDH', namedCurve: curve };
279
+ const keys = createKeyUtils({ name: 'ECDSA', namedCurve: curve }, false, keyLen, pcks8header);
280
+ const keysEcdh = createKeyUtils(ECDH_ALGO, true, keyLen, pcks8header);
281
+ return Object.freeze({
282
+ name: curve,
283
+ isAvailable: keys.isAvailable,
284
+ getPublicKey: keys.getPublicKey,
285
+ ...createSigner(keys, { name: 'ECDSA', hash: { name: hash } }),
286
+ ...createECDH(keysEcdh, ECDH_ALGO, keyLen),
287
+ utils: keys.utils,
288
+ });
289
+ }
290
+
291
+ function wrapEdDSA(
292
+ curve: 'Ed25519' | 'Ed448',
293
+ keyLen: number,
294
+ pcks8header: string
295
+ ): WebCryptoEdDSA {
296
+ const keys = createKeyUtils(curve, false, keyLen, pcks8header);
297
+ return Object.freeze({
298
+ name: curve,
299
+ isAvailable: keys.isAvailable,
300
+ getPublicKey: keys.getPublicKey,
301
+ ...createSigner(keys, { name: curve }),
302
+ utils: keys.utils,
303
+ });
304
+ }
305
+
306
+ function wrapMontgomery(
307
+ curve: 'X25519' | 'X448',
308
+ keyLen: number,
309
+ pcks8header: string
310
+ ): WebCryptoMontgomery {
311
+ const keys = createKeyUtils(curve, true, keyLen, pcks8header);
312
+ return Object.freeze({
313
+ name: curve,
314
+ isAvailable: keys.isAvailable,
315
+ getPublicKey: keys.getPublicKey,
316
+ ...createECDH(keys, curve, keyLen),
317
+ utils: keys.utils,
318
+ });
319
+ }
320
+
321
+ export const p256: WebCryptoNIST = /* @__PURE__ */ wrapNIST(
322
+ 'P-256',
323
+ 'SHA-256',
324
+ 32,
325
+ '3041020100301306072a8648ce3d020106082a8648ce3d030107042730250201010420'
326
+ );
327
+ export const p384: WebCryptoNIST = /* @__PURE__ */ wrapNIST(
328
+ 'P-384',
329
+ 'SHA-384',
330
+ 48,
331
+ '304e020100301006072a8648ce3d020106052b81040022043730350201010430'
332
+ );
333
+ export const p521: WebCryptoNIST = /* @__PURE__ */ wrapNIST(
334
+ 'P-521',
335
+ 'SHA-512',
336
+ 66,
337
+ '3060020100301006072a8648ce3d020106052b81040023044930470201010442'
338
+ );
339
+
340
+ export const ed25519: WebCryptoEdDSA = /* @__PURE__ */ wrapEdDSA(
341
+ 'Ed25519',
342
+ 32,
343
+ '302e020100300506032b657004220420'
344
+ );
345
+ export const ed448: WebCryptoEdDSA = /* @__PURE__ */ wrapEdDSA(
346
+ 'Ed448',
347
+ 57,
348
+ '3047020100300506032b6571043b0439'
349
+ );
350
+
351
+ export const x25519: WebCryptoMontgomery = /* @__PURE__ */ wrapMontgomery(
352
+ 'X25519',
353
+ 32,
354
+ '302e020100300506032b656e04220420'
355
+ );
356
+ export const x448: WebCryptoMontgomery = /* @__PURE__ */ wrapMontgomery(
357
+ 'X448',
358
+ 56,
359
+ '3046020100300506032b656f043a0438'
360
+ );
361
+
362
+ export const supportsWc = (a: WebCryptoBaseCurve): Promise<boolean> => a.isAvailable();
package/utils.d.ts CHANGED
@@ -1,19 +1,14 @@
1
- export { abytes, anumber, bytesToHex, bytesToUtf8, concatBytes, hexToBytes, isBytes, randomBytes, utf8ToBytes, } from '@noble/hashes/utils.js';
2
- export type Hex = Uint8Array | string;
3
- export type PrivKey = Hex | bigint;
1
+ export { abytes, anumber, bytesToHex, bytesToUtf8, concatBytes, hexToBytes, isBytes, randomBytes, utf8ToBytes } from '@noble/hashes/utils.js';
4
2
  export type CHash = {
5
- (message: Uint8Array | string): Uint8Array;
3
+ (message: Uint8Array): Uint8Array;
6
4
  blockLen: number;
7
5
  outputLen: number;
8
6
  create(opts?: {
9
7
  dkLen?: number;
10
8
  }): any;
11
9
  };
12
- export type FHash = (message: Uint8Array | string) => Uint8Array;
13
- export declare function abool(title: string, value: boolean): void;
14
- export declare function _abool2(value: boolean, title?: string): boolean;
15
- /** Asserts something is Uint8Array. */
16
- export declare function _abytes2(value: Uint8Array, length?: number, title?: string): Uint8Array;
10
+ export type FHash = (message: Uint8Array) => Uint8Array;
11
+ export declare function abool(value: boolean, title?: string): boolean;
17
12
  export declare function numberToHexUnpadded(num: number | bigint): string;
18
13
  export declare function hexToNumber(hex: string): bigint;
19
14
  export declare function bytesToNumberBE(bytes: Uint8Array): bigint;
@@ -21,16 +16,6 @@ export declare function bytesToNumberLE(bytes: Uint8Array): bigint;
21
16
  export declare function numberToBytesBE(n: number | bigint, len: number): Uint8Array;
22
17
  export declare function numberToBytesLE(n: number | bigint, len: number): Uint8Array;
23
18
  export declare function numberToVarBytesBE(n: number | bigint): Uint8Array;
24
- /**
25
- * Takes hex string or Uint8Array, converts to Uint8Array.
26
- * Validates output length.
27
- * Will throw error for other types.
28
- * @param title descriptive title for an error e.g. 'secret key'
29
- * @param hex hex string or Uint8Array
30
- * @param expectedLength optional, will compare to result array's length
31
- * @returns
32
- */
33
- export declare function ensureBytes(title: string, hex: Hex, expectedLength?: number): Uint8Array;
34
19
  export declare function equalBytes(a: Uint8Array, b: Uint8Array): boolean;
35
20
  /**
36
21
  * Copies Uint8Array. We can't use u8a.slice(), because u8a can be Buffer,
@@ -107,4 +92,28 @@ export declare const notImplemented: () => never;
107
92
  * Uses WeakMap: the value is going auto-cleaned by GC after last reference is removed.
108
93
  */
109
94
  export declare function memoized<T extends object, R, O extends any[]>(fn: (arg: T, ...args: O) => R): (arg: T, ...args: O) => R;
95
+ export interface CryptoKeys {
96
+ lengths: {
97
+ seed?: number;
98
+ public?: number;
99
+ secret?: number;
100
+ };
101
+ keygen: (seed?: Uint8Array) => {
102
+ secretKey: Uint8Array;
103
+ publicKey: Uint8Array;
104
+ };
105
+ getPublicKey: (secretKey: Uint8Array) => Uint8Array;
106
+ }
107
+ /** Generic interface for signatures. Has keygen, sign and verify. */
108
+ export interface Signer extends CryptoKeys {
109
+ lengths: {
110
+ seed?: number;
111
+ public?: number;
112
+ secret?: number;
113
+ signRand?: number;
114
+ signature?: number;
115
+ };
116
+ sign: (msg: Uint8Array, secretKey: Uint8Array) => Uint8Array;
117
+ verify: (sig: Uint8Array, msg: Uint8Array, publicKey: Uint8Array) => boolean;
118
+ }
110
119
  //# sourceMappingURL=utils.d.ts.map
package/utils.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["src/utils.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["src/utils.ts"],"names":[],"mappings":"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"}