@noble/curves 1.9.7 → 2.0.0-beta.2
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 +520 -505
- package/abstract/bls.d.ts +58 -120
- 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 +18 -54
- package/abstract/curve.d.ts.map +1 -1
- package/abstract/curve.js +30 -49
- package/abstract/curve.js.map +1 -1
- package/abstract/edwards.d.ts +18 -77
- package/abstract/edwards.d.ts.map +1 -1
- package/abstract/edwards.js +68 -144
- 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 +35 -47
- package/abstract/hash-to-curve.d.ts.map +1 -1
- package/abstract/hash-to-curve.js +42 -46
- 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 +170 -169
- package/abstract/modular.js.map +1 -1
- package/abstract/montgomery.d.ts +7 -12
- package/abstract/montgomery.d.ts.map +1 -1
- package/abstract/montgomery.js +22 -29
- 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.d.ts.map +1 -1
- package/abstract/poseidon.js +26 -31
- package/abstract/poseidon.js.map +1 -1
- package/abstract/tower.d.ts.map +1 -1
- package/abstract/tower.js +43 -19
- package/abstract/tower.js.map +1 -1
- package/abstract/weierstrass.d.ts +77 -168
- package/abstract/weierstrass.d.ts.map +1 -1
- package/abstract/weierstrass.js +184 -389
- package/abstract/weierstrass.js.map +1 -1
- package/bls12-381.d.ts +5 -11
- package/bls12-381.d.ts.map +1 -1
- package/bls12-381.js +161 -181
- package/bls12-381.js.map +1 -1
- package/bn254.d.ts +59 -11
- package/bn254.d.ts.map +1 -1
- package/bn254.js +69 -97
- package/bn254.js.map +1 -1
- package/ed25519.d.ts +33 -48
- package/ed25519.d.ts.map +1 -1
- package/ed25519.js +147 -161
- package/ed25519.js.map +1 -1
- package/ed448.d.ts +27 -36
- package/ed448.d.ts.map +1 -1
- package/ed448.js +143 -164
- package/ed448.js.map +1 -1
- package/index.d.ts +1 -0
- package/index.js +20 -4
- package/index.js.map +1 -1
- package/misc.d.ts +10 -14
- package/misc.d.ts.map +1 -1
- package/misc.js +53 -62
- package/misc.js.map +1 -1
- package/nist.d.ts +31 -16
- package/nist.d.ts.map +1 -1
- package/nist.js +75 -64
- package/nist.js.map +1 -1
- package/package.json +20 -234
- package/secp256k1.d.ts +17 -30
- package/secp256k1.d.ts.map +1 -1
- package/secp256k1.js +59 -73
- package/secp256k1.js.map +1 -1
- package/src/abstract/bls.ts +207 -354
- package/src/abstract/curve.ts +25 -84
- package/src/abstract/edwards.ts +68 -193
- package/src/abstract/hash-to-curve.ts +71 -85
- package/src/abstract/modular.ts +150 -134
- package/src/abstract/montgomery.ts +28 -35
- package/src/abstract/oprf.ts +600 -0
- package/src/abstract/poseidon.ts +6 -8
- package/src/abstract/tower.ts +0 -3
- package/src/abstract/weierstrass.ts +203 -525
- package/src/bls12-381.ts +133 -139
- package/src/bn254.ts +69 -93
- package/src/ed25519.ts +106 -133
- package/src/ed448.ts +111 -138
- package/src/index.ts +19 -3
- package/src/misc.ts +68 -51
- package/src/nist.ts +77 -70
- package/src/secp256k1.ts +46 -81
- package/src/utils.ts +67 -137
- package/src/webcrypto.ts +403 -0
- package/utils.d.ts +31 -38
- package/utils.d.ts.map +1 -1
- package/utils.js +66 -185
- package/utils.js.map +1 -1
- package/webcrypto.d.ts +99 -0
- package/webcrypto.d.ts.map +1 -0
- package/webcrypto.js +256 -0
- package/webcrypto.js.map +1 -0
- package/_shortw_utils.d.ts +0 -19
- package/_shortw_utils.d.ts.map +0 -1
- package/_shortw_utils.js +0 -20
- package/_shortw_utils.js.map +0 -1
- package/abstract/utils.d.ts +0 -78
- package/abstract/utils.d.ts.map +0 -1
- package/abstract/utils.js +0 -73
- package/abstract/utils.js.map +0 -1
- 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 -243
- package/esm/abstract/edwards.d.ts.map +0 -1
- package/esm/abstract/edwards.js +0 -627
- 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 -95
- package/esm/abstract/tower.d.ts.map +0 -1
- package/esm/abstract/tower.js +0 -714
- package/esm/abstract/tower.js.map +0 -1
- package/esm/abstract/utils.d.ts +0 -78
- package/esm/abstract/utils.d.ts.map +0 -1
- package/esm/abstract/utils.js +0 -70
- package/esm/abstract/utils.js.map +0 -1
- package/esm/abstract/weierstrass.d.ts +0 -416
- package/esm/abstract/weierstrass.d.ts.map +0 -1
- package/esm/abstract/weierstrass.js +0 -1413
- 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 -705
- 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 -214
- 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 -100
- package/esm/ed448.d.ts.map +0 -1
- package/esm/ed448.js +0 -459
- 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 -294
- 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/jubjub.d.ts +0 -12
- package/jubjub.d.ts.map +0 -1
- package/jubjub.js +0 -15
- package/jubjub.js.map +0 -1
- package/p256.d.ts +0 -16
- package/p256.d.ts.map +0 -1
- package/p256.js +0 -13
- package/p256.js.map +0 -1
- package/p384.d.ts +0 -16
- package/p384.d.ts.map +0 -1
- package/p384.js +0 -13
- package/p384.js.map +0 -1
- package/p521.d.ts +0 -16
- package/p521.d.ts.map +0 -1
- package/p521.js +0 -13
- package/p521.js.map +0 -1
- package/pasta.d.ts +0 -10
- package/pasta.d.ts.map +0 -1
- package/pasta.js +0 -13
- package/pasta.js.map +0 -1
- package/src/_shortw_utils.ts +0 -21
- package/src/abstract/utils.ts +0 -80
- 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/webcrypto.ts
ADDED
|
@@ -0,0 +1,403 @@
|
|
|
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
|
+
- PKCS8 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
|
+
|
|
41
|
+
/** Raw type */
|
|
42
|
+
const TYPE_RAW = 'raw';
|
|
43
|
+
const TYPE_JWK = 'jwk';
|
|
44
|
+
const TYPE_SPKI = 'spki';
|
|
45
|
+
const TYPE_PKCS = 'pkcs8';
|
|
46
|
+
export type WebCryptoFormat =
|
|
47
|
+
| typeof TYPE_RAW
|
|
48
|
+
| typeof TYPE_JWK
|
|
49
|
+
| typeof TYPE_SPKI
|
|
50
|
+
| typeof TYPE_PKCS;
|
|
51
|
+
/** WebCrypto keys can be in raw, jwk, pkcs8/spki formats. Raw is internal and fragile. */
|
|
52
|
+
export type WebCryptoOpts = {
|
|
53
|
+
formatSec?: WebCryptoFormat;
|
|
54
|
+
formatPub?: WebCryptoFormat;
|
|
55
|
+
};
|
|
56
|
+
// default formats
|
|
57
|
+
const dfsec = TYPE_PKCS;
|
|
58
|
+
const dfpub = TYPE_SPKI;
|
|
59
|
+
|
|
60
|
+
function getSubtle(): any {
|
|
61
|
+
const s: any = globalThis?.crypto?.subtle;
|
|
62
|
+
if (typeof s === 'object' && s != null) return s;
|
|
63
|
+
throw new Error('crypto.subtle must be defined');
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function createKeygenA(randomSecretKey: any, getPublicKey: any) {
|
|
67
|
+
return async function keygenA(_seed?: Uint8Array) {
|
|
68
|
+
const secretKey = await randomSecretKey();
|
|
69
|
+
return { secretKey, publicKey: await getPublicKey(secretKey) };
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
function hexToBytesUns(hex: string): Uint8Array {
|
|
74
|
+
return Uint8Array.from(hex.match(/(\w\w)/g)!, (b) => Number.parseInt(b, 16));
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Trying to do generics here creates hell on conversion and usage
|
|
78
|
+
type JsonWebKey = {
|
|
79
|
+
crv?: string;
|
|
80
|
+
d?: string;
|
|
81
|
+
kty?: string;
|
|
82
|
+
x?: string;
|
|
83
|
+
y?: string;
|
|
84
|
+
[key: string]: unknown;
|
|
85
|
+
};
|
|
86
|
+
type Key = JsonWebKey | Uint8Array;
|
|
87
|
+
type CryptoKey = Awaited<ReturnType<typeof crypto.subtle.importKey>>;
|
|
88
|
+
type KeyUsage = 'deriveBits' | 'deriveKey' | 'sign' | 'verify';
|
|
89
|
+
type Algo = string | { name: string; namedCurve: string };
|
|
90
|
+
type SigAlgo = string | { name: string; hash?: { name: string } };
|
|
91
|
+
|
|
92
|
+
type KeyUtils = {
|
|
93
|
+
import(key: Key, format?: WebCryptoFormat): Promise<CryptoKey>;
|
|
94
|
+
export(key: CryptoKey, format?: WebCryptoFormat): Promise<Key>;
|
|
95
|
+
convert(key: Key, inFormat?: WebCryptoFormat, outFormat?: WebCryptoFormat): Promise<Key>;
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
function assertType(type: 'private' | 'public', key: any) {
|
|
99
|
+
if (key.type !== type) throw new Error(`invalid key type, expected ${type}`);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function createKeyUtils(algo: Algo, derive: boolean, keyLen: number, pkcs8header: string) {
|
|
103
|
+
const secUsage: KeyUsage[] = derive ? ['deriveBits'] : ['sign'];
|
|
104
|
+
const pubUsage: KeyUsage[] = derive ? [] : ['verify'];
|
|
105
|
+
// Return Uint8Array instead of ArrayBuffer
|
|
106
|
+
const arrBufToU8 = (res: Key, format: WebCryptoFormat) =>
|
|
107
|
+
format === TYPE_JWK ? res : new Uint8Array(res as unknown as ArrayBuffer);
|
|
108
|
+
const pub: KeyUtils = {
|
|
109
|
+
async import(key: Key, format: WebCryptoFormat): Promise<CryptoKey> {
|
|
110
|
+
const keyi: CryptoKey = await getSubtle().importKey(format, key, algo, true, pubUsage);
|
|
111
|
+
assertType('public', keyi);
|
|
112
|
+
return keyi;
|
|
113
|
+
},
|
|
114
|
+
async export(key: CryptoKey, format: WebCryptoFormat): Promise<Key> {
|
|
115
|
+
assertType('public', key);
|
|
116
|
+
const keyi = await getSubtle().exportKey(format, key);
|
|
117
|
+
return arrBufToU8(keyi, format);
|
|
118
|
+
},
|
|
119
|
+
async convert(key: Key, inFormat: WebCryptoFormat, outFormat: WebCryptoFormat): Promise<Key> {
|
|
120
|
+
return pub.export(await pub.import(key, inFormat), outFormat);
|
|
121
|
+
},
|
|
122
|
+
};
|
|
123
|
+
const priv: KeyUtils = {
|
|
124
|
+
async import(key: Key, format: WebCryptoFormat): Promise<CryptoKey> {
|
|
125
|
+
const crypto = getSubtle();
|
|
126
|
+
let keyi: CryptoKey;
|
|
127
|
+
if (format === TYPE_RAW) {
|
|
128
|
+
// Chrome, node, bun, deno: works
|
|
129
|
+
// Safari, Firefox: Data provided to an operation does not meet requirements
|
|
130
|
+
// This is the best one can do. JWK can't be used: it contains public key component inside.
|
|
131
|
+
const k = key as Uint8Array;
|
|
132
|
+
const head = hexToBytesUns(pkcs8header);
|
|
133
|
+
const all = new Uint8Array(head.length + k.length);
|
|
134
|
+
all.set(head, 0);
|
|
135
|
+
all.set(k, head.length);
|
|
136
|
+
|
|
137
|
+
keyi = await crypto.importKey(TYPE_PKCS, all, algo, true, secUsage);
|
|
138
|
+
} else {
|
|
139
|
+
// Fix import of ECDSA keys into ECDH, other formats are ok
|
|
140
|
+
if (derive && format === TYPE_JWK) key = { ...key, key_ops: secUsage };
|
|
141
|
+
keyi = await crypto.importKey(format, key, algo, true, secUsage);
|
|
142
|
+
}
|
|
143
|
+
assertType('private', keyi);
|
|
144
|
+
return keyi;
|
|
145
|
+
},
|
|
146
|
+
async export(key: CryptoKey, format: WebCryptoFormat): Promise<Key> {
|
|
147
|
+
const crypto = getSubtle();
|
|
148
|
+
assertType('private', key);
|
|
149
|
+
if (format === TYPE_RAW) {
|
|
150
|
+
// scure-base base64urlnopad could have been used, but we can't add more deps.
|
|
151
|
+
// pkcs8 would be even more fragile
|
|
152
|
+
const jwk = await crypto.exportKey(TYPE_JWK, key);
|
|
153
|
+
const base64 = jwk.d.replace(/-/g, '+').replace(/_/g, '/'); // base64url
|
|
154
|
+
const pad = base64.length % 4 ? '='.repeat(4 - (base64.length % 4)) : ''; // add padding
|
|
155
|
+
const binary = atob(base64 + pad);
|
|
156
|
+
// This is not ASCII, and not text: this is only semi-safe with atob output
|
|
157
|
+
const raw = Uint8Array.from(binary, (c) => c.charCodeAt(0));
|
|
158
|
+
// Pad key to key len because Bun strips leading zero for P-521 only
|
|
159
|
+
const res = new Uint8Array(keyLen);
|
|
160
|
+
res.set(raw, keyLen - raw.length);
|
|
161
|
+
return res as Key;
|
|
162
|
+
}
|
|
163
|
+
const keyi = await crypto.exportKey(format, key);
|
|
164
|
+
return arrBufToU8(keyi, format);
|
|
165
|
+
},
|
|
166
|
+
async convert(key: Key, inFormat: WebCryptoFormat, outFormat: WebCryptoFormat): Promise<Key> {
|
|
167
|
+
return priv.export(await priv.import(key, inFormat), outFormat);
|
|
168
|
+
},
|
|
169
|
+
};
|
|
170
|
+
async function getPublicKey(secretKey: Key, opts: WebCryptoOpts = {}): Promise<Key> {
|
|
171
|
+
const fsec = opts.formatSec ?? dfsec;
|
|
172
|
+
const fpub = opts.formatPub ?? dfpub;
|
|
173
|
+
// Export to jwk, remove private scalar and then convert to format
|
|
174
|
+
const jwk = (
|
|
175
|
+
fsec === TYPE_JWK ? { ...secretKey } : await priv.convert(secretKey, fsec, TYPE_JWK)
|
|
176
|
+
) as JsonWebKey;
|
|
177
|
+
delete jwk.d;
|
|
178
|
+
jwk.key_ops = pubUsage;
|
|
179
|
+
if (fpub === TYPE_JWK) return jwk;
|
|
180
|
+
return pub.convert(jwk, TYPE_JWK, fpub);
|
|
181
|
+
}
|
|
182
|
+
async function randomSecretKey(format: WebCryptoFormat = dfsec): Promise<Key> {
|
|
183
|
+
const keyPair = await getSubtle().generateKey(algo, true, secUsage);
|
|
184
|
+
return priv.export(keyPair.privateKey, format);
|
|
185
|
+
}
|
|
186
|
+
// Key generation could be slow, so we cache result once.
|
|
187
|
+
let supported: boolean | undefined;
|
|
188
|
+
return {
|
|
189
|
+
pub: pub as KeyUtils,
|
|
190
|
+
priv: priv as KeyUtils,
|
|
191
|
+
async isSupported(): Promise<boolean> {
|
|
192
|
+
if (supported !== undefined) return supported;
|
|
193
|
+
try {
|
|
194
|
+
const crypto = getSubtle();
|
|
195
|
+
const key = await crypto.generateKey(algo, true, secUsage);
|
|
196
|
+
// Deno is broken and generates key for unsupported curves, but then fails on export
|
|
197
|
+
await priv.export(key.privateKey, TYPE_JWK);
|
|
198
|
+
// Bun fails on derive for x25519, but not x448
|
|
199
|
+
if (derive) {
|
|
200
|
+
await crypto.deriveBits(
|
|
201
|
+
{ name: typeof algo === 'string' ? algo : algo.name, public: key.publicKey },
|
|
202
|
+
key.privateKey,
|
|
203
|
+
8
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
return (supported = true);
|
|
207
|
+
} catch (e) {
|
|
208
|
+
return (supported = false);
|
|
209
|
+
}
|
|
210
|
+
},
|
|
211
|
+
getPublicKey,
|
|
212
|
+
keygen: createKeygenA(randomSecretKey, getPublicKey),
|
|
213
|
+
utils: {
|
|
214
|
+
randomSecretKey,
|
|
215
|
+
convertPublicKey: pub.convert as KeyUtils['convert'],
|
|
216
|
+
convertSecretKey: priv.convert as KeyUtils['convert'],
|
|
217
|
+
},
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
function createSigner(keys: ReturnType<typeof createKeyUtils>, algo: SigAlgo): WebCryptoSigner {
|
|
222
|
+
return {
|
|
223
|
+
async sign(msgHash: Uint8Array, secretKey: Key, opts: WebCryptoOpts = {}): Promise<Uint8Array> {
|
|
224
|
+
const key = await keys.priv.import(secretKey, opts.formatSec ?? dfsec);
|
|
225
|
+
const sig = await getSubtle().sign(algo, key, msgHash);
|
|
226
|
+
return new Uint8Array(sig);
|
|
227
|
+
},
|
|
228
|
+
async verify(
|
|
229
|
+
signature: Uint8Array,
|
|
230
|
+
msgHash: Uint8Array,
|
|
231
|
+
publicKey: Key,
|
|
232
|
+
opts: WebCryptoOpts = {}
|
|
233
|
+
): Promise<boolean> {
|
|
234
|
+
const key = await keys.pub.import(publicKey, opts.formatPub ?? dfpub);
|
|
235
|
+
return await getSubtle().verify(algo, key, signature, msgHash);
|
|
236
|
+
},
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
function createECDH(
|
|
241
|
+
keys: ReturnType<typeof createKeyUtils>,
|
|
242
|
+
algo: Algo,
|
|
243
|
+
keyLen: number
|
|
244
|
+
): WebCryptoECDH {
|
|
245
|
+
return {
|
|
246
|
+
async getSharedSecret(
|
|
247
|
+
secretKeyA: Uint8Array,
|
|
248
|
+
publicKeyB: Uint8Array,
|
|
249
|
+
opts: WebCryptoOpts = {}
|
|
250
|
+
): Promise<Uint8Array> {
|
|
251
|
+
// if (_isCompressed !== true) throw new Error('WebCrypto only supports compressed keys');
|
|
252
|
+
const secKey = await keys.priv.import(secretKeyA, opts.formatSec || dfsec);
|
|
253
|
+
const pubKey = await keys.pub.import(publicKeyB, opts.formatPub || dfpub);
|
|
254
|
+
const shared = await getSubtle().deriveBits(
|
|
255
|
+
{ name: typeof algo === 'string' ? algo : algo.name, public: pubKey },
|
|
256
|
+
secKey,
|
|
257
|
+
8 * keyLen
|
|
258
|
+
);
|
|
259
|
+
return new Uint8Array(shared);
|
|
260
|
+
},
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
type WebCryptoBaseCurve = {
|
|
265
|
+
name: string;
|
|
266
|
+
isSupported(): Promise<boolean>;
|
|
267
|
+
keygen(): Promise<{ secretKey: Uint8Array; publicKey: Uint8Array }>;
|
|
268
|
+
getPublicKey(secretKey: Key, opts?: WebCryptoOpts): Promise<Key>;
|
|
269
|
+
utils: {
|
|
270
|
+
randomSecretKey: (format?: WebCryptoFormat) => Promise<Key>;
|
|
271
|
+
convertSecretKey: (
|
|
272
|
+
key: Key,
|
|
273
|
+
inFormat?: WebCryptoFormat,
|
|
274
|
+
outFormat?: WebCryptoFormat
|
|
275
|
+
) => Promise<Key>;
|
|
276
|
+
convertPublicKey: (
|
|
277
|
+
key: Key,
|
|
278
|
+
inFormat?: WebCryptoFormat,
|
|
279
|
+
outFormat?: WebCryptoFormat
|
|
280
|
+
) => Promise<Key>;
|
|
281
|
+
};
|
|
282
|
+
};
|
|
283
|
+
|
|
284
|
+
// Specific per-curve methods - no reason to export them; we can't "add" a new curve
|
|
285
|
+
export type WebCryptoSigner = {
|
|
286
|
+
sign(message: Uint8Array, secretKey: Key, opts?: WebCryptoOpts): Promise<Uint8Array>;
|
|
287
|
+
verify(
|
|
288
|
+
signature: Uint8Array,
|
|
289
|
+
message: Uint8Array,
|
|
290
|
+
publicKey: Key,
|
|
291
|
+
opts?: WebCryptoOpts
|
|
292
|
+
): Promise<boolean>;
|
|
293
|
+
};
|
|
294
|
+
export type WebCryptoECDH = {
|
|
295
|
+
getSharedSecret(secA: Uint8Array, pubB: Uint8Array, opts?: WebCryptoOpts): Promise<Uint8Array>;
|
|
296
|
+
};
|
|
297
|
+
export type WebCryptoECDSA = WebCryptoBaseCurve & WebCryptoSigner & WebCryptoECDH;
|
|
298
|
+
export type WebCryptoEdDSA = WebCryptoBaseCurve & WebCryptoSigner;
|
|
299
|
+
export type WebCryptoMontgomery = WebCryptoBaseCurve & WebCryptoECDH;
|
|
300
|
+
|
|
301
|
+
function wrapECDSA(
|
|
302
|
+
curve: 'P-256' | 'P-384' | 'P-521',
|
|
303
|
+
hash: string,
|
|
304
|
+
keyLen: number,
|
|
305
|
+
pkcs8header: string
|
|
306
|
+
): WebCryptoECDSA {
|
|
307
|
+
const ECDH_ALGO = { name: 'ECDH', namedCurve: curve };
|
|
308
|
+
const keys = createKeyUtils({ name: 'ECDSA', namedCurve: curve }, false, keyLen, pkcs8header);
|
|
309
|
+
const keysEcdh = createKeyUtils(ECDH_ALGO, true, keyLen, pkcs8header);
|
|
310
|
+
return Object.freeze({
|
|
311
|
+
name: curve,
|
|
312
|
+
isSupported: keys.isSupported,
|
|
313
|
+
getPublicKey: keys.getPublicKey,
|
|
314
|
+
keygen: createKeygenA(keys.utils.randomSecretKey, keys.getPublicKey),
|
|
315
|
+
...createSigner(keys, { name: 'ECDSA', hash: { name: hash } }),
|
|
316
|
+
...createECDH(keysEcdh, ECDH_ALGO, keyLen),
|
|
317
|
+
utils: keys.utils,
|
|
318
|
+
});
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
function wrapEdDSA(
|
|
322
|
+
curve: 'Ed25519' | 'Ed448',
|
|
323
|
+
keyLen: number,
|
|
324
|
+
pkcs8header: string
|
|
325
|
+
): WebCryptoEdDSA {
|
|
326
|
+
const keys = createKeyUtils(curve, false, keyLen, pkcs8header);
|
|
327
|
+
return Object.freeze({
|
|
328
|
+
name: curve,
|
|
329
|
+
isSupported: keys.isSupported,
|
|
330
|
+
getPublicKey: keys.getPublicKey,
|
|
331
|
+
keygen: createKeygenA(keys.utils.randomSecretKey, keys.getPublicKey),
|
|
332
|
+
...createSigner(keys, { name: curve }),
|
|
333
|
+
utils: keys.utils,
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
function wrapMontgomery(
|
|
338
|
+
curve: 'X25519' | 'X448',
|
|
339
|
+
keyLen: number,
|
|
340
|
+
pkcs8header: string
|
|
341
|
+
): WebCryptoMontgomery {
|
|
342
|
+
const keys = createKeyUtils(curve, true, keyLen, pkcs8header);
|
|
343
|
+
return Object.freeze({
|
|
344
|
+
name: curve,
|
|
345
|
+
isSupported: keys.isSupported,
|
|
346
|
+
getPublicKey: keys.getPublicKey,
|
|
347
|
+
keygen: createKeygenA(keys.utils.randomSecretKey, keys.getPublicKey),
|
|
348
|
+
...createECDH(keys, curve, keyLen),
|
|
349
|
+
utils: keys.utils,
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
/** Friendly wrapper over built-in WebCrypto NIST P-256 (secp256r1). */
|
|
354
|
+
export const p256: WebCryptoECDSA = /* @__PURE__ */ wrapECDSA(
|
|
355
|
+
'P-256',
|
|
356
|
+
'SHA-256',
|
|
357
|
+
32,
|
|
358
|
+
'3041020100301306072a8648ce3d020106082a8648ce3d030107042730250201010420'
|
|
359
|
+
);
|
|
360
|
+
|
|
361
|
+
/** Friendly wrapper over built-in WebCrypto NIST P-384 (secp384r1). */
|
|
362
|
+
export const p384: WebCryptoECDSA = /* @__PURE__ */ wrapECDSA(
|
|
363
|
+
'P-384',
|
|
364
|
+
'SHA-384',
|
|
365
|
+
48,
|
|
366
|
+
'304e020100301006072a8648ce3d020106052b81040022043730350201010430'
|
|
367
|
+
);
|
|
368
|
+
|
|
369
|
+
/** Friendly wrapper over built-in WebCrypto NIST P-521 (secp521r1). */
|
|
370
|
+
export const p521: WebCryptoECDSA = /* @__PURE__ */ wrapECDSA(
|
|
371
|
+
'P-521',
|
|
372
|
+
'SHA-512',
|
|
373
|
+
66,
|
|
374
|
+
'3060020100301006072a8648ce3d020106052b81040023044930470201010442'
|
|
375
|
+
);
|
|
376
|
+
|
|
377
|
+
/** Friendly wrapper over built-in WebCrypto ed25519. */
|
|
378
|
+
export const ed25519: WebCryptoEdDSA = /* @__PURE__ */ wrapEdDSA(
|
|
379
|
+
'Ed25519',
|
|
380
|
+
32,
|
|
381
|
+
'302e020100300506032b657004220420'
|
|
382
|
+
);
|
|
383
|
+
|
|
384
|
+
/** Friendly wrapper over built-in WebCrypto ed448. */
|
|
385
|
+
export const ed448: WebCryptoEdDSA = /* @__PURE__ */ wrapEdDSA(
|
|
386
|
+
'Ed448',
|
|
387
|
+
57,
|
|
388
|
+
'3047020100300506032b6571043b0439'
|
|
389
|
+
);
|
|
390
|
+
|
|
391
|
+
/** Friendly wrapper over built-in WebCrypto x25519 (ECDH over Curve25519). */
|
|
392
|
+
export const x25519: WebCryptoMontgomery = /* @__PURE__ */ wrapMontgomery(
|
|
393
|
+
'X25519',
|
|
394
|
+
32,
|
|
395
|
+
'302e020100300506032b656e04220420'
|
|
396
|
+
);
|
|
397
|
+
|
|
398
|
+
/** Friendly wrapper over built-in WebCrypto x448 (ECDH over Curve448). */
|
|
399
|
+
export const x448: WebCryptoMontgomery = /* @__PURE__ */ wrapMontgomery(
|
|
400
|
+
'X448',
|
|
401
|
+
56,
|
|
402
|
+
'3046020100300506032b656f043a0438'
|
|
403
|
+
);
|
package/utils.d.ts
CHANGED
|
@@ -1,19 +1,15 @@
|
|
|
1
|
-
export { abytes, anumber, bytesToHex,
|
|
2
|
-
export type Hex = Uint8Array | string;
|
|
3
|
-
export type PrivKey = Hex | bigint;
|
|
1
|
+
export { abytes, anumber, bytesToHex, concatBytes, hexToBytes, isBytes, randomBytes, } from '@noble/hashes/utils.js';
|
|
4
2
|
export type CHash = {
|
|
5
|
-
(message: 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
|
|
13
|
-
export declare function abool(
|
|
14
|
-
export declare function
|
|
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;
|
|
12
|
+
export declare function asafenumber(value: number, title?: string): void;
|
|
17
13
|
export declare function numberToHexUnpadded(num: number | bigint): string;
|
|
18
14
|
export declare function hexToNumber(hex: string): bigint;
|
|
19
15
|
export declare function bytesToNumberBE(bytes: Uint8Array): bigint;
|
|
@@ -21,16 +17,6 @@ export declare function bytesToNumberLE(bytes: Uint8Array): bigint;
|
|
|
21
17
|
export declare function numberToBytesBE(n: number | bigint, len: number): Uint8Array;
|
|
22
18
|
export declare function numberToBytesLE(n: number | bigint, len: number): Uint8Array;
|
|
23
19
|
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
20
|
export declare function equalBytes(a: Uint8Array, b: Uint8Array): boolean;
|
|
35
21
|
/**
|
|
36
22
|
* Copies Uint8Array. We can't use u8a.slice(), because u8a can be Buffer,
|
|
@@ -79,25 +65,8 @@ type Pred<T> = (v: Uint8Array) => T | undefined;
|
|
|
79
65
|
* const drbg = createHmacDRBG<Key>(32, 32, hmac);
|
|
80
66
|
* drbg(seed, bytesToKey); // bytesToKey must return Key or undefined
|
|
81
67
|
*/
|
|
82
|
-
export declare function createHmacDrbg<T>(hashLen: number, qByteLen: number, hmacFn: (key: Uint8Array,
|
|
83
|
-
declare
|
|
84
|
-
readonly bigint: (val: any) => boolean;
|
|
85
|
-
readonly function: (val: any) => boolean;
|
|
86
|
-
readonly boolean: (val: any) => boolean;
|
|
87
|
-
readonly string: (val: any) => boolean;
|
|
88
|
-
readonly stringOrUint8Array: (val: any) => boolean;
|
|
89
|
-
readonly isSafeInteger: (val: any) => boolean;
|
|
90
|
-
readonly array: (val: any) => boolean;
|
|
91
|
-
readonly field: (val: any, object: any) => any;
|
|
92
|
-
readonly hash: (val: any) => boolean;
|
|
93
|
-
};
|
|
94
|
-
type Validator = keyof typeof validatorFns;
|
|
95
|
-
type ValMap<T extends Record<string, any>> = {
|
|
96
|
-
[K in keyof T]?: Validator;
|
|
97
|
-
};
|
|
98
|
-
export declare function validateObject<T extends Record<string, any>>(object: T, validators: ValMap<T>, optValidators?: ValMap<T>): T;
|
|
99
|
-
export declare function isHash(val: CHash): boolean;
|
|
100
|
-
export declare function _validateObject(object: Record<string, any>, fields: Record<string, string>, optFields?: Record<string, string>): void;
|
|
68
|
+
export declare function createHmacDrbg<T>(hashLen: number, qByteLen: number, hmacFn: (key: Uint8Array, message: Uint8Array) => Uint8Array): (seed: Uint8Array, predicate: Pred<T>) => T;
|
|
69
|
+
export declare function validateObject(object: Record<string, any>, fields?: Record<string, string>, optFields?: Record<string, string>): void;
|
|
101
70
|
/**
|
|
102
71
|
* throws not implemented error
|
|
103
72
|
*/
|
|
@@ -107,4 +76,28 @@ export declare const notImplemented: () => never;
|
|
|
107
76
|
* Uses WeakMap: the value is going auto-cleaned by GC after last reference is removed.
|
|
108
77
|
*/
|
|
109
78
|
export declare function memoized<T extends object, R, O extends any[]>(fn: (arg: T, ...args: O) => R): (arg: T, ...args: O) => R;
|
|
79
|
+
export interface CryptoKeys {
|
|
80
|
+
lengths: {
|
|
81
|
+
seed?: number;
|
|
82
|
+
public?: number;
|
|
83
|
+
secret?: number;
|
|
84
|
+
};
|
|
85
|
+
keygen: (seed?: Uint8Array) => {
|
|
86
|
+
secretKey: Uint8Array;
|
|
87
|
+
publicKey: Uint8Array;
|
|
88
|
+
};
|
|
89
|
+
getPublicKey: (secretKey: Uint8Array) => Uint8Array;
|
|
90
|
+
}
|
|
91
|
+
/** Generic interface for signatures. Has keygen, sign and verify. */
|
|
92
|
+
export interface Signer extends CryptoKeys {
|
|
93
|
+
lengths: {
|
|
94
|
+
seed?: number;
|
|
95
|
+
public?: number;
|
|
96
|
+
secret?: number;
|
|
97
|
+
signRand?: number;
|
|
98
|
+
signature?: number;
|
|
99
|
+
};
|
|
100
|
+
sign: (msg: Uint8Array, secretKey: Uint8Array) => Uint8Array;
|
|
101
|
+
verify: (sig: Uint8Array, msg: Uint8Array, publicKey: Uint8Array) => boolean;
|
|
102
|
+
}
|
|
110
103
|
//# 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":"AAYA,OAAO,EACL,MAAM,EACN,OAAO,EACP,UAAU,EACV,WAAW,EACX,
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["src/utils.ts"],"names":[],"mappings":"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"}
|