@blamejs/pki 0.6.13 → 0.6.15
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/CHANGELOG.md +22 -1
- package/README.md +1 -1
- package/index.js +1 -1
- package/lib/acme.js +59 -815
- package/lib/asn1-der.js +7 -245
- package/lib/attrcert-sign.js +12 -260
- package/lib/attrcert-verify.js +1 -7
- package/lib/byte-reader.js +0 -8
- package/lib/byte-writer.js +0 -11
- package/lib/cbor-det.js +0 -54
- package/lib/cmc-build.js +15 -357
- package/lib/cmc-verify.js +6 -239
- package/lib/cmp-build.js +41 -317
- package/lib/cmp-session.js +73 -760
- package/lib/cmp-verify.js +32 -488
- package/lib/cms-compress.js +3 -32
- package/lib/cms-decrypt.js +29 -294
- package/lib/cms-encrypt.js +14 -234
- package/lib/cms-sign.js +29 -324
- package/lib/cms-verify.js +9 -500
- package/lib/composite-kem.js +2 -102
- package/lib/composite-sig.js +1 -77
- package/lib/constants.js +0 -249
- package/lib/crl-sign.js +9 -237
- package/lib/crl-verify.js +1 -10
- package/lib/crmf-sign.js +19 -198
- package/lib/crmf-verify.js +1 -12
- package/lib/csr-sign.js +3 -34
- package/lib/csr-verify.js +1 -12
- package/lib/ct.js +28 -253
- package/lib/edwards-point.js +10 -44
- package/lib/est.js +28 -764
- package/lib/framework-error.js +4 -182
- package/lib/guard-all.js +1 -58
- package/lib/guard-async.js +1 -36
- package/lib/guard-bytes.js +6 -650
- package/lib/guard-compress.js +5 -102
- package/lib/guard-crypto.js +1 -40
- package/lib/guard-der.js +2 -93
- package/lib/guard-encoding.js +2 -60
- package/lib/guard-header.js +1 -36
- package/lib/guard-identifier.js +7 -531
- package/lib/guard-intrinsic.js +1 -150
- package/lib/guard-json.js +10 -73
- package/lib/guard-limits.js +1 -77
- package/lib/guard-list.js +1 -49
- package/lib/guard-name.js +3 -209
- package/lib/guard-parsed.js +7 -335
- package/lib/guard-range.js +1 -71
- package/lib/guard-secret.js +1 -102
- package/lib/guard-text.js +1 -64
- package/lib/guard-time.js +1 -97
- package/lib/hpke.js +3 -105
- package/lib/http-digest.js +14 -142
- package/lib/http-retry-after.js +1 -47
- package/lib/http-transport.js +21 -131
- package/lib/inspect.js +30 -284
- package/lib/ip-utils.js +6 -47
- package/lib/jose.js +7 -142
- package/lib/key.js +2 -67
- package/lib/lint.js +9 -194
- package/lib/merkle.js +1 -27
- package/lib/mime.js +9 -82
- package/lib/ocsp-request-verify.js +1 -14
- package/lib/ocsp-verify.js +1 -82
- package/lib/ocsp.js +11 -169
- package/lib/oid.js +5 -337
- package/lib/path-validate.js +103 -1492
- package/lib/pbes2.js +2 -89
- package/lib/pkcs12-build.js +31 -379
- package/lib/pki-build.js +64 -290
- package/lib/rc2.js +2 -18
- package/lib/rfc3339.js +4 -27
- package/lib/scep.js +59 -233
- package/lib/schema-all.js +0 -122
- package/lib/schema-attrcert.js +4 -146
- package/lib/schema-c509.js +153 -802
- package/lib/schema-cmc.js +5 -220
- package/lib/schema-cmp.js +2 -223
- package/lib/schema-cms.js +13 -427
- package/lib/schema-crl.js +5 -68
- package/lib/schema-crmf.js +6 -167
- package/lib/schema-csr.js +1 -54
- package/lib/schema-csrattrs.js +2 -87
- package/lib/schema-engine.js +0 -152
- package/lib/schema-ocsp.js +0 -117
- package/lib/schema-pkcs12.js +2 -93
- package/lib/schema-pkcs8.js +3 -35
- package/lib/schema-pkix.js +24 -655
- package/lib/schema-smime.js +0 -54
- package/lib/schema-tsp.js +3 -99
- package/lib/schema-x509.js +4 -63
- package/lib/shbs.js +11 -95
- package/lib/sign-scheme.js +2 -97
- package/lib/sigstore.js +9 -169
- package/lib/sleep.js +2 -8
- package/lib/smime.js +15 -408
- package/lib/tls-cert-compress.js +0 -62
- package/lib/trust.js +19 -185
- package/lib/tsp-sign.js +16 -270
- package/lib/validator-all.js +1 -30
- package/lib/validator-attcert.js +2 -46
- package/lib/validator-cose.js +2 -153
- package/lib/validator-keydesc.js +1 -37
- package/lib/validator-sig.js +1 -46
- package/lib/validator-tls.js +1 -88
- package/lib/validator-tpm.js +19 -122
- package/lib/verify-seam.js +1 -24
- package/lib/webauthn-mds.js +3 -400
- package/lib/webauthn.js +12 -833
- package/lib/webcrypto.js +5 -485
- package/lib/x509-sign.js +4 -108
- package/package.json +1 -1
- package/sbom.cdx.json +6 -6
package/lib/key.js
CHANGED
|
@@ -18,16 +18,6 @@
|
|
|
18
18
|
* @spec RFC 5958, RFC 8018, RFC 5280
|
|
19
19
|
* @card Export / import PKCS#8 and SPKI keys and encrypt a private key under RFC 8018 PBES2.
|
|
20
20
|
*/
|
|
21
|
-
//
|
|
22
|
-
// PBES2 is composed from lib/pbes2.js (the single PBKDF2 + AES-CBC home shared with pki.cms), bound to the key
|
|
23
|
-
// namespace through the `_err` error FACTORY + the "key" domain prefix so every reject keeps a key/* code.
|
|
24
|
-
// A MAC-less PBES2-CBC decrypt is not a padding oracle (RFC 8018 sec. 8): every post-derivation failure
|
|
25
|
-
// (a bad PKCS#7 pad, or a valid pad that does not re-parse as a PrivateKeyInfo) collapses into one uniform
|
|
26
|
-
// key/decrypt-failed; the structural pre-derivation faults (a non-PBKDF2 KDF, a non-AES-CBC scheme, an
|
|
27
|
-
// over-cap salt / iteration count, a wrong-length IV, a malformed parameter SEQUENCE) stay distinct and are
|
|
28
|
-
// thrown before any key derivation, so they leak nothing password-dependent. Unencrypted export / import
|
|
29
|
-
// and publicFromPrivate delegate to the WebCrypto / node key engines and re-serialize no
|
|
30
|
-
// AlgorithmIdentifier. A re-encode is exactly where a params-absent-vs-NULL divergence sneaks back in.
|
|
31
21
|
|
|
32
22
|
var nodeCrypto = require("crypto");
|
|
33
23
|
var asn1 = require("./asn1-der");
|
|
@@ -44,23 +34,15 @@ var subtle = webcrypto.webcrypto.subtle;
|
|
|
44
34
|
var KeyError = frameworkError.KeyError;
|
|
45
35
|
var PemError = frameworkError.PemError;
|
|
46
36
|
function O(n) { return oid.byName(n); }
|
|
47
|
-
// The guard / pbes2 error convention: a (code, msg, cause) factory, never the KeyError class, because pbes2
|
|
48
|
-
// and the guards invoke it as E(code, msg) with no `new` (a class there crashes on the error path).
|
|
49
37
|
function _err(code, msg, cause) { return new KeyError(code, msg, cause); }
|
|
50
38
|
|
|
51
|
-
// The operator-facing node cipher name <-> the AES-CBC registry name the PBES2 home speaks.
|
|
52
39
|
var CIPHER_NAME = { "aes-128-cbc": "aes128-CBC", "aes-192-cbc": "aes192-CBC", "aes-256-cbc": "aes256-CBC" };
|
|
53
40
|
|
|
54
|
-
// import inference: the algorithm OIDs that name exactly one WebCrypto algorithm and need no parameters --
|
|
55
|
-
// the Edwards/Montgomery curves and the FIPS post-quantum ML-DSA, ML-KEM, and SLH-DSA (all signing-only or
|
|
56
|
-
// agreement-only, so unambiguous). RSA (sign vs OAEP) and EC (ECDSA vs ECDH) are deliberately absent. Each
|
|
57
|
-
// is ambiguous, so import fails closed there and asks for opts.algorithm.
|
|
58
41
|
var INFER_ALG = {};
|
|
59
42
|
["Ed25519", "Ed448", "X25519", "X448"].forEach(function (n) { INFER_ALG[O(n)] = { name: n }; });
|
|
60
43
|
[["id-ml-dsa-44", "ML-DSA-44"], ["id-ml-dsa-65", "ML-DSA-65"], ["id-ml-dsa-87", "ML-DSA-87"],
|
|
61
44
|
["id-ml-kem-512", "ML-KEM-512"], ["id-ml-kem-768", "ML-KEM-768"], ["id-ml-kem-1024", "ML-KEM-1024"]
|
|
62
45
|
].forEach(function (r) { INFER_ALG[O(r[0])] = { name: r[1] }; });
|
|
63
|
-
// SLH-DSA (FIPS 205) -- all twelve parameter sets; the WebCrypto name is the OID name minus "id-", uppercased.
|
|
64
46
|
["sha2-128s", "sha2-128f", "sha2-192s", "sha2-192f", "sha2-256s", "sha2-256f",
|
|
65
47
|
"shake-128s", "shake-128f", "shake-192s", "shake-192f", "shake-256s", "shake-256f"
|
|
66
48
|
].forEach(function (s) { INFER_ALG[O("id-slh-dsa-" + s)] = { name: ("SLH-DSA-" + s).toUpperCase() }; });
|
|
@@ -68,7 +50,6 @@ var INFER_ALG = {};
|
|
|
68
50
|
function _isCryptoKey(x) { return webcrypto.isCryptoKeyLike(x); }
|
|
69
51
|
function _algName(a) { return typeof a === "string" ? a : (a && a.name); }
|
|
70
52
|
|
|
71
|
-
// A private-key input (CryptoKey | DER Buffer | 'PRIVATE KEY' PEM) -> the raw PKCS#8 PrivateKeyInfo DER.
|
|
72
53
|
async function _toPrivateKeyDer(input) {
|
|
73
54
|
if (_isCryptoKey(input)) {
|
|
74
55
|
if (input.type !== "private") throw _err("key/bad-input", "a private CryptoKey is required (got a " + input.type + " key)");
|
|
@@ -107,9 +88,6 @@ async function _toPrivateKeyDer(input) {
|
|
|
107
88
|
* var enc = await pki.key.encrypt(der, "s3cr3t", { pem: true });
|
|
108
89
|
* var back = await pki.key.decrypt(enc, "s3cr3t");
|
|
109
90
|
*/
|
|
110
|
-
// Every option pki.key.encrypt reads. `iterations` here answers a different question from
|
|
111
|
-
// `maxIterations` on decrypt. This side chooses a PBKDF2 count, and that side caps the one it
|
|
112
|
-
// will honor. Passing either name to the other verb is silently nothing, so both are refused.
|
|
113
91
|
var _ENCRYPT_OPTS = { cipher: 1, iterations: 1, pem: 1, prf: 1, salt: 1 };
|
|
114
92
|
|
|
115
93
|
async function encrypt(privateKey, password, opts) {
|
|
@@ -118,8 +96,6 @@ async function encrypt(privateKey, password, opts) {
|
|
|
118
96
|
"pki.key.encrypt has an unknown option (the PBKDF2 count here is `iterations`; " +
|
|
119
97
|
"`maxIterations` is the decrypt-side cap): ");
|
|
120
98
|
var der = await _toPrivateKeyDer(privateKey);
|
|
121
|
-
// RFC 5958 sec. 3: the plaintext is the DER PrivateKeyInfo -- validate it IS one (the strict parser
|
|
122
|
-
// rejects BER / non-canonical / trailing bytes) before encrypting, so we never wrap opaque input.
|
|
123
99
|
try { pkcs8.parse(der); } catch (e) { throw _err("key/bad-input", "the private key is not a well-formed PKCS#8 PrivateKeyInfo", e); }
|
|
124
100
|
var cipherName = CIPHER_NAME[opts.cipher || "aes-256-cbc"];
|
|
125
101
|
if (!cipherName) throw _err("key/bad-input", "unsupported cipher " + JSON.stringify(opts.cipher) + " (aes-128-cbc / aes-192-cbc / aes-256-cbc)");
|
|
@@ -129,11 +105,6 @@ async function encrypt(privateKey, password, opts) {
|
|
|
129
105
|
var iterations = pbes2.assertIterations(opts.iterations == null ? 600000 : opts.iterations, _err, "key");
|
|
130
106
|
var salt = opts.salt != null ? pbes2.assertSalt(guard.bytes.view(opts.salt, KeyError, "key/bad-input", "salt"), _err, "key") : nodeCrypto.randomBytes(16);
|
|
131
107
|
var iv = nodeCrypto.randomBytes(16);
|
|
132
|
-
// The derived key protects a PRIVATE KEY, so it is cleared as soon as the encryption is done. The
|
|
133
|
-
// caller's password is untouched -- passwordBytes returns a supplied Buffer as-is.
|
|
134
|
-
// A string / Uint8Array password is encoded into a buffer THIS toolkit allocated -- a credential
|
|
135
|
-
// copy -- so it is cleared once the derivation has consumed it. A caller-supplied Buffer is
|
|
136
|
-
// borrowed and left intact.
|
|
137
108
|
var pwK = pbes2.passwordBytesOwned(password, _err, "key");
|
|
138
109
|
var dk;
|
|
139
110
|
try { dk = nodeCrypto.pbkdf2Sync(pwK.bytes, salt, iterations, keyBits / 8, prfNode); }
|
|
@@ -141,7 +112,7 @@ async function encrypt(privateKey, password, opts) {
|
|
|
141
112
|
try {
|
|
142
113
|
var ciphertext = pbes2.cbcEncrypt(dk, iv, der, keyBits, KeyError, "key/bad-input");
|
|
143
114
|
var epki = b.sequence([pbes2.pbes2AlgId(salt, iterations, prf, cipherName, iv), b.octetString(ciphertext)]);
|
|
144
|
-
pkcs8.parseEncrypted(epki);
|
|
115
|
+
pkcs8.parseEncrypted(epki);
|
|
145
116
|
return opts.pem ? pkcs8.pemEncode(epki, "ENCRYPTED PRIVATE KEY") : epki;
|
|
146
117
|
} finally {
|
|
147
118
|
guard.secret.zeroize(dk, KeyError, "key/bad-input", "the password-derived encryption key");
|
|
@@ -175,8 +146,6 @@ async function encrypt(privateKey, password, opts) {
|
|
|
175
146
|
* var enc = await pki.key.encrypt(await pki.key.export(pair.privateKey), "s3cr3t", { pem: true });
|
|
176
147
|
* var der = await pki.key.decrypt(enc, "s3cr3t");
|
|
177
148
|
*/
|
|
178
|
-
// Every option pki.key.decrypt reads. `maxIterations` is the cap this side honors, not the
|
|
179
|
-
// `iterations` the encrypt side chooses; see the note above _ENCRYPT_OPTS.
|
|
180
149
|
var _DECRYPT_OPTS = { maxIterations: 1, pem: 1 };
|
|
181
150
|
|
|
182
151
|
async function decrypt(encrypted, password, opts) {
|
|
@@ -184,9 +153,6 @@ async function decrypt(encrypted, password, opts) {
|
|
|
184
153
|
guard.identifier.assertKnownKeys(opts, _DECRYPT_OPTS, _err, "key/bad-input",
|
|
185
154
|
"pki.key.decrypt has an unknown option (the PBKDF2 cap here is `maxIterations`; " +
|
|
186
155
|
"`iterations` is the encrypt-side count): ");
|
|
187
|
-
// opts.maxIterations is a CALLER authoring bound (a downward-only cap): validate it config-time so an
|
|
188
|
-
// invalid value is a key/bad-input, never a NaN that silently disables the DoS cap and never mis-coded as
|
|
189
|
-
// a fault in the attacker-controlled input parameters.
|
|
190
156
|
if (opts.maxIterations != null && (typeof opts.maxIterations !== "number" || !isFinite(opts.maxIterations) || opts.maxIterations < 1 || Math.floor(opts.maxIterations) !== opts.maxIterations)) {
|
|
191
157
|
throw _err("key/bad-input", "maxIterations must be a positive integer");
|
|
192
158
|
}
|
|
@@ -201,12 +167,6 @@ async function decrypt(encrypted, password, opts) {
|
|
|
201
167
|
}
|
|
202
168
|
|
|
203
169
|
function _decryptPbes2(encAlg, ciphertext, password, opts) {
|
|
204
|
-
// The shared PBES2 decrypt home (strict params + the uniform decrypt-failed on a wrong key / bad pad). The
|
|
205
|
-
// plaintext re-parse below is the MAC-less PBES2-CBC integrity check (RFC 8018 sec. 8): a bad pad and a
|
|
206
|
-
// valid pad whose plaintext is not a PrivateKeyInfo are indistinguishable, and it MUST run (never skipped).
|
|
207
|
-
// A string / Uint8Array password is encoded into a buffer THIS toolkit allocated -- a credential
|
|
208
|
-
// copy -- so it is cleared once the derivation has consumed it. A caller-supplied Buffer is
|
|
209
|
-
// borrowed and left intact.
|
|
210
170
|
var pwD = pbes2.passwordBytesOwned(password, _err, "key");
|
|
211
171
|
var plaintext;
|
|
212
172
|
try { plaintext = pbes2.pbes2Decrypt(pwD.bytes, encAlg.parameters, ciphertext, opts, _err, "key"); }
|
|
@@ -242,16 +202,10 @@ function _decryptPbes2(encAlg, ciphertext, password, opts) {
|
|
|
242
202
|
* var pair = await pki.key.generate("Ed25519");
|
|
243
203
|
* var spkiPem = await pki.key.export(pair.publicKey, { format: "pem" });
|
|
244
204
|
*/
|
|
245
|
-
// Every option pki.key.export reads. Adding one here is the only way to make it accepted.
|
|
246
205
|
var _EXPORT_OPTS = { format: 1, label: 1 };
|
|
247
206
|
|
|
248
207
|
async function export_(key, opts) {
|
|
249
208
|
opts = guard.identifier.optionsObject(opts, _err, "key/bad-input", "pki.key.export options");
|
|
250
|
-
// This verb does NOT encrypt, and `password` is the option a caller reaches for when they
|
|
251
|
-
// think it does. Ignoring it writes the private key in the clear while the call site reads
|
|
252
|
-
// as though it were protected. Every other unknown option here costs a setting that does
|
|
253
|
-
// nothing; this one costs a plaintext key on disk. `pki.key.encrypt(key, password, opts)`
|
|
254
|
-
// is the verb that encrypts; export serializes whatever it is handed.
|
|
255
209
|
guard.identifier.assertKnownKeys(opts, _EXPORT_OPTS, _err, "key/bad-input",
|
|
256
210
|
"pki.key.export has an unknown option. It serializes only. To protect a private key, call " +
|
|
257
211
|
"pki.key.encrypt(key, password) first and export its result. The unknown option was: ");
|
|
@@ -291,7 +245,6 @@ async function export_(key, opts) {
|
|
|
291
245
|
* var spki = await pki.key.export(pair.publicKey);
|
|
292
246
|
* var pub = await pki.key.import(spki); // Ed25519 -- algorithm inferred
|
|
293
247
|
*/
|
|
294
|
-
// Every option pki.key.import reads.
|
|
295
248
|
var _IMPORT_OPTS = { algorithm: 1, extractable: 1, password: 1, usages: 1 };
|
|
296
249
|
|
|
297
250
|
async function import_(input, opts) {
|
|
@@ -305,9 +258,6 @@ async function import_(input, opts) {
|
|
|
305
258
|
}
|
|
306
259
|
var algorithm = opts.algorithm != null ? opts.algorithm : _inferAlgorithm(detected);
|
|
307
260
|
var isPublic = detected.format === "spki";
|
|
308
|
-
// Checked at this verb's own door rather than left for the engine to discover: a non-list reached
|
|
309
|
-
// the CryptoKey copy, where `Array.prototype.slice` on a number yields an empty list, so the key
|
|
310
|
-
// was minted permitted for NOTHING instead of the call naming the argument that was wrong.
|
|
311
261
|
if (opts.usages != null && !Array.isArray(opts.usages)) throw _err("key/bad-input", "opts.usages must be an array of key-usage strings");
|
|
312
262
|
var usages = opts.usages || _importUsages(_algName(algorithm), isPublic);
|
|
313
263
|
var extractable = opts.extractable != null ? opts.extractable : false;
|
|
@@ -339,8 +289,6 @@ async function import_(input, opts) {
|
|
|
339
289
|
* var pair = await pki.key.generate("Ed25519");
|
|
340
290
|
* var pkcs8 = await pki.key.export(pair.privateKey);
|
|
341
291
|
*/
|
|
342
|
-
// Every option pki.key.generate reads. `extractable` follows the WebCrypto spelling; a
|
|
343
|
-
// misspelling would leave a key extractable by default, which is the permissive direction.
|
|
344
292
|
var _GENERATE_OPTS = { extractable: 1, usages: 1 };
|
|
345
293
|
|
|
346
294
|
async function generate(algorithm, opts) {
|
|
@@ -348,7 +296,6 @@ async function generate(algorithm, opts) {
|
|
|
348
296
|
guard.identifier.assertKnownKeys(opts, _GENERATE_OPTS, _err, "key/bad-input",
|
|
349
297
|
"pki.key.generate has an unknown option (the WebCrypto spelling is `extractable`): ");
|
|
350
298
|
var extractable = opts.extractable != null ? opts.extractable : true;
|
|
351
|
-
// The same door as import: a non-list is named here rather than becoming an empty usage set.
|
|
352
299
|
if (opts.usages != null && !Array.isArray(opts.usages)) throw _err("key/bad-input", "opts.usages must be an array of key-usage strings");
|
|
353
300
|
var usages = opts.usages || _generateUsages(_algName(algorithm));
|
|
354
301
|
var pair;
|
|
@@ -377,7 +324,6 @@ async function generate(algorithm, opts) {
|
|
|
377
324
|
* var pair = await pki.key.generate("Ed25519");
|
|
378
325
|
* var spki = await pki.key.publicFromPrivate(await pki.key.export(pair.privateKey));
|
|
379
326
|
*/
|
|
380
|
-
// Every option pki.key.publicFromPrivate reads.
|
|
381
327
|
var _PUBLIC_FROM_PRIVATE_OPTS = { pem: 1 };
|
|
382
328
|
|
|
383
329
|
async function publicFromPrivate(privateKey, opts) {
|
|
@@ -393,11 +339,7 @@ async function publicFromPrivate(privateKey, opts) {
|
|
|
393
339
|
return opts.pem ? pkix.pemEncode(spki, "PUBLIC KEY", PemError) : spki;
|
|
394
340
|
}
|
|
395
341
|
|
|
396
|
-
// ---- import helpers --------------------------------------------------------
|
|
397
342
|
|
|
398
|
-
// Auto-detect a key input by structure (works for a raw DER Buffer or a label-agnostic PEM): a PrivateKeyInfo
|
|
399
|
-
// leads with an INTEGER version; an SPKI is SEQ{ algId, BIT STRING }; an EncryptedPrivateKeyInfo is
|
|
400
|
-
// SEQ{ algId, OCTET STRING }. Returns { format, der }.
|
|
401
343
|
function _detectKeyInput(input) {
|
|
402
344
|
var der = pkix.coerceToDer(input, { pemLabel: null, PemError: PemError, ErrorClass: KeyError, prefix: "key" });
|
|
403
345
|
var root;
|
|
@@ -409,13 +351,9 @@ function _detectKeyInput(input) {
|
|
|
409
351
|
throw _err("key/bad-input", "the input is not a recognized PKCS#8, SPKI, or EncryptedPrivateKeyInfo");
|
|
410
352
|
}
|
|
411
353
|
|
|
412
|
-
// The AlgorithmIdentifier OID from a detected key: privateKeyAlgorithm (PKCS#8) or algorithm (SPKI).
|
|
413
354
|
function _readAlgOid(detected) {
|
|
414
355
|
try {
|
|
415
356
|
if (detected.format === "pkcs8") return pkcs8.parse(detected.der).privateKeyAlgorithm.oid;
|
|
416
|
-
// SPKI: SEQUENCE { algorithm AlgorithmIdentifier SEQUENCE { OID, ... }, subjectPublicKey BIT STRING }.
|
|
417
|
-
// Validate the algorithm SEQUENCE shape before dereferencing its OID -- a malformed SPKI must be a typed
|
|
418
|
-
// reject, never a raw children[] fault.
|
|
419
357
|
var alg = asn1.decode(detected.der).children[0];
|
|
420
358
|
if (!alg || alg.tagClass !== "universal" || alg.tagNumber !== asn1.TAGS.SEQUENCE || !alg.children || !alg.children.length) {
|
|
421
359
|
throw _err("key/bad-input", "malformed SubjectPublicKeyInfo algorithm identifier");
|
|
@@ -435,15 +373,12 @@ function _inferAlgorithm(detected) {
|
|
|
435
373
|
" (RSA and EC are ambiguous between signing and key agreement -- pass opts.algorithm)");
|
|
436
374
|
}
|
|
437
375
|
|
|
438
|
-
// Default key usages by algorithm CLASS. The name is normalized to upper case first: WebCrypto matches
|
|
439
|
-
// algorithm names case-insensitively, so a caller passing { name: "x25519" } / "ml-kem-768" must land on the
|
|
440
|
-
// same usage class as the canonical spelling rather than fall through to the signing default.
|
|
441
376
|
function _importUsages(name, isPublic) {
|
|
442
377
|
var n = String(name == null ? "" : name).toUpperCase();
|
|
443
378
|
if (n === "X25519" || n === "X448" || n === "ECDH") return isPublic ? [] : ["deriveBits", "deriveKey"];
|
|
444
379
|
if (n.indexOf("ML-KEM") === 0) return isPublic ? ["encapsulateBits"] : ["decapsulateBits"];
|
|
445
380
|
if (n === "RSA-OAEP") return isPublic ? ["encrypt"] : ["decrypt"];
|
|
446
|
-
return isPublic ? ["verify"] : ["sign"];
|
|
381
|
+
return isPublic ? ["verify"] : ["sign"];
|
|
447
382
|
}
|
|
448
383
|
|
|
449
384
|
function _generateUsages(name) {
|