@blamejs/pki 0.5.16 → 0.5.18
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 +57 -1
- package/lib/acme.js +7 -4
- package/lib/asn1-der.js +1 -0
- package/lib/attrcert-sign.js +1 -0
- package/lib/cbor-det.js +1 -0
- package/lib/cmc-verify.js +1 -0
- package/lib/cmp-build.js +16 -1
- package/lib/cms-decrypt.js +58 -29
- package/lib/cms-encrypt.js +200 -38
- package/lib/cms-sign.js +18 -4
- package/lib/cms-verify.js +5 -1
- package/lib/constants.js +1 -0
- package/lib/crl-sign.js +62 -2
- package/lib/crmf-sign.js +1 -0
- package/lib/csr-sign.js +1 -0
- package/lib/ct.js +1 -0
- package/lib/est.js +1 -0
- package/lib/framework-error.js +1 -0
- package/lib/guard-secret.js +45 -1
- package/lib/hpke.js +6 -2
- package/lib/http-transport.js +1 -0
- package/lib/inspect.js +1 -0
- package/lib/jose.js +31 -3
- package/lib/key.js +2 -1
- package/lib/lint.js +1 -0
- package/lib/merkle.js +1 -0
- package/lib/ocsp.js +1 -0
- package/lib/oid.js +1 -0
- package/lib/path-validate.js +1 -0
- package/lib/pbes2.js +16 -8
- package/lib/pkcs12-build.js +203 -12
- package/lib/schema-all.js +1 -0
- package/lib/schema-c509.js +1 -0
- package/lib/schema-csrattrs.js +1 -0
- package/lib/schema-engine.js +1 -0
- package/lib/schema-pkcs8.js +1 -0
- package/lib/schema-smime.js +1 -0
- package/lib/schema-tsp.js +1 -0
- package/lib/schema-x509.js +1 -0
- package/lib/shbs.js +1 -0
- package/lib/sigstore.js +1 -0
- package/lib/smime.js +1 -0
- package/lib/tls-cert-compress.js +1 -0
- package/lib/trust.js +1 -0
- package/lib/tsp-sign.js +65 -0
- package/lib/webauthn.js +1 -0
- package/lib/webcrypto.js +11 -8
- package/lib/x509-sign.js +38 -0
- package/package.json +1 -1
- package/sbom.cdx.json +6 -6
package/lib/webcrypto.js
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
* @module pki.webcrypto
|
|
6
6
|
* @nav Core
|
|
7
7
|
* @title WebCrypto
|
|
8
|
+
* @fullname WebCrypto: a SubtleCrypto surface over node:crypto
|
|
8
9
|
* @order 50
|
|
9
10
|
* @featured true
|
|
10
11
|
* @slug webcrypto
|
|
@@ -470,7 +471,7 @@ SubtleCrypto.prototype.encrypt = async function encrypt(algorithm, key, data) {
|
|
|
470
471
|
return _withSecretBytes(key, function (kb) {
|
|
471
472
|
var cipher = nodeCrypto.createCipheriv("aes-" + key.algorithm.length + "-gcm", kb, iv, { authTagLength: (alg.tagLength || 128) / 8 });
|
|
472
473
|
if (aad) cipher.setAAD(aad);
|
|
473
|
-
var ct =
|
|
474
|
+
var ct = guard.secret.cipherFinish(cipher, buf, WebCryptoError, "webcrypto/operation", "an AES-GCM encrypt intermediate");
|
|
474
475
|
return Buffer.concat([ct, cipher.getAuthTag()]);
|
|
475
476
|
});
|
|
476
477
|
}, "encrypt"));
|
|
@@ -480,7 +481,7 @@ SubtleCrypto.prototype.encrypt = async function encrypt(algorithm, key, data) {
|
|
|
480
481
|
return _toArrayBuffer(_runCipher(function () {
|
|
481
482
|
return _withSecretBytes(key, function (kb) {
|
|
482
483
|
var c2 = nodeCrypto.createCipheriv("aes-" + key.algorithm.length + "-cbc", kb, cbcIv);
|
|
483
|
-
return
|
|
484
|
+
return guard.secret.cipherFinish(c2, buf, WebCryptoError, "webcrypto/operation", "an AES-CBC encrypt intermediate");
|
|
484
485
|
});
|
|
485
486
|
}, "encrypt"));
|
|
486
487
|
}
|
|
@@ -490,7 +491,7 @@ SubtleCrypto.prototype.encrypt = async function encrypt(algorithm, key, data) {
|
|
|
490
491
|
return _toArrayBuffer(_runCipher(function () {
|
|
491
492
|
return _withSecretBytes(key, function (kb) {
|
|
492
493
|
var c3 = nodeCrypto.createCipheriv("aes-" + key.algorithm.length + "-ctr", kb, ctrCounter);
|
|
493
|
-
return
|
|
494
|
+
return guard.secret.cipherFinish(c3, buf, WebCryptoError, "webcrypto/operation", "an AES-CTR encrypt intermediate");
|
|
494
495
|
});
|
|
495
496
|
}, "encrypt"));
|
|
496
497
|
}
|
|
@@ -528,7 +529,9 @@ SubtleCrypto.prototype.decrypt = async function decrypt(algorithm, key, data) {
|
|
|
528
529
|
var d = nodeCrypto.createDecipheriv("aes-" + key.algorithm.length + "-gcm", kb, iv, { authTagLength: tagLen });
|
|
529
530
|
if (gcmAad) d.setAAD(gcmAad);
|
|
530
531
|
d.setAuthTag(tag);
|
|
531
|
-
|
|
532
|
+
// The recovered plaintext exists in full before final() judges the tag, so a forged message
|
|
533
|
+
// would otherwise abandon a readable copy on the throw path.
|
|
534
|
+
return guard.secret.cipherFinish(d, ct, WebCryptoError, "webcrypto/operation", "the recovered AES-GCM plaintext");
|
|
532
535
|
});
|
|
533
536
|
}, "decrypt"));
|
|
534
537
|
}
|
|
@@ -537,7 +540,7 @@ SubtleCrypto.prototype.decrypt = async function decrypt(algorithm, key, data) {
|
|
|
537
540
|
return _toArrayBuffer(_runCipher(function () {
|
|
538
541
|
return _withSecretBytes(key, function (kb) {
|
|
539
542
|
var d2 = nodeCrypto.createDecipheriv("aes-" + key.algorithm.length + "-cbc", kb, cbcIv2);
|
|
540
|
-
return
|
|
543
|
+
return guard.secret.cipherFinish(d2, buf, WebCryptoError, "webcrypto/operation", "the recovered AES-CBC plaintext");
|
|
541
544
|
});
|
|
542
545
|
}, "decrypt"));
|
|
543
546
|
}
|
|
@@ -547,7 +550,7 @@ SubtleCrypto.prototype.decrypt = async function decrypt(algorithm, key, data) {
|
|
|
547
550
|
return _toArrayBuffer(_runCipher(function () {
|
|
548
551
|
return _withSecretBytes(key, function (kb) {
|
|
549
552
|
var d3 = nodeCrypto.createDecipheriv("aes-" + key.algorithm.length + "-ctr", kb, ctrCounter2);
|
|
550
|
-
return
|
|
553
|
+
return guard.secret.cipherFinish(d3, buf, WebCryptoError, "webcrypto/operation", "the recovered AES-CTR plaintext");
|
|
551
554
|
});
|
|
552
555
|
}, "decrypt"));
|
|
553
556
|
}
|
|
@@ -874,7 +877,7 @@ SubtleCrypto.prototype.wrapKey = async function wrapKey(format, key, wrappingKey
|
|
|
874
877
|
try {
|
|
875
878
|
return _withSecretBytes(wrappingKey, function (wkBytes) {
|
|
876
879
|
var c = nodeCrypto.createCipheriv("aes" + wrappingKey.algorithm.length + "-wrap", wkBytes, Buffer.from("A6A6A6A6A6A6A6A6", "hex"));
|
|
877
|
-
return _toArrayBuffer(
|
|
880
|
+
return _toArrayBuffer(guard.secret.cipherFinish(c, bytes, WebCryptoError, "webcrypto/operation", "an AES-KW wrap intermediate"));
|
|
878
881
|
});
|
|
879
882
|
} catch (e) { throw new WebCryptoError("webcrypto/operation", "wrapKey: AES-KW key wrap failed", e); }
|
|
880
883
|
}
|
|
@@ -919,7 +922,7 @@ SubtleCrypto.prototype.unwrapKey = async function unwrapKey(format, wrappedKey,
|
|
|
919
922
|
try {
|
|
920
923
|
bytes = _withSecretBytes(unwrappingKey, function (kwBytes) {
|
|
921
924
|
var d = nodeCrypto.createDecipheriv("aes" + unwrappingKey.algorithm.length + "-wrap", kwBytes, Buffer.from("A6A6A6A6A6A6A6A6", "hex"));
|
|
922
|
-
return
|
|
925
|
+
return guard.secret.cipherFinish(d, wrapped, WebCryptoError, "webcrypto/operation", "the unwrapped key material");
|
|
923
926
|
});
|
|
924
927
|
} catch (e) { throw new WebCryptoError("webcrypto/operation", "unwrapKey: AES-KW key unwrap failed (integrity or length)", e); }
|
|
925
928
|
} else {
|
package/lib/x509-sign.js
CHANGED
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* @module pki.x509
|
|
7
7
|
* @nav Signing
|
|
8
8
|
* @title Certificates
|
|
9
|
+
* @fullname X.509 certificates: parse, sign and inspect
|
|
9
10
|
* @intro The X.509 certificate-issuance producing side. `pki.x509.sign` builds a `TBSCertificate`,
|
|
10
11
|
* signs it, and emits a `Certificate` (RFC 5280 sec. 4) that `pki.schema.x509.parse`,
|
|
11
12
|
* `pki.path.validate`, and OpenSSL all accept, self-signed or CA-signed, over any signature
|
|
@@ -52,6 +53,27 @@ var OID_SKI = O("subjectKeyIdentifier");
|
|
|
52
53
|
|
|
53
54
|
// The recognized keys of the `extensions` spec object; an unknown key is a typo and throws at
|
|
54
55
|
// config-time (a custom extension is passed as pre-encoded DER via the array form).
|
|
56
|
+
// The three caller-owned objects pki.x509.sign reads, each with its own door. A key nothing here
|
|
57
|
+
// names is a typo or a misplaced argument, and the failure it causes is invisible: the certificate
|
|
58
|
+
// builds, signs, and simply does not carry what was asked for. `spec.extension` (one letter short
|
|
59
|
+
// of `extensions`) emitted a certificate with NO extensions at all -- no basicConstraints on an
|
|
60
|
+
// intended CA, no keyUsage on an intended constrained leaf. `spec.issuer` is the other shape: the
|
|
61
|
+
// issuer is argument TWO, and nesting it in the spec left the certificate SELF-SIGNED with nothing
|
|
62
|
+
// to read as a failure.
|
|
63
|
+
//
|
|
64
|
+
// Every table is derived from what the function actually reads, not from the doc block, because a
|
|
65
|
+
// table naming a key nothing reads reopens the hole it was added to close.
|
|
66
|
+
var KNOWN_SPEC_KEYS = {
|
|
67
|
+
subject: 1, subjectPublicKey: 1, notBefore: 1, notAfter: 1, serialNumber: 1, extensions: 1,
|
|
68
|
+
};
|
|
69
|
+
// The issuer names itself in one of two FORMS, and the cert form wins unconditionally: when
|
|
70
|
+
// `issuer.cert` is present the builder takes the DN and the public key from it and never reads
|
|
71
|
+
// `name` or `publicKey`. A union accepted `{ key, cert, name: "Different CA", publicKey }` and
|
|
72
|
+
// signed under the certificate's identity while discarding the identity the caller wrote out.
|
|
73
|
+
var KNOWN_ISSUER_CERT_KEYS = { key: 1, cert: 1 };
|
|
74
|
+
var KNOWN_ISSUER_EXPLICIT_KEYS = { key: 1, name: 1, publicKey: 1 };
|
|
75
|
+
var KNOWN_SIGN_OPTS = { digestAlgorithm: 1, pem: 1, pss: 1 };
|
|
76
|
+
|
|
55
77
|
var KNOWN_EXT_KEYS = {
|
|
56
78
|
subjectKeyIdentifier: 1, authorityKeyIdentifier: 1, keyUsage: 1, keyUsageCritical: 1,
|
|
57
79
|
extendedKeyUsage: 1, extendedKeyUsageCritical: 1, basicConstraints: 1, subjectAltName: 1,
|
|
@@ -281,6 +303,22 @@ function _sign(spec, issuer, opts) {
|
|
|
281
303
|
opts = opts || {};
|
|
282
304
|
if (!spec || typeof spec !== "object" || Buffer.isBuffer(spec)) throw _err("x509/bad-input", "the certificate spec must be an object");
|
|
283
305
|
issuer = issuer || {};
|
|
306
|
+
// Before a single field is read, so a misspelling is a refusal rather than an omission carried
|
|
307
|
+
// into a signed certificate. The issuer message names its own argument because the mistake this
|
|
308
|
+
// catches most often is putting the issuer inside the spec, where it self-signed in silence.
|
|
309
|
+
guard.identifier.assertKnownKeys(spec, KNOWN_SPEC_KEYS, _err, "x509/bad-input", function (k) {
|
|
310
|
+
return "unknown certificate spec field " + JSON.stringify(k) +
|
|
311
|
+
(k === "issuer" ? "; the issuer is the SECOND argument to pki.x509.sign, not a spec field" : "") +
|
|
312
|
+
(k === "extension" ? "; the extensions spec field is `extensions`" : "");
|
|
313
|
+
});
|
|
314
|
+
var byCert = issuer.cert != null;
|
|
315
|
+
guard.identifier.assertKnownKeys(issuer, byCert ? KNOWN_ISSUER_CERT_KEYS : KNOWN_ISSUER_EXPLICIT_KEYS,
|
|
316
|
+
_err, "x509/bad-input", function (k) {
|
|
317
|
+
return "unknown issuer field " + JSON.stringify(k) + " for the " + (byCert
|
|
318
|
+
? "certificate form; issuer.cert supplies the name and the public key, so they are not read here"
|
|
319
|
+
: "explicit form; the issuer takes { key, name, publicKey }, or { key, cert } to take both from a certificate");
|
|
320
|
+
});
|
|
321
|
+
guard.identifier.assertKnownKeys(opts, KNOWN_SIGN_OPTS, _err, "x509/bad-input", "pki.x509.sign has an unknown option ");
|
|
284
322
|
if (issuer.key == null) throw _err("x509/bad-input", "a signing key (issuer.key, a PKCS#8 private key) is required");
|
|
285
323
|
|
|
286
324
|
var spki = _reqDer(spec.subjectPublicKey, "spec.subjectPublicKey (the SPKI DER of the certified key)");
|
package/package.json
CHANGED
package/sbom.cdx.json
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
"$schema": "http://cyclonedx.org/schema/bom-1.5.schema.json",
|
|
3
3
|
"bomFormat": "CycloneDX",
|
|
4
4
|
"specVersion": "1.5",
|
|
5
|
-
"serialNumber": "urn:uuid:
|
|
5
|
+
"serialNumber": "urn:uuid:123ddb5e-05ea-4e65-9d7d-7a667c46e3a3",
|
|
6
6
|
"version": 1,
|
|
7
7
|
"metadata": {
|
|
8
|
-
"timestamp": "2026-08-
|
|
8
|
+
"timestamp": "2026-08-20T20:31:47.390Z",
|
|
9
9
|
"lifecycles": [
|
|
10
10
|
{
|
|
11
11
|
"phase": "build"
|
|
@@ -19,14 +19,14 @@
|
|
|
19
19
|
}
|
|
20
20
|
],
|
|
21
21
|
"component": {
|
|
22
|
-
"bom-ref": "@blamejs/pki@0.5.
|
|
22
|
+
"bom-ref": "@blamejs/pki@0.5.18",
|
|
23
23
|
"type": "application",
|
|
24
24
|
"name": "pki",
|
|
25
|
-
"version": "0.5.
|
|
25
|
+
"version": "0.5.18",
|
|
26
26
|
"scope": "required",
|
|
27
27
|
"author": "blamejs contributors",
|
|
28
28
|
"description": "Pure-JavaScript PKI toolkit that owns its stack — X.509, ASN.1/DER, CMS, PQC-first.",
|
|
29
|
-
"purl": "pkg:npm/%40blamejs/pki@0.5.
|
|
29
|
+
"purl": "pkg:npm/%40blamejs/pki@0.5.18",
|
|
30
30
|
"properties": [],
|
|
31
31
|
"externalReferences": [
|
|
32
32
|
{
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
"components": [],
|
|
55
55
|
"dependencies": [
|
|
56
56
|
{
|
|
57
|
-
"ref": "@blamejs/pki@0.5.
|
|
57
|
+
"ref": "@blamejs/pki@0.5.18",
|
|
58
58
|
"dependsOn": []
|
|
59
59
|
}
|
|
60
60
|
]
|