@blamejs/pki 0.8.60 → 0.9.0
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 +48 -0
- package/README.md +7 -0
- package/index.js +55 -26
- package/lib/acme.js +5 -5
- package/lib/asn1-der.js +1 -1
- package/lib/attrcert-sign.js +2 -2
- package/lib/cbor-det.js +4 -1
- package/lib/cmc-build.js +15 -10
- package/lib/cmp-build.js +5 -5
- package/lib/cmp-session.js +6 -3
- package/lib/cmp-verify.js +1 -1
- package/lib/cms-compress.js +5 -2
- package/lib/cms-decrypt.js +17 -17
- package/lib/cms-digest.js +2 -3
- package/lib/cms-encrypt.js +17 -18
- package/lib/cms-sign.js +2 -2
- package/lib/composite-kem.js +28 -29
- package/lib/crl-sign.js +3 -3
- package/lib/crmf-sign.js +12 -18
- package/lib/csr-sign.js +1 -1
- package/lib/ct.js +25 -22
- package/lib/est.js +12 -12
- package/lib/framework-error.js +1 -1
- package/lib/guard-bytes.js +1 -1
- package/lib/guard-crypto.js +506 -14
- package/lib/guard-limits.js +3 -2
- package/lib/guard-secret.js +3 -2
- package/lib/hpke.js +26 -26
- package/lib/http-digest.js +5 -7
- package/lib/http-retry-after.js +4 -1
- package/lib/http-transport.js +6 -6
- package/lib/inspect.js +9 -4
- package/lib/jose.js +3 -3
- package/lib/key.js +41 -29
- package/lib/merkle.js +4 -4
- package/lib/ocsp.js +3 -4
- package/lib/path-validate.js +3 -3
- package/lib/pbes2.js +14 -11
- package/lib/pkcs12-build.js +10 -11
- package/lib/pki-build.js +3 -3
- package/lib/scep.js +8 -9
- package/lib/schema-engine.js +12 -12
- package/lib/schema-pkix.js +12 -12
- package/lib/schema-tsp.js +3 -3
- package/lib/shbs.js +3 -6
- package/lib/sign-scheme.js +4 -4
- package/lib/sigstore.js +10 -10
- package/lib/smime.js +12 -9
- package/lib/tlog.js +5 -4
- package/lib/tls-cert-compress.js +3 -3
- package/lib/tsp-sign.js +6 -6
- package/lib/tuf.js +6 -5
- package/lib/validator-cose.js +2 -2
- package/lib/webauthn-mds.js +4 -8
- package/lib/webauthn.js +5 -12
- package/lib/webcrypto.js +61 -46
- package/lib/x509-sign.js +3 -3
- package/package.json +1 -1
- package/sbom.cdx.json +6 -6
package/lib/cms-digest.js
CHANGED
|
@@ -26,7 +26,6 @@
|
|
|
26
26
|
* attached or detached, constant-time comparison, fail-closed.
|
|
27
27
|
*/
|
|
28
28
|
|
|
29
|
-
var nodeCrypto = require("node:crypto");
|
|
30
29
|
var oid = require("./oid");
|
|
31
30
|
var schemaCms = require("./schema-cms");
|
|
32
31
|
var frameworkError = require("./framework-error");
|
|
@@ -101,7 +100,7 @@ async function _digest(content, opts) {
|
|
|
101
100
|
var ctOid = O(ctName);
|
|
102
101
|
if (!ctOid) throw _err("cms/bad-input", "opts.contentType is not a known OID name: " + guard.text.showValue(ctName));
|
|
103
102
|
|
|
104
|
-
var value =
|
|
103
|
+
var value = guard.crypto.digest(NODE_DIGEST[alg], raw);
|
|
105
104
|
var eciChildren = opts.detached === true
|
|
106
105
|
? [b.oid(ctOid)]
|
|
107
106
|
: [b.oid(ctOid), b.explicit(0, b.octetString(raw))];
|
|
@@ -176,7 +175,7 @@ async function _verifyDigest(input, opts) {
|
|
|
176
175
|
var covered = embedded != null
|
|
177
176
|
? guard.bytes.snapshotSource(embedded, CmsError, "cms/bad-input", "the encapsulated content")
|
|
178
177
|
: supplied;
|
|
179
|
-
var recomputed =
|
|
178
|
+
var recomputed = guard.crypto.digest(NODE_DIGEST[alg], covered);
|
|
180
179
|
var matched = guard.crypto.constantTimeEqual(recomputed, parsed.digest);
|
|
181
180
|
return guard.verdict.of({
|
|
182
181
|
valid: matched,
|
package/lib/cms-encrypt.js
CHANGED
|
@@ -4,7 +4,6 @@
|
|
|
4
4
|
// @internal
|
|
5
5
|
// @primitive pki.cms.encrypt block live in cms-verify.js, which re-exports this function (the
|
|
6
6
|
|
|
7
|
-
var nodeCrypto = require("crypto");
|
|
8
7
|
var asn1 = require("./asn1-der");
|
|
9
8
|
var pkiBuild = require("./pki-build");
|
|
10
9
|
var oid = require("./oid");
|
|
@@ -203,7 +202,7 @@ async function _buildKekri(cek, desc) {
|
|
|
203
202
|
|
|
204
203
|
async function _buildPwri(cek, desc) {
|
|
205
204
|
var iterations = pbes2.assertIterations(desc.iterations == null ? 600000 : desc.iterations, _err, "cms");
|
|
206
|
-
var salt = desc.salt ? pbes2.assertSalt(guard.bytes.view(desc.salt, CmsError, "cms/bad-input", "salt"), _err, "cms") :
|
|
205
|
+
var salt = desc.salt ? pbes2.assertSalt(guard.bytes.view(desc.salt, CmsError, "cms/bad-input", "salt"), _err, "cms") : guard.crypto.randomBytes(16);
|
|
207
206
|
var prf = desc.prf || "hmacWithSHA256";
|
|
208
207
|
_prfHash(prf);
|
|
209
208
|
var innerKeyBytes = 32;
|
|
@@ -213,7 +212,7 @@ async function _buildPwri(cek, desc) {
|
|
|
213
212
|
var kek = Buffer.from(await subtle.deriveBits({ name: "PBKDF2", hash: _prfHash(prf), salt: salt, iterations: iterations }, kekKey, innerKeyBytes * 8));
|
|
214
213
|
if (pwOwn.owned) guard.secret.zeroize(password, CmsError, "cms/bad-input", "the password encoding");
|
|
215
214
|
try {
|
|
216
|
-
var iv =
|
|
215
|
+
var iv = guard.crypto.randomBytes(16);
|
|
217
216
|
var encryptedKey = _pwriWrapIv(kek, cek, iv);
|
|
218
217
|
var kdfParams = pbes2.pbkdf2ParamsSeq(salt, iterations, prf);
|
|
219
218
|
var kdfAlg = b.contextConstructed(0, Buffer.concat([b.oid(O("pbkdf2")), kdfParams]));
|
|
@@ -288,17 +287,17 @@ function _pwriFormat(cek) {
|
|
|
288
287
|
var blk = 16;
|
|
289
288
|
var padLen = body.length % blk === 0 ? 0 : blk - (body.length % blk);
|
|
290
289
|
if (body.length + padLen < 2 * blk) padLen += (2 * blk - (body.length + padLen));
|
|
291
|
-
var wrapped = Buffer.concat([body,
|
|
290
|
+
var wrapped = Buffer.concat([body, guard.crypto.randomBytes(padLen)]);
|
|
292
291
|
guard.secret.zeroizeAll([check, body], CmsError, "cms/bad-input", "a PWRI formatting intermediate");
|
|
293
292
|
return wrapped;
|
|
294
293
|
}
|
|
295
294
|
function _pwriWrapIv(kek, cek, iv) {
|
|
296
295
|
var wk = _pwriFormat(cek);
|
|
297
296
|
try {
|
|
298
|
-
var c1 =
|
|
297
|
+
var c1 = guard.crypto.cipher("aes-256-cbc", kek, iv); guard.crypto.transformNoPadding(c1);
|
|
299
298
|
var pass1 = guard.secret.cipherFinish(c1, wk, CmsError, "cms/bad-input", "the PWRI first-pass ciphertext");
|
|
300
299
|
var iv2 = pass1.subarray(pass1.length - 16);
|
|
301
|
-
var c2 =
|
|
300
|
+
var c2 = guard.crypto.cipher("aes-256-cbc", kek, iv2); guard.crypto.transformNoPadding(c2);
|
|
302
301
|
return guard.secret.cipherFinish(c2, pass1, CmsError, "cms/bad-input", "the PWRI wrapped key");
|
|
303
302
|
} finally {
|
|
304
303
|
guard.secret.zeroize(wk, CmsError, "cms/bad-input", "the PWRI plaintext block");
|
|
@@ -427,7 +426,7 @@ function encrypt(content, recipients, opts) {
|
|
|
427
426
|
}
|
|
428
427
|
|
|
429
428
|
async function _encryptImpl(content, recipients, opts) {
|
|
430
|
-
opts = opts ||
|
|
429
|
+
opts = opts || intrinsic.create(null);
|
|
431
430
|
var algName = opts.contentEncryptionAlgorithm || "aes-256-gcm";
|
|
432
431
|
var ca = CONTENT_ALGS[guard.text.keyOf(algName)];
|
|
433
432
|
if (!ca) throw _err("cms/bad-input", "unsupported contentEncryptionAlgorithm " + guard.text.showValue(algName));
|
|
@@ -444,7 +443,7 @@ async function _encryptImpl(content, recipients, opts) {
|
|
|
444
443
|
* them. */
|
|
445
444
|
var contentBytes = contentStream ? null : guard.bytes.view(content, CmsError, "cms/bad-input", "content");
|
|
446
445
|
var contentType = opts.contentType || "data";
|
|
447
|
-
var cek =
|
|
446
|
+
var cek = guard.crypto.randomBytes(ca.keyBits / 8);
|
|
448
447
|
|
|
449
448
|
try {
|
|
450
449
|
if (!Array.isArray(recipients)) return await _encryptedData(contentBytes, contentStream, recipients, ca, contentType, opts, cek);
|
|
@@ -477,7 +476,7 @@ async function _encStream(spec, stream) {
|
|
|
477
476
|
}
|
|
478
477
|
|
|
479
478
|
async function _envelopedData(contentBytes, contentStream, cek, ca, contentType, riNodes, recips) {
|
|
480
|
-
var iv =
|
|
479
|
+
var iv = guard.crypto.randomBytes(16);
|
|
481
480
|
var enc = contentStream
|
|
482
481
|
? (await _encStream({ algNode: "aes-" + ca.keyBits + "-cbc", key: cek, iv: iv }, contentStream)).ciphertext
|
|
483
482
|
: pbes2.cbcEncrypt(cek, iv, contentBytes, ca.keyBits, CmsError, "cms/bad-input");
|
|
@@ -522,7 +521,7 @@ var AUTH_ENVELOPED_FORBIDDEN = intrinsic.assign(intrinsic.create(null), {
|
|
|
522
521
|
});
|
|
523
522
|
|
|
524
523
|
async function _authEnvelopedData(contentBytes, contentStream, cek, ca, contentType, opts, riNodes, recips) {
|
|
525
|
-
var nonce =
|
|
524
|
+
var nonce = guard.crypto.randomBytes(12);
|
|
526
525
|
var authAttrsDer = null, aad = Buffer.alloc(0);
|
|
527
526
|
if (contentType !== "data" && !(opts.authAttrs && opts.authAttrs.length)) {
|
|
528
527
|
throw _err("cms/bad-input", "AuthEnvelopedData with a non-data contentType requires authAttrs (RFC 5083 sec. 2.1)");
|
|
@@ -561,7 +560,7 @@ async function _encryptedData(contentBytes, contentStream, desc, ca, contentType
|
|
|
561
560
|
" EncryptedData descriptor; that field is not read for this arm";
|
|
562
561
|
});
|
|
563
562
|
}
|
|
564
|
-
var iv =
|
|
563
|
+
var iv = guard.crypto.randomBytes(16);
|
|
565
564
|
var contentAlgNode, encKey;
|
|
566
565
|
if (desc && desc.cek != null) {
|
|
567
566
|
encKey = guard.bytes.view(desc.cek, CmsError, "cms/bad-input", "cek");
|
|
@@ -584,9 +583,9 @@ async function _encryptedDataPbes2(contentBytes, contentStream, desc, ca, conten
|
|
|
584
583
|
var pwOwn2 = pbes2.passwordBytesOwned(desc.password, _err, "cms");
|
|
585
584
|
var password = pwOwn2.bytes;
|
|
586
585
|
var iterations = pbes2.assertIterations(desc.iterations == null ? 600000 : desc.iterations, _err, "cms");
|
|
587
|
-
var salt = desc.salt ? pbes2.assertSalt(guard.bytes.view(desc.salt, CmsError, "cms/bad-input", "salt"), _err, "cms") :
|
|
586
|
+
var salt = desc.salt ? pbes2.assertSalt(guard.bytes.view(desc.salt, CmsError, "cms/bad-input", "salt"), _err, "cms") : guard.crypto.randomBytes(16);
|
|
588
587
|
var prf = desc.prf || "hmacWithSHA256";
|
|
589
|
-
var key =
|
|
588
|
+
var key = guard.crypto.pbkdf2(password, salt, iterations, ca.keyBits / 8, pbes2.prfNodeByName(prf, _err, "cms"));
|
|
590
589
|
if (pwOwn2.owned) guard.secret.zeroize(password, CmsError, "cms/bad-input", "the password encoding");
|
|
591
590
|
try {
|
|
592
591
|
var enc = contentStream
|
|
@@ -602,10 +601,10 @@ async function _encryptedDataPbes2(contentBytes, contentStream, desc, ca, conten
|
|
|
602
601
|
}
|
|
603
602
|
|
|
604
603
|
function _gcmEncrypt(key, nonce, plaintext, aad, keyBits, tagLen) {
|
|
605
|
-
var c =
|
|
606
|
-
if (aad && aad.length)
|
|
604
|
+
var c = guard.crypto.cipher("aes-" + keyBits + "-gcm", key, nonce, { authTagLength: tagLen });
|
|
605
|
+
if (aad && aad.length) guard.crypto.transformSetAAD(c, aad);
|
|
607
606
|
var ct = guard.secret.cipherFinish(c, plaintext, CmsError, "cms/bad-input", "a content-encryption intermediate");
|
|
608
|
-
return { ct: ct, tag:
|
|
607
|
+
return { ct: ct, tag: guard.crypto.cipherAuthTag(c) };
|
|
609
608
|
}
|
|
610
609
|
|
|
611
610
|
function _tlvHeaderLen(der) {
|
|
@@ -649,7 +648,7 @@ function authenticate(content, recipients, opts) {
|
|
|
649
648
|
}
|
|
650
649
|
|
|
651
650
|
async function _authenticateImpl(content, recipients, opts) {
|
|
652
|
-
opts = opts ||
|
|
651
|
+
opts = opts || intrinsic.create(null);
|
|
653
652
|
var withAttrs = opts.authenticatedAttributes !== false;
|
|
654
653
|
guard.identifier.assertKnownKeys(opts, withAttrs ? _AUTHENTICATE_OPTS_ATTRS : _AUTHENTICATE_OPTS_BARE,
|
|
655
654
|
_err, "cms/bad-input", function (k) {
|
|
@@ -682,7 +681,7 @@ async function _authenticateImpl(content, recipients, opts) {
|
|
|
682
681
|
var contentType = opts.contentType || "data";
|
|
683
682
|
if (contentType !== "data" && !withAttrs) throw _err("cms/bad-input", "AuthenticatedData with a non-data contentType requires authenticated attributes (RFC 5652 sec. 9.1)");
|
|
684
683
|
|
|
685
|
-
var macKey =
|
|
684
|
+
var macKey = guard.crypto.randomBytes(MAC_KEY_OCTETS);
|
|
686
685
|
try {
|
|
687
686
|
var recips = [];
|
|
688
687
|
var consumedAuth = {};
|
package/lib/cms-sign.js
CHANGED
|
@@ -203,7 +203,7 @@ function _assertAlgorithmProtectionPairs(pairs, digestAlgId, armAlgId, armTag) {
|
|
|
203
203
|
}
|
|
204
204
|
|
|
205
205
|
function _resolveSignerContext(signer, opts) {
|
|
206
|
-
var so = signer ||
|
|
206
|
+
var so = signer || intrinsic.create(null);
|
|
207
207
|
var keyOnly = so.cert == null && so.spki != null;
|
|
208
208
|
var soKey = so.key;
|
|
209
209
|
var soSpki = keyOnly ? guard.bytes.snapshotSource(so.spki, CmsError, "cms/bad-input", "a key-only signer's spki") : null;
|
|
@@ -533,7 +533,7 @@ function _resolveSignerIndices(spec, n) {
|
|
|
533
533
|
}
|
|
534
534
|
|
|
535
535
|
function _buildCountersignature(targetSigOctets, countersigner, opts) {
|
|
536
|
-
var so = countersigner ||
|
|
536
|
+
var so = countersigner || intrinsic.create(null);
|
|
537
537
|
var certDer = _normCertDer(so.cert);
|
|
538
538
|
var cert = x509.parse(certDer);
|
|
539
539
|
var scheme = signScheme.resolveSignScheme(cert, so, opts.signedAttributes === false, _signE);
|
package/lib/composite-kem.js
CHANGED
|
@@ -23,7 +23,6 @@
|
|
|
23
23
|
var asn1 = require("./asn1-der");
|
|
24
24
|
var oid = require("./oid");
|
|
25
25
|
var webcrypto = require("./webcrypto");
|
|
26
|
-
var nodeCrypto = require("node:crypto");
|
|
27
26
|
var frameworkError = require("./framework-error");
|
|
28
27
|
var guard = require("./guard-all");
|
|
29
28
|
var intrinsic = require("./guard-intrinsic");
|
|
@@ -115,11 +114,11 @@ function _mlkemDecaps(d, seed, mlkemCT) {
|
|
|
115
114
|
function _ecPubFromPoint(d, point) {
|
|
116
115
|
if (point.length < 1 || point[0] !== 0x04) throw _err("kem/bad-key", "the EC component point is not in uncompressed form");
|
|
117
116
|
var spki = _b.sequence([_b.sequence([_b.oid(oid.byName("ecPublicKey")), _b.oid(oid.byName(d.trad.curve))]), _b.bitString(point, 0)]);
|
|
118
|
-
return
|
|
117
|
+
return guard.crypto.publicKey({ key: spki, format: "der", type: "spki" });
|
|
119
118
|
}
|
|
120
119
|
function _okpPubFromRaw(d, raw) {
|
|
121
120
|
var spki = _b.sequence([_b.sequence([_b.oid(oid.byName(d.trad.curve))]), _b.bitString(raw, 0)]);
|
|
122
|
-
return
|
|
121
|
+
return guard.crypto.publicKey({ key: spki, format: "der", type: "spki" });
|
|
123
122
|
}
|
|
124
123
|
/** @internal The encoding is this helper's own allocation and holds the traditional private scalar, so
|
|
125
124
|
* it is cleared here. A caller's own cleanup cannot reach a buffer it never sees, and both the
|
|
@@ -127,13 +126,13 @@ function _okpPubFromRaw(d, raw) {
|
|
|
127
126
|
function _okpPrivFromRaw(d, raw) {
|
|
128
127
|
var p8 = _b.sequence([_b.integer(0n), _b.sequence([_b.oid(oid.byName(d.trad.curve))]), _b.octetString(_b.octetString(raw))]);
|
|
129
128
|
try {
|
|
130
|
-
return
|
|
129
|
+
return guard.crypto.privateKey({ key: p8, format: "der", type: "pkcs8" });
|
|
131
130
|
} finally {
|
|
132
131
|
guard.secret.zeroize(p8, KemError, "kem/bad-input", "the " + d.trad.curve + " component key encoding");
|
|
133
132
|
}
|
|
134
133
|
}
|
|
135
134
|
function _rawPubOf(keyObject) {
|
|
136
|
-
var spki =
|
|
135
|
+
var spki = guard.crypto.exportKey(keyObject, { format: "der", type: "spki" });
|
|
137
136
|
return Buffer.from(asn1.read.bitString(asn1.decode(spki).children[1]).bytes);
|
|
138
137
|
}
|
|
139
138
|
|
|
@@ -143,12 +142,12 @@ function _tradEncaps(d, tradPK) {
|
|
|
143
142
|
var pub;
|
|
144
143
|
try {
|
|
145
144
|
asn1.decode(tradPK);
|
|
146
|
-
pub =
|
|
145
|
+
pub = guard.crypto.publicKey({ key: tradPK, format: "der", type: "pkcs1" });
|
|
147
146
|
} catch (e) { return _promiseReject(_Promise, _err("kem/bad-key", "the RSA component public key is not a valid RSAPublicKey", e)); }
|
|
148
|
-
if (pub.
|
|
149
|
-
var ss = Buffer.from(
|
|
147
|
+
if (guard.crypto.keyDetails(pub).modulusLength !== trad.bits) return _promiseReject(_Promise, _err("kem/bad-key", "the RSA component modulus is not " + trad.bits + " bits (draft sec. 6)"));
|
|
148
|
+
var ss = Buffer.from(guard.crypto.randomBytes(RSA_SS));
|
|
150
149
|
var ct;
|
|
151
|
-
try { ct = Buffer.from(
|
|
150
|
+
try { ct = Buffer.from(guard.crypto.publicEncrypt({ key: pub, padding: guard.crypto.padding.RSA_PKCS1_OAEP, oaepHash: "sha256" }, ss)); }
|
|
152
151
|
catch (e) {
|
|
153
152
|
guard.secret.zeroize(ss, KemError, "kem/bad-input", "the RSA-OAEP component secret");
|
|
154
153
|
return _promiseReject(_Promise, _err("kem/bad-key", "the RSA-OAEP component encryption failed", e));
|
|
@@ -158,8 +157,8 @@ function _tradEncaps(d, tradPK) {
|
|
|
158
157
|
var dh, dhCt;
|
|
159
158
|
try {
|
|
160
159
|
var recip = trad.kind === "ec" ? _ecPubFromPoint(d, tradPK) : _okpPubFromRaw(d, tradPK);
|
|
161
|
-
var eph = trad.kind === "ec" ?
|
|
162
|
-
dh = Buffer.from(
|
|
160
|
+
var eph = trad.kind === "ec" ? guard.crypto.generateKeyPair("ec", { namedCurve: trad.node }) : guard.crypto.generateKeyPair(trad.curve.toLowerCase());
|
|
161
|
+
dh = Buffer.from(guard.crypto.diffieHellman({ privateKey: eph.privateKey, publicKey: recip }));
|
|
163
162
|
dhCt = _rawPubOf(eph.publicKey);
|
|
164
163
|
} catch (e) { return _promiseReject(_Promise, _err("kem/bad-key", "the " + trad.curve + " public key is invalid", e)); }
|
|
165
164
|
return _promiseResolve(_Promise, { ss: dh, ct: dhCt });
|
|
@@ -171,37 +170,38 @@ function _tradDecaps(d, tradSK, tradCT) {
|
|
|
171
170
|
var priv;
|
|
172
171
|
try {
|
|
173
172
|
asn1.decode(tradSK);
|
|
174
|
-
priv =
|
|
173
|
+
priv = guard.crypto.privateKey({ key: tradSK, format: "der", type: "pkcs1" });
|
|
175
174
|
} catch (e) { return _promiseReject(_Promise, _err("kem/bad-key", "the RSA component private key is not a valid RSAPrivateKey", e)); }
|
|
176
|
-
if (priv.
|
|
175
|
+
if (guard.crypto.keyDetails(priv).modulusLength !== trad.bits) return _promiseReject(_Promise, _err("kem/bad-key", "the RSA component modulus is not " + trad.bits + " bits (draft sec. 6)"));
|
|
177
176
|
var ss;
|
|
178
|
-
try { ss = Buffer.from(
|
|
177
|
+
try { ss = Buffer.from(guard.crypto.privateDecrypt({ key: priv, padding: guard.crypto.padding.RSA_PKCS1_OAEP, oaepHash: "sha256" }, tradCT)); }
|
|
179
178
|
catch (_e) { return _promiseReject(_Promise, _err("kem/decapsulation-failed", "the RSA-OAEP component decryption failed")); }
|
|
180
179
|
if (ss.length !== RSA_SS) {
|
|
181
180
|
guard.secret.zeroize(ss, KemError, "kem/bad-input", "the RSA-OAEP component secret");
|
|
182
181
|
return _promiseReject(_Promise, _err("kem/decapsulation-failed", "the RSA-OAEP component decryption failed"));
|
|
183
182
|
}
|
|
184
|
-
return _promiseResolve(_Promise, { ss: ss,
|
|
183
|
+
return _promiseResolve(_Promise, { ss: ss,
|
|
184
|
+
tradPK: Buffer.from(guard.crypto.exportKey(guard.crypto.publicKey(priv), { format: "der", type: "pkcs1" })) });
|
|
185
185
|
}
|
|
186
186
|
var priv2, eph;
|
|
187
187
|
try {
|
|
188
188
|
if (trad.kind === "ec") {
|
|
189
189
|
asn1.decode(tradSK);
|
|
190
|
-
priv2 =
|
|
190
|
+
priv2 = guard.crypto.privateKey({ key: tradSK, format: "der", type: "sec1" });
|
|
191
191
|
} else {
|
|
192
192
|
priv2 = _okpPrivFromRaw(d, tradSK);
|
|
193
193
|
}
|
|
194
194
|
eph = trad.kind === "ec" ? _ecPubFromPoint(d, tradCT) : _okpPubFromRaw(d, tradCT);
|
|
195
195
|
} catch (e) { return _promiseReject(_Promise, _err("kem/bad-key", "the " + trad.curve + " key material is invalid", e)); }
|
|
196
196
|
var dh;
|
|
197
|
-
try { dh = Buffer.from(
|
|
197
|
+
try { dh = Buffer.from(guard.crypto.diffieHellman({ privateKey: priv2, publicKey: eph })); }
|
|
198
198
|
catch (e) { return _promiseReject(_Promise, _err("kem/decapsulation-failed", "the " + trad.curve + " Diffie-Hellman failed", e)); }
|
|
199
199
|
/** @internal The same canonical point the derivation states, read from the one function that spells
|
|
200
200
|
* it. The combiner hashes these bytes, so a stored spelling here and a generated one there would
|
|
201
201
|
* reach different secrets from the two sides of one key. */
|
|
202
202
|
var tradPK;
|
|
203
203
|
try {
|
|
204
|
-
tradPK = trad.kind === "ec" ? _ecPointOf(d, tradSK) : _rawPubOf(
|
|
204
|
+
tradPK = trad.kind === "ec" ? _ecPointOf(d, tradSK) : _rawPubOf(guard.crypto.publicKey(priv2));
|
|
205
205
|
} catch (e) {
|
|
206
206
|
/** @internal The agreement already produced a secret, and this rejection happens after it, so the
|
|
207
207
|
* secret is wiped here: the caller's settle-or-wipe covers a value it was handed, and a rejected
|
|
@@ -371,9 +371,7 @@ function _ecPointOf(d, tradSK) {
|
|
|
371
371
|
var scalar = _ecScalarOf(d, tradSK);
|
|
372
372
|
var point;
|
|
373
373
|
try {
|
|
374
|
-
|
|
375
|
-
ecdh.setPrivateKey(scalar);
|
|
376
|
-
point = ecdh.getPublicKey(null, "uncompressed");
|
|
374
|
+
point = guard.crypto.ecPointFromScalar(d.trad.node, scalar);
|
|
377
375
|
} catch (e) {
|
|
378
376
|
if (e instanceof KemError) throw e;
|
|
379
377
|
throw _err("kem/bad-key", "the EC component scalar does not generate a point on " + d.trad.node, e);
|
|
@@ -418,18 +416,18 @@ function _tradPubOf(d, tradSK) {
|
|
|
418
416
|
var rp;
|
|
419
417
|
try {
|
|
420
418
|
asn1.decode(tradSK);
|
|
421
|
-
rp =
|
|
419
|
+
rp = guard.crypto.privateKey({ key: tradSK, format: "der", type: "pkcs1" });
|
|
422
420
|
} catch (e) { throw _err("kem/bad-key", "the RSA component private key is not a valid RSAPrivateKey", e); }
|
|
423
|
-
if (rp.
|
|
421
|
+
if (guard.crypto.keyDetails(rp).modulusLength !== trad.bits) {
|
|
424
422
|
throw _err("kem/bad-key", "the RSA component modulus is not " + trad.bits + " bits (draft sec. 6)");
|
|
425
423
|
}
|
|
426
|
-
return Buffer.from(
|
|
424
|
+
return Buffer.from(guard.crypto.exportKey(guard.crypto.publicKey(rp), { format: "der", type: "pkcs1" }));
|
|
427
425
|
}
|
|
428
426
|
var priv;
|
|
429
427
|
try {
|
|
430
428
|
if (trad.kind === "ec") {
|
|
431
429
|
asn1.decode(tradSK);
|
|
432
|
-
priv =
|
|
430
|
+
priv = guard.crypto.privateKey({ key: tradSK, format: "der", type: "sec1" });
|
|
433
431
|
} else {
|
|
434
432
|
priv = _okpPrivFromRaw(d, tradSK);
|
|
435
433
|
}
|
|
@@ -439,7 +437,8 @@ function _tradPubOf(d, tradSK) {
|
|
|
439
437
|
* public key nothing can use, so the two are held to each other here. Decapsulation reaches the same
|
|
440
438
|
* conclusion by failing the agreement; a derivation performs no operation that would notice. */
|
|
441
439
|
if (trad.kind === "ec") {
|
|
442
|
-
var
|
|
440
|
+
var privDetails = guard.crypto.keyDetails(priv);
|
|
441
|
+
var named = privDetails && privDetails.namedCurve;
|
|
443
442
|
if (named !== trad.node) {
|
|
444
443
|
throw _err("kem/bad-key", "the EC component is on " + guard.text.showValue(named) + ", and " + d.name + " names " + trad.node);
|
|
445
444
|
}
|
|
@@ -450,7 +449,7 @@ function _tradPubOf(d, tradSK) {
|
|
|
450
449
|
* point stored beside it cannot stand in for one it does not generate. */
|
|
451
450
|
return _ecPointOf(d, tradSK);
|
|
452
451
|
}
|
|
453
|
-
return _rawPubOf(
|
|
452
|
+
return _rawPubOf(guard.crypto.publicKey(priv));
|
|
454
453
|
}
|
|
455
454
|
|
|
456
455
|
/** @internal The composite `SubjectPublicKeyInfo` for a composite ML-KEM private key. The runtime key
|
|
@@ -488,8 +487,8 @@ async function _publicFromPrivate(privateKey) {
|
|
|
488
487
|
* copy of the seed and is registered as one. */
|
|
489
488
|
var seedPkcs8 = _mlkemSeedPkcs8(d, seed);
|
|
490
489
|
guard.list.append(secrets, seedPkcs8);
|
|
491
|
-
var mlPriv =
|
|
492
|
-
ek = _rawPubOf(
|
|
490
|
+
var mlPriv = guard.crypto.privateKey({ key: seedPkcs8, format: "der", type: "pkcs8" });
|
|
491
|
+
ek = _rawPubOf(guard.crypto.publicKey(mlPriv));
|
|
493
492
|
} catch (e) {
|
|
494
493
|
if (e instanceof KemError) throw e;
|
|
495
494
|
throw _err("kem/bad-key", "the ML-KEM component private key is invalid", e);
|
package/lib/crl-sign.js
CHANGED
|
@@ -240,7 +240,7 @@ function _buildCrlExtensions(spec, ctx) {
|
|
|
240
240
|
var crlNumberVal = null;
|
|
241
241
|
if (spec.crlNumber != null) { var cn = _boundedInteger(spec.crlNumber, "cRLNumber"); crlNumberVal = cn.value; push("cRLNumber", false, cn.tlv); }
|
|
242
242
|
var ext = spec.extensions;
|
|
243
|
-
if (ext == null) ext =
|
|
243
|
+
if (ext == null) ext = intrinsic.create(null);
|
|
244
244
|
if (Array.isArray(ext)) {
|
|
245
245
|
var arrBase = null, arrCrlNum = null;
|
|
246
246
|
/** @internal The walk goes through `guard.list.copyMap`, never the caller's own `forEach`. Reached
|
|
@@ -391,9 +391,9 @@ function _assertIssuerCanSignCrl(issuerCert) {
|
|
|
391
391
|
}
|
|
392
392
|
|
|
393
393
|
function _sign(spec, issuer, opts) {
|
|
394
|
-
opts = opts ||
|
|
394
|
+
opts = opts || intrinsic.create(null);
|
|
395
395
|
if (!spec || typeof spec !== "object" || Buffer.isBuffer(spec)) throw _err("crl/bad-input", "the CRL spec must be an object");
|
|
396
|
-
issuer = issuer ||
|
|
396
|
+
issuer = issuer || intrinsic.create(null);
|
|
397
397
|
var byCert = issuer.cert != null, byName = issuer.name != null;
|
|
398
398
|
guard.identifier.assertKnownKeys(spec, byCert || byName ? KNOWN_SPEC_KEYS_ISSUER_NAMED : KNOWN_SPEC_KEYS,
|
|
399
399
|
_err, "crl/bad-input", function (k) {
|
package/lib/crmf-sign.js
CHANGED
|
@@ -17,12 +17,6 @@
|
|
|
17
17
|
* @card Build a CRMF CertReqMessages with a signature proof of possession.
|
|
18
18
|
*/
|
|
19
19
|
|
|
20
|
-
var nodeCrypto = require("node:crypto");
|
|
21
|
-
/** @internal Bound at module load, like every other capture here: the proof below decides what it
|
|
22
|
-
* agrees and what it hashes, so a replacement swapped in afterwards must not be able to steer it. */
|
|
23
|
-
var _diffieHellman = nodeCrypto.diffieHellman;
|
|
24
|
-
var _createPublicKey = nodeCrypto.createPublicKey;
|
|
25
|
-
var _createPrivateKey = nodeCrypto.createPrivateKey;
|
|
26
20
|
var asn1 = require("./asn1-der");
|
|
27
21
|
var oid = require("./oid");
|
|
28
22
|
var x509 = require("./schema-x509");
|
|
@@ -345,7 +339,7 @@ function _buildAgreeMac(pop, outerTag, certReqDer, template) {
|
|
|
345
339
|
_assertAgreementExponent(pkcs3, "the authority certificate's key");
|
|
346
340
|
}
|
|
347
341
|
}
|
|
348
|
-
try { caPub =
|
|
342
|
+
try { caPub = guard.crypto.publicKey({ key: caSpkiBytes, format: "der", type: "spki" }); }
|
|
349
343
|
catch (e) { throw _err("crmf/bad-popo", "the authority certificate does not carry a key this runtime can agree with", e); }
|
|
350
344
|
/** @internal The snapshot of the caller's key is this function's own copy of private material, so it
|
|
351
345
|
* is registered for the wipe below rather than left to the argument boundary, which clears what it
|
|
@@ -357,7 +351,7 @@ function _buildAgreeMac(pop, outerTag, certReqDer, template) {
|
|
|
357
351
|
/** @internal Inside the cleanup scope, because the import can throw AFTER the snapshot exists: a
|
|
358
352
|
* catch that returned from out here would leave that copy of private material behind. */
|
|
359
353
|
try {
|
|
360
|
-
if (
|
|
354
|
+
if (guard.crypto.keyTypeOf(pop.key) != null) {
|
|
361
355
|
eePriv = pop.key;
|
|
362
356
|
} else if (pop.key && typeof pop.key === "object" && pop.key.type === "private" &&
|
|
363
357
|
typeof pop.key.export === "function") {
|
|
@@ -366,10 +360,10 @@ function _buildAgreeMac(pop, outerTag, certReqDer, template) {
|
|
|
366
360
|
* applies here: supporting the encoding for a caller holding bytes and refusing the caller
|
|
367
361
|
* holding the key those bytes import to would be the same key admitted one way. The export
|
|
368
362
|
* is this function's own copy of private material and is cleared with the rest. */
|
|
369
|
-
keySnapshot = pop.key
|
|
363
|
+
keySnapshot = guard.crypto.exportKey(pop.key, { format: "der", type: "pkcs8" });
|
|
370
364
|
translated = _x942PrivToPkcs3(keySnapshot);
|
|
371
365
|
eePriv = translated !== null
|
|
372
|
-
?
|
|
366
|
+
? guard.crypto.privateKey({ key: translated, format: "der", type: "pkcs8" })
|
|
373
367
|
: pop.key;
|
|
374
368
|
} else if (guard.bytes.isByteSource(pop.key)) {
|
|
375
369
|
keySnapshot = guard.bytes.snapshotSource(pop.key, CrmfError, "crmf/bad-popo", "the requester's private key");
|
|
@@ -377,7 +371,7 @@ function _buildAgreeMac(pop, outerTag, certReqDer, template) {
|
|
|
377
371
|
* copy of the private value, and an import that throws after it exists must not leave it
|
|
378
372
|
* behind. The wipe below clears whatever was made, on every way out. */
|
|
379
373
|
translated = _x942PrivToPkcs3(keySnapshot);
|
|
380
|
-
eePriv =
|
|
374
|
+
eePriv = guard.crypto.privateKey({ key: translated || keySnapshot, format: "der", type: "pkcs8" });
|
|
381
375
|
} else {
|
|
382
376
|
/** @internal A PEM key reaches the same conversion: it is the same key in the same encoding
|
|
383
377
|
* with an armor around it, so admitting one form and not the other would support X9.42 for a
|
|
@@ -386,9 +380,9 @@ function _buildAgreeMac(pop, outerTag, certReqDer, template) {
|
|
|
386
380
|
if (pemDer !== null) {
|
|
387
381
|
keySnapshot = pemDer;
|
|
388
382
|
translated = _x942PrivToPkcs3(keySnapshot);
|
|
389
|
-
eePriv =
|
|
383
|
+
eePriv = guard.crypto.privateKey({ key: translated || keySnapshot, format: "der", type: "pkcs8" });
|
|
390
384
|
} else {
|
|
391
|
-
eePriv =
|
|
385
|
+
eePriv = guard.crypto.privateKey(pop.key);
|
|
392
386
|
}
|
|
393
387
|
}
|
|
394
388
|
} catch (e) {
|
|
@@ -402,7 +396,7 @@ function _buildAgreeMac(pop, outerTag, certReqDer, template) {
|
|
|
402
396
|
* something this request never asked to have certified. The encryptedKey arm holds its enclosed
|
|
403
397
|
* key to the same rule. */
|
|
404
398
|
var eeSpki;
|
|
405
|
-
try { eeSpki =
|
|
399
|
+
try { eeSpki = guard.crypto.exportKey(guard.crypto.publicKey(eePriv), { format: "der", type: "spki" }); }
|
|
406
400
|
catch (e) { throw _err("crmf/bad-popo", "the public half of pop.key could not be derived to check it against the requested key", e); }
|
|
407
401
|
/** @internal Compared as keys, not as bytes. A PKCS#3 DHParameter carries an optional
|
|
408
402
|
* privateValueLength, so one finite-field key has more than one valid SubjectPublicKeyInfo and a
|
|
@@ -449,7 +443,7 @@ function _buildAgreeMac(pop, outerTag, certReqDer, template) {
|
|
|
449
443
|
* with parameters g and p, agreeing `g^xy mod p`. An elliptic-curve or montgomery pair agrees a
|
|
450
444
|
* secret through the same call and would be emitted under the same OID, which names an operation
|
|
451
445
|
* the recipient would not be performing. */
|
|
452
|
-
if (eePriv
|
|
446
|
+
if (guard.crypto.keyType(eePriv) !== "dh" || guard.crypto.keyType(caPub) !== "dh") {
|
|
453
447
|
/** @internal A key this runtime imported but did not classify reports no asymmetricKeyType, which
|
|
454
448
|
* is what an X9.42 dhpublicnumber SubjectPublicKeyInfo does here where the PKCS#3 dhKeyAgreement
|
|
455
449
|
* form is classified. The agreement refuses such a key on its own, so naming the unrecognized
|
|
@@ -459,7 +453,7 @@ function _buildAgreeMac(pop, outerTag, certReqDer, template) {
|
|
|
459
453
|
}
|
|
460
454
|
/** @internal The agreement's own Buffer, not a copy of it: wrapping it would leave the original
|
|
461
455
|
* holding the secret with nothing to clear it. */
|
|
462
|
-
try { zz =
|
|
456
|
+
try { zz = guard.crypto.diffieHellman({ privateKey: eePriv, publicKey: caPub }); }
|
|
463
457
|
catch (e) { throw _err("crmf/bad-popo", "the requester's key and the authority's key did not agree a secret; this proof needs a key on the authority's own parameters (RFC 4211 sec. 4.3)", e); }
|
|
464
458
|
/** @internal K = SHA1(LeadingInfo | ZZ | TrailingInfo) (RFC 2875 sec. 3, step 3c), under the
|
|
465
459
|
* digest the proof's own algorithm identifier names. */
|
|
@@ -762,7 +756,7 @@ function _x942ToPkcs3(spkiBytes, what) {
|
|
|
762
756
|
/** @internal How a key reads in the refusal above. A key the runtime imported without classifying
|
|
763
757
|
* carries no asymmetricKeyType, and reporting that as a type name says nothing an operator can act on. */
|
|
764
758
|
function _keyTypeLabel(what, key) {
|
|
765
|
-
var type = key
|
|
759
|
+
var type = guard.crypto.keyTypeOf(key);
|
|
766
760
|
if (typeof type !== "string" || type === "") {
|
|
767
761
|
return what + " carries an algorithm this runtime does not recognize as a key it can agree with";
|
|
768
762
|
}
|
|
@@ -1221,7 +1215,7 @@ function _buildCertReqMsg(spec, key, opts) {
|
|
|
1221
1215
|
}
|
|
1222
1216
|
|
|
1223
1217
|
function _build(spec, key, opts) {
|
|
1224
|
-
opts = opts ||
|
|
1218
|
+
opts = opts || intrinsic.create(null);
|
|
1225
1219
|
if (!spec || typeof spec !== "object" || _isBuffer(spec)) throw _err("crmf/bad-input", "the certificate-request-message spec must be an object");
|
|
1226
1220
|
var specs;
|
|
1227
1221
|
if (spec.messages != null) {
|
package/lib/csr-sign.js
CHANGED
|
@@ -209,7 +209,7 @@ function sign(spec, key, opts) {
|
|
|
209
209
|
}
|
|
210
210
|
|
|
211
211
|
function _sign(spec, key, opts) {
|
|
212
|
-
opts = opts ||
|
|
212
|
+
opts = opts || intrinsic.create(null);
|
|
213
213
|
if (!spec || typeof spec !== "object" || Buffer.isBuffer(spec)) throw _err("csr/bad-input", "the certification-request spec must be an object");
|
|
214
214
|
guard.identifier.assertKnownKeys(spec, KNOWN_SPEC_KEYS, _err, "csr/bad-input", "unknown spec field ");
|
|
215
215
|
guard.identifier.assertKnownKeys(opts, KNOWN_SIGN_OPTS, _err, "csr/bad-input", "pki.csr.sign has an unknown option ");
|