@blamejs/pki 0.5.30 → 0.5.32
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 +28 -0
- package/README.md +2 -2
- package/lib/acme.js +347 -90
- package/lib/asn1-der.js +97 -33
- package/lib/attrcert-sign.js +1 -1
- package/lib/cmc-build.js +19 -8
- package/lib/cmc-verify.js +4 -4
- package/lib/cmp-build.js +36 -6
- package/lib/cmp-session.js +5 -5
- package/lib/cmp-verify.js +86 -16
- package/lib/cms-compress.js +2 -2
- package/lib/cms-decrypt.js +3 -3
- package/lib/cms-encrypt.js +1 -1
- package/lib/cms-sign.js +7 -7
- package/lib/cms-verify.js +9 -4
- package/lib/crl-sign.js +5 -5
- package/lib/crmf-sign.js +2 -1
- package/lib/csr-sign.js +1 -4
- package/lib/ct.js +8 -4
- package/lib/est.js +234 -34
- package/lib/framework-error.js +20 -6
- package/lib/guard-bytes.js +24 -3
- package/lib/http-digest.js +69 -16
- package/lib/http-retry-after.js +68 -24
- package/lib/http-transport.js +60 -6
- package/lib/inspect.js +13 -2
- package/lib/ip-utils.js +102 -25
- package/lib/key.js +2 -2
- package/lib/lint.js +1 -1
- package/lib/mime.js +27 -4
- package/lib/ocsp.js +7 -7
- package/lib/oid.js +16 -0
- package/lib/path-validate.js +76 -18
- package/lib/pbes2.js +2 -2
- package/lib/pkcs12-build.js +2 -2
- package/lib/pki-build.js +320 -21
- package/lib/rfc3339.js +75 -17
- package/lib/schema-c509.js +36 -9
- package/lib/schema-cmc.js +3 -3
- package/lib/schema-pkix.js +174 -25
- package/lib/schema-tsp.js +10 -1
- package/lib/sign-scheme.js +27 -7
- package/lib/sigstore.js +52 -9
- package/lib/smime.js +86 -6
- package/lib/trust.js +114 -14
- package/lib/tsp-sign.js +39 -27
- package/lib/validator-tpm.js +2 -2
- package/lib/webauthn-mds.js +24 -6
- package/lib/webauthn.js +3 -3
- package/lib/webcrypto.js +1 -1
- package/lib/x509-sign.js +9 -5
- package/package.json +1 -1
- package/sbom.cdx.json +6 -6
package/lib/cms-compress.js
CHANGED
|
@@ -37,7 +37,7 @@ var NULL_PARAMS_DER = Buffer.from([0x05, 0x00]);
|
|
|
37
37
|
// (default id-data), eContent = the RFC 1950 ZLIB stream }.
|
|
38
38
|
async function compress(content, opts) {
|
|
39
39
|
opts = opts || {};
|
|
40
|
-
var raw = guard.bytes.
|
|
40
|
+
var raw = guard.bytes.source(content, CmsError, "cms/bad-input", "content");
|
|
41
41
|
var level = opts.level;
|
|
42
42
|
if (level !== undefined && (typeof level !== "number" || !isFinite(level) || Math.floor(level) !== level)) throw _err("cms/bad-input", "opts.level must be an integer");
|
|
43
43
|
var ctName = opts.contentType || "data";
|
|
@@ -86,7 +86,7 @@ async function decompress(input, opts) {
|
|
|
86
86
|
}
|
|
87
87
|
|
|
88
88
|
function _toDer(input) {
|
|
89
|
-
if (
|
|
89
|
+
if (guard.bytes.isByteSource(input)) return guard.bytes.snapshotSource(input, CmsError, "cms/bad-input", "input");
|
|
90
90
|
if (typeof input === "string") { try { return schemaCms.pemDecode(input); } catch (e) { throw _err("cms/bad-input", "the CMS PEM could not be decoded", e); } }
|
|
91
91
|
throw _err("cms/bad-input", "input must be a DER Buffer, Uint8Array, or PEM string");
|
|
92
92
|
}
|
package/lib/cms-decrypt.js
CHANGED
|
@@ -129,7 +129,7 @@ function _parse(input) {
|
|
|
129
129
|
return schemaCms.parse(_toDer(input));
|
|
130
130
|
}
|
|
131
131
|
function _toDer(input) {
|
|
132
|
-
if (
|
|
132
|
+
if (guard.bytes.isByteSource(input)) return guard.bytes.snapshotSource(input, CmsError, "cms/bad-input", "input");
|
|
133
133
|
if (typeof input === "string") { try { return schemaCms.pemDecode(input); } catch (e) { throw _err("cms/bad-input", "the CMS PEM could not be decoded", e); } }
|
|
134
134
|
throw _err("cms/bad-input", "input must be a DER Buffer, Uint8Array, or PEM string");
|
|
135
135
|
}
|
|
@@ -166,7 +166,7 @@ function _riKindForKey(km) {
|
|
|
166
166
|
throw _err("cms/bad-input", "key material needs { key, cert }, { password }, { kek }, or { cek }");
|
|
167
167
|
}
|
|
168
168
|
function _assertSupported(ri, km) {
|
|
169
|
-
if (ri.type === "kari" && ri.keyEncryptionAlgorithm &&
|
|
169
|
+
if (ri.type === "kari" && ri.keyEncryptionAlgorithm && intrinsic.stringIndexOf(intrinsic.toLowerCase(ri.keyEncryptionAlgorithm.name || ""), "mqv") !== -1) throw _err("cms/unsupported-algorithm", "ECMQV kari is not supported"); // /mqv/i (ASCII name)
|
|
170
170
|
if (ri.type === "ori") {
|
|
171
171
|
if (ri.oriType !== O("kem")) throw _err("cms/unsupported-recipient-type", "unsupported OtherRecipientInfo type " + ri.oriType);
|
|
172
172
|
if (ri.kemri && ri.kemri.kem && ri.kemri.kem.oid === O("id-kem-rsa")) throw _err("cms/unsupported-algorithm", "RSA-KEM is not supported");
|
|
@@ -801,7 +801,7 @@ function _releaseKeyDer(k) {
|
|
|
801
801
|
if (k && k.owned) guard.secret.zeroize(k.der, CmsError, "cms/bad-input", "the recipient private-key copy");
|
|
802
802
|
}
|
|
803
803
|
function _normCertDer(cert) {
|
|
804
|
-
if (
|
|
804
|
+
if (guard.bytes.isByteSource(cert)) return guard.bytes.snapshotSource(cert, CmsError, "cms/bad-input", "the recipient certificate");
|
|
805
805
|
if (typeof cert === "string") { try { return x509.pemDecode(cert); } catch (e) { throw _err("cms/bad-input", "the recipient certificate PEM could not be decoded", e); } }
|
|
806
806
|
throw _err("cms/bad-input", "the recipient certificate must be a DER Buffer or PEM string");
|
|
807
807
|
}
|
package/lib/cms-encrypt.js
CHANGED
|
@@ -41,7 +41,7 @@ function _algId(name, shape) { return shape === "null" ? b.sequence([b.oid(O(nam
|
|
|
41
41
|
// A certificate descriptor -> raw DER (the recipient cert is parsed for dispatch + rid; the caller
|
|
42
42
|
// supplies bytes, not a re-encoded parse).
|
|
43
43
|
function _normCertDer(cert, what) {
|
|
44
|
-
if (
|
|
44
|
+
if (guard.bytes.isByteSource(cert)) return guard.bytes.snapshotSource(cert, CmsError, "cms/bad-input", what || "a certificate");
|
|
45
45
|
if (typeof cert === "string") { try { return x509.pemDecode(cert); } catch (e) { throw _err("cms/bad-input", (what || "a certificate") + " PEM could not be decoded", e); } }
|
|
46
46
|
throw _err("cms/bad-input", (what || "a certificate") + " must be a DER Buffer, Uint8Array, or PEM string");
|
|
47
47
|
}
|
package/lib/cms-sign.js
CHANGED
|
@@ -134,7 +134,7 @@ function _resolveAttrPairs(list, what) {
|
|
|
134
134
|
return (list || []).map(function (a) {
|
|
135
135
|
var vals = (a.values || []).map(function (v) { return _toBuf(v, what); });
|
|
136
136
|
if (!vals.length) throw _err("cms/bad-input", "a signed attribute must carry at least one value (RFC 5652 -- Attribute values is SET SIZE (1..MAX))");
|
|
137
|
-
return { type:
|
|
137
|
+
return { type: oid.isDottedDecimal(a.type) ? a.type : O(a.type), values: vals };
|
|
138
138
|
});
|
|
139
139
|
}
|
|
140
140
|
|
|
@@ -351,17 +351,17 @@ function _keyOnlyKeyId(so) {
|
|
|
351
351
|
|
|
352
352
|
function _normCertDer(c) {
|
|
353
353
|
if (c == null) throw _err("cms/bad-input", "each signer requires a certificate (cert)");
|
|
354
|
-
if (
|
|
355
|
-
c = guard.bytes.
|
|
354
|
+
if (guard.bytes.isByteSource(c)) {
|
|
355
|
+
c = guard.bytes.snapshotSource(c, CmsError, "cms/bad-input", "a signer certificate");
|
|
356
356
|
return c[0] === 0x30 ? c : _pemToDer(c.toString("latin1")); // DER as-is, else PEM
|
|
357
357
|
}
|
|
358
358
|
if (typeof c === "string") return _pemToDer(c);
|
|
359
359
|
throw _err("cms/bad-input", "a signer certificate must be a DER Buffer or a PEM string");
|
|
360
360
|
}
|
|
361
361
|
function _pemToDer(text) {
|
|
362
|
-
var
|
|
363
|
-
if (
|
|
364
|
-
return
|
|
362
|
+
var der = pkix.pemDecodeLenient(text, "CERTIFICATE");
|
|
363
|
+
if (der === null) throw _err("cms/bad-input", "a signer certificate PEM is not a CERTIFICATE block");
|
|
364
|
+
return der;
|
|
365
365
|
}
|
|
366
366
|
|
|
367
367
|
// pki.cms.sign -- documented by the @primitive block in cms-verify.js (the @module pki.cms home).
|
|
@@ -460,7 +460,7 @@ function _dedupe(ders) {
|
|
|
460
460
|
}
|
|
461
461
|
|
|
462
462
|
function _toBuf(v, what) {
|
|
463
|
-
if (
|
|
463
|
+
if (guard.bytes.isByteSource(v)) return guard.bytes.snapshotSource(v, CmsError, "cms/bad-input", what);
|
|
464
464
|
throw _err("cms/bad-input", what + " must be a Buffer");
|
|
465
465
|
}
|
|
466
466
|
|
package/lib/cms-verify.js
CHANGED
|
@@ -123,7 +123,7 @@ EC_CURVE[oid.byName("secp384r1")] = { curve: "P-384", coordLen: 48 };
|
|
|
123
123
|
EC_CURVE[oid.byName("secp521r1")] = { curve: "P-521", coordLen: 66 };
|
|
124
124
|
|
|
125
125
|
function _toBuf(v, what) {
|
|
126
|
-
if (
|
|
126
|
+
if (guard.bytes.isByteSource(v)) return guard.bytes.snapshotSource(v, CmsError, "cms/bad-input", what);
|
|
127
127
|
throw _err("cms/bad-input", what + " must be a Buffer");
|
|
128
128
|
}
|
|
129
129
|
|
|
@@ -679,7 +679,7 @@ function _snapshotIfBytes(input, label) {
|
|
|
679
679
|
// Every byte form the parser accepts -- an ArrayBuffer or a DataView reaches the
|
|
680
680
|
// decoder as readily as a Buffer, and leaving those aliased would reopen the
|
|
681
681
|
// window for exactly the inputs that came in by the wider door.
|
|
682
|
-
if (
|
|
682
|
+
if (guard.bytes.isByteSource(input)) {
|
|
683
683
|
return guard.bytes.snapshotSource(input, CmsError, "cms/bad-input", label);
|
|
684
684
|
}
|
|
685
685
|
return input;
|
|
@@ -804,7 +804,7 @@ function setEngine(engine) { _engine = engine; }
|
|
|
804
804
|
// rewritten. `requiredEku` is copied for the same reason as the array.
|
|
805
805
|
var _ANCHOR_CLONE_DEPTH = 8;
|
|
806
806
|
function _cloneAnchorValue(v, depth) {
|
|
807
|
-
if (
|
|
807
|
+
if (guard.bytes.isByteSource(v)) {
|
|
808
808
|
return _snapshotIfBytes(v, "opts.trustAnchors[]");
|
|
809
809
|
}
|
|
810
810
|
if (v === null || typeof v !== "object") return v;
|
|
@@ -969,7 +969,12 @@ function _applyTrust(res, parsedCerts, cfg) {
|
|
|
969
969
|
// A CONFIG fault -- unusable anchors, an invalid time -- is the caller's mistake and must
|
|
970
970
|
// not be absorbed into "untrusted", which would read as a verdict about the message. A
|
|
971
971
|
// chain that simply does not reach an anchor is not that: it is the answer.
|
|
972
|
-
if (e && e.code
|
|
972
|
+
if (e && e.code) {
|
|
973
|
+
var code = String(e.code);
|
|
974
|
+
if (intrinsic.stringIndexOf(code, "bad-input") !== -1 ||
|
|
975
|
+
intrinsic.stringIndexOf(code, "bad-anchor") !== -1 ||
|
|
976
|
+
intrinsic.stringIndexOf(code, "bad-time") !== -1) throw e;
|
|
977
|
+
}
|
|
973
978
|
s.trusted = false;
|
|
974
979
|
});
|
|
975
980
|
});
|
package/lib/crl-sign.js
CHANGED
|
@@ -180,7 +180,7 @@ function _resolveReason(reason, isDelta) {
|
|
|
180
180
|
// The AKI keyIdentifier from the issuer: an explicit Buffer, or true -> the issuer cert's subjectKeyIdentifier,
|
|
181
181
|
// else the SHA-1 of the issuer SPKI (RFC 5280 sec. 5.2.1 key-identifier method).
|
|
182
182
|
function _akiKeyId(val, ctx) {
|
|
183
|
-
if (
|
|
183
|
+
if (guard.bytes.isByteSource(val)) return guard.bytes.snapshotSource(val, CrlError, "crl/bad-input", "the authorityKeyIdentifier keyIdentifier");
|
|
184
184
|
if (val === true) {
|
|
185
185
|
if (ctx.issuerCert) {
|
|
186
186
|
var ski = (ctx.issuerCert.extensions || []).filter(function (e) { return e.oid === OID_SKI; })[0];
|
|
@@ -463,7 +463,7 @@ function _sign(spec, issuer, opts) {
|
|
|
463
463
|
: "explicit form; the issuer takes { key, name, publicKey }, or { key, cert } to take both from a certificate");
|
|
464
464
|
});
|
|
465
465
|
guard.identifier.assertKnownKeys(opts, KNOWN_SIGN_OPTS, _err, "crl/bad-input", "pki.crl.sign has an unknown option ");
|
|
466
|
-
if (issuer.key == null) throw _err("crl/bad-input", "a signing key (issuer.key, a PKCS#8 private key) is required");
|
|
466
|
+
if (issuer.key == null) throw _err("crl/bad-input", "a signing key (issuer.key, a WebCrypto CryptoKey or a PKCS#8 private key DER/PEM) is required");
|
|
467
467
|
|
|
468
468
|
// Resolve the issuer name + signing-key SPKI. `{ cert }` supplies both; else `{ name|spec.issuer, publicKey }`.
|
|
469
469
|
var issuerDer, issuerSpki, issuerCert = null;
|
|
@@ -597,7 +597,7 @@ function _coerceCrl(crl) {
|
|
|
597
597
|
// names, are separate questions that only a certificate can answer.
|
|
598
598
|
function _resolveIssuer(issuer) {
|
|
599
599
|
if (issuer == null) throw _err("crl/bad-input", "an issuer is required to verify a CRL");
|
|
600
|
-
if (
|
|
600
|
+
if (guard.bytes.isByteSource(issuer)) { var _isp = guard.bytes.source(issuer, CrlError, "crl/bad-input", "issuer SPKI"); _assertValidSpki(_isp, "issuer SPKI"); return { spki: _isp, cert: null }; }
|
|
601
601
|
if (issuer.cert != null) { var ic = _parseIssuerCert(issuer.cert); return { spki: ic.subjectPublicKeyInfo.bytes, cert: ic }; }
|
|
602
602
|
if (issuer.publicKey != null) { var spki = _reqDer(issuer.publicKey, "issuer.publicKey"); _assertValidSpki(spki, "issuer.publicKey"); return { spki: spki, cert: null }; }
|
|
603
603
|
// A parsed certificate passed directly. It reaches the same identity and cRLSign checks the
|
|
@@ -685,8 +685,8 @@ function _serialHexOf(serial) {
|
|
|
685
685
|
if (typeof serial === "bigint") v = serial;
|
|
686
686
|
else if (typeof serial === "number") { if (!Number.isSafeInteger(serial)) throw _err("crl/bad-input", "serialNumber number must be a safe integer (pass a BigInt, hex string, or Buffer)"); v = BigInt(serial); }
|
|
687
687
|
else if (typeof serial === "string") { try { v = BigInt(serial); } catch (e) { throw _err("crl/bad-input", "serialNumber string must be a decimal or 0x-hex integer", e); } }
|
|
688
|
-
else if (
|
|
689
|
-
else throw _err("crl/bad-input", "serialNumber must be a BigInt, integer, hex string, or
|
|
688
|
+
else if (guard.bytes.isByteSource(serial)) { var _sb = guard.bytes.source(serial, CrlError, "crl/bad-input", "serialNumber"); v = _sb.length ? BigInt("0x" + _sb.toString("hex")) : 0n; }
|
|
689
|
+
else throw _err("crl/bad-input", "serialNumber must be a BigInt, integer, hex string, or BufferSource");
|
|
690
690
|
if (v <= 0n) throw _err("crl/bad-input", "serialNumber must be a positive integer");
|
|
691
691
|
// Match schema-crl's serialNumberHex: the DER INTEGER content octets (preserving sign padding).
|
|
692
692
|
return asn1.decode(b.integer(v)).content.toString("hex");
|
package/lib/crmf-sign.js
CHANGED
|
@@ -328,7 +328,8 @@ function _buildEncryptedKeyPop(pop, outerTag, template) {
|
|
|
328
328
|
// reject. CBC is the default here for that reason, not as a preference between the two.
|
|
329
329
|
var cea = pop.contentEncryptionAlgorithm || "aes-256-cbc";
|
|
330
330
|
if (typeof cea !== "string") throw _err("crmf/bad-input", "pop.contentEncryptionAlgorithm must be an algorithm name");
|
|
331
|
-
|
|
331
|
+
var _ceaLc = intrinsic.toLowerCase(cea); // /gcm|ccm|chacha/i (ASCII algorithm name)
|
|
332
|
+
if (intrinsic.stringIndexOf(_ceaLc, "gcm") !== -1 || intrinsic.stringIndexOf(_ceaLc, "ccm") !== -1 || intrinsic.stringIndexOf(_ceaLc, "chacha") !== -1) {
|
|
332
333
|
throw _err("crmf/bad-popo", "encryptedKey is typed EnvelopedData, and the AEAD algorithm " + cea +
|
|
333
334
|
" produces an AuthEnvelopedData instead (RFC 5083) -- choose a CBC content-encryption algorithm");
|
|
334
335
|
}
|
package/lib/csr-sign.js
CHANGED
|
@@ -47,9 +47,6 @@ var _b = pkiBuild.makeBuilder({
|
|
|
47
47
|
NAME_SCHEMA: pkix.name(NS), SPKI_SCHEMA: pkix.spki(NS), EXT_DECODERS: EXT_DECODERS,
|
|
48
48
|
});
|
|
49
49
|
|
|
50
|
-
// challengePassword DirectoryString charset (PrintableString set); anything else uses UTF8String.
|
|
51
|
-
var PRINTABLE_RE = /^[A-Za-z0-9 '()+,\-./:=?]*$/;
|
|
52
|
-
|
|
53
50
|
// attributes ::= [0] IMPLICIT SET OF Attribute (RFC 2986). The IMPLICIT tag replaces the universal SET,
|
|
54
51
|
// so it is a context-constructed [0] whose DER-sorted members ARE the SET-OF; empty -> A0 00.
|
|
55
52
|
function _implicitSetOf0(members) {
|
|
@@ -64,7 +61,7 @@ function _buildRequestedExtensions(extSpec, subjectSpki) { return _b.requestedEx
|
|
|
64
61
|
// value is in that charset, else UTF8String; never a Teletex/BMP/Universal string for a new value.
|
|
65
62
|
function _challengePassword(pw) {
|
|
66
63
|
if (typeof pw !== "string" || pw.length < 1 || pw.length > 255) throw _err("csr/bad-input", "challengePassword must be a 1..255 character string (RFC 2985 sec. 5.4.1)");
|
|
67
|
-
return
|
|
64
|
+
return asn1.isPrintableString(pw) ? b.printable(pw) : b.utf8(pw);
|
|
68
65
|
}
|
|
69
66
|
|
|
70
67
|
/**
|
package/lib/ct.js
CHANGED
|
@@ -49,6 +49,10 @@ var intrinsic = require("./guard-intrinsic.js");
|
|
|
49
49
|
// replaceable properties to answer one thing, and here it decides whether a log state is one this
|
|
50
50
|
// toolkit trusts -- answering true for a name the table never carried trusts an untrusted log.
|
|
51
51
|
var _hasOwn = intrinsic.hasOwn;
|
|
52
|
+
var _strSlice = intrinsic.uncurry(String.prototype.slice);
|
|
53
|
+
var _JSON_SUFFIX = ".json";
|
|
54
|
+
// A pathname ending with the literal ".json" suffix (matching /\.json$/), by suffix compare (no regex).
|
|
55
|
+
function _endsWithJson(s) { return s.length >= _JSON_SUFFIX.length && _strSlice(s, s.length - _JSON_SUFFIX.length) === _JSON_SUFFIX; }
|
|
52
56
|
var ByteReader = require("./byte-reader.js");
|
|
53
57
|
var ByteWriter = require("./byte-writer.js");
|
|
54
58
|
var oid = require("./oid.js");
|
|
@@ -973,9 +977,9 @@ function _parseHttpsUrl(u, label) {
|
|
|
973
977
|
// yield an unambiguous sig URL, so the caller must pass opts.sigUrl explicitly (guards never guess a value).
|
|
974
978
|
// The derived URL inherits the json URL's https origin.
|
|
975
979
|
function _sigUrlFor(parsed) {
|
|
976
|
-
if (
|
|
980
|
+
if (!_endsWithJson(parsed.pathname)) throw _ctErr("ct/bad-input", "cannot derive the detached-signature URL from a non-.json path (" + JSON.stringify(parsed.pathname) + "); pass opts.sigUrl explicitly");
|
|
977
981
|
var sig = new URL(parsed.href);
|
|
978
|
-
sig.pathname = parsed.pathname.
|
|
982
|
+
sig.pathname = _strSlice(parsed.pathname, 0, parsed.pathname.length - _JSON_SUFFIX.length) + ".sig";
|
|
979
983
|
return sig.href;
|
|
980
984
|
}
|
|
981
985
|
|
|
@@ -994,8 +998,8 @@ function _fetchBody(transport, url, req, label) {
|
|
|
994
998
|
res = res || {};
|
|
995
999
|
var h = {};
|
|
996
1000
|
Object.keys(res.headers || {}).forEach(function (k) { h[k.toLowerCase()] = res.headers[k]; });
|
|
997
|
-
var body =
|
|
998
|
-
? guard.bytes.
|
|
1001
|
+
var body = guard.bytes.isByteSource(res.body)
|
|
1002
|
+
? guard.bytes.source(res.body, CtError, "ct/bad-input", label)
|
|
999
1003
|
: Buffer.from(String(res.body == null ? "" : res.body), "utf8");
|
|
1000
1004
|
if (body.length > req.maxResponseBytes) throw _ctErr("ct/response-too-large", "the " + label + " (" + body.length + " bytes) exceeds the " + req.maxResponseBytes + "-byte cap");
|
|
1001
1005
|
if (res.status !== 200) throw _ctErr("ct/http-error", "the CT server returned HTTP " + JSON.stringify(res.status) + " for the " + label);
|