@blamejs/pki 0.8.55 → 0.8.57
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 +94 -0
- package/README.md +1 -1
- package/lib/acme.js +2 -2
- package/lib/asn1-der.js +17 -5
- package/lib/attrcert-verify.js +1 -1
- package/lib/cmc-verify.js +1 -1
- package/lib/cmp-session.js +2 -2
- package/lib/cmp-verify.js +2 -2
- package/lib/cms-decrypt.js +4 -1
- package/lib/cms-encrypt.js +4 -1
- package/lib/cms-sign.js +26 -12
- package/lib/cms-verify.js +1 -1
- package/lib/composite-kem.js +30 -12
- package/lib/composite-sig.js +42 -23
- package/lib/constants.js +7 -2
- package/lib/crl-verify.js +1 -1
- package/lib/crmf-sign.js +72 -43
- package/lib/crmf-verify.js +1 -1
- package/lib/csr-verify.js +1 -1
- package/lib/ct.js +2 -2
- package/lib/edwards-point.js +1 -1
- package/lib/est.js +3 -3
- package/lib/guard-async.js +22 -1
- package/lib/guard-bytes.js +6 -3
- package/lib/guard-identifier.js +1 -1
- package/lib/guard-intrinsic.js +474 -0
- package/lib/guard-parsed.js +23 -7
- package/lib/http-digest.js +146 -62
- package/lib/http-transport.js +82 -17
- package/lib/identity-match.js +2 -2
- package/lib/inspect.js +1 -1
- package/lib/lint.js +51 -3
- package/lib/merkle.js +2 -2
- package/lib/ocsp-request-verify.js +1 -1
- package/lib/ocsp.js +53 -22
- package/lib/oid.js +7 -0
- package/lib/path-validate.js +169 -76
- package/lib/pbes2.js +14 -7
- package/lib/schema-attrcert.js +2 -2
- package/lib/schema-cmc.js +2 -2
- package/lib/schema-cmp.js +2 -2
- package/lib/schema-cms.js +115 -10
- package/lib/schema-crmf.js +2 -2
- package/lib/schema-csr.js +2 -2
- package/lib/schema-ocsp.js +41 -6
- package/lib/schema-pkix.js +3 -3
- package/lib/schema-x509.js +2 -2
- package/lib/sigstore.js +1 -1
- package/lib/tlog.js +7 -4
- package/lib/trust.js +187 -104
- package/lib/tsp-sign.js +1 -1
- package/lib/webauthn-mds.js +257 -121
- package/lib/webauthn.js +327 -164
- package/lib/webcrypto.js +10 -3
- package/package.json +1 -1
- package/sbom.cdx.json +6 -6
package/lib/composite-sig.js
CHANGED
|
@@ -24,7 +24,6 @@ var _promiseResolve = _intrinsic.uncurry(_intrinsic.promiseResolve);
|
|
|
24
24
|
/** @internal The aggregator is the same defect one step out: the composite verdict is `ok` only when
|
|
25
25
|
* BOTH component verifications resolve true, so a replaced `all` that resolves `[true, true]` without
|
|
26
26
|
* awaiting either half reports a forged signature as verified. */
|
|
27
|
-
var _promiseAll = _intrinsic.uncurry(_intrinsic.promiseAll);
|
|
28
27
|
var _b = asn1.build;
|
|
29
28
|
|
|
30
29
|
function _codeOf(e, fallback) {
|
|
@@ -85,7 +84,11 @@ function compositeMprime(d, phBuf, ctx) {
|
|
|
85
84
|
function _verifyTradComponent(trad, tradPK, tradSig, mprime, E, badSig) {
|
|
86
85
|
if (trad.ec) {
|
|
87
86
|
if (tradPK.length < 1 || tradPK[0] !== 0x04) return _promiseResolve(_Promise, false);
|
|
88
|
-
|
|
87
|
+
/** @internal Every continuation on this path comes from the capture. A continuation is read off
|
|
88
|
+
* the promise at the call, and these deliver the two component verdicts a composite signature is
|
|
89
|
+
* the conjunction of: a replacement settling either one reports a component as verified without
|
|
90
|
+
* it having been checked, and the path validator that calls this reads the conjunction. */
|
|
91
|
+
return _intrinsic.chain(subtle.importKey("spki", _ecSpki(trad.ec, tradPK), { name: "ECDSA" }, false, ["verify"]), function (k) {
|
|
89
92
|
var p1363 = validator.sig.ecdsaDerToP1363(tradSig, trad.ec, E, badSig);
|
|
90
93
|
return _subtleVerify(subtle, { name: "ECDSA", hash: trad.hash }, k, p1363, mprime);
|
|
91
94
|
});
|
|
@@ -94,8 +97,8 @@ function _verifyTradComponent(trad, tradPK, tradSig, mprime, E, badSig) {
|
|
|
94
97
|
if (!edwardsPoint.validate(tradPK, trad.eddsa === "Ed25519" ? 6 : 7)) {
|
|
95
98
|
throw new E(badSig, "the composite EdDSA component public key is not a valid, full-order Edwards point");
|
|
96
99
|
}
|
|
97
|
-
return subtle.importKey("spki", _edSpki(trad.eddsa, tradPK), { name: trad.eddsa }, false, ["verify"])
|
|
98
|
-
|
|
100
|
+
return _intrinsic.chain(subtle.importKey("spki", _edSpki(trad.eddsa, tradPK), { name: trad.eddsa }, false, ["verify"]),
|
|
101
|
+
function (k) { return _subtleVerify(subtle, { name: trad.eddsa }, k, tradSig, mprime); });
|
|
99
102
|
}
|
|
100
103
|
if (trad.rsaPss || trad.rsaPkcs1) {
|
|
101
104
|
var bits;
|
|
@@ -103,11 +106,11 @@ function _verifyTradComponent(trad, tradPK, tradSig, mprime, E, badSig) {
|
|
|
103
106
|
catch (_e) { return _promiseResolve(_Promise, false); }
|
|
104
107
|
if (bits !== trad.rsaBits) return _promiseResolve(_Promise, false);
|
|
105
108
|
if (trad.rsaPss) {
|
|
106
|
-
return subtle.importKey("spki", _rsaSpki(tradPK), { name: "RSA-PSS", hash: trad.hash }, false, ["verify"])
|
|
107
|
-
|
|
109
|
+
return _intrinsic.chain(subtle.importKey("spki", _rsaSpki(tradPK), { name: "RSA-PSS", hash: trad.hash }, false, ["verify"]),
|
|
110
|
+
function (k) { return _subtleVerify(subtle, { name: "RSA-PSS", saltLength: trad.salt }, k, tradSig, mprime); });
|
|
108
111
|
}
|
|
109
|
-
return subtle.importKey("spki", _rsaSpki(tradPK), { name: "RSASSA-PKCS1-v1_5", hash: trad.hash }, false, ["verify"])
|
|
110
|
-
|
|
112
|
+
return _intrinsic.chain(subtle.importKey("spki", _rsaSpki(tradPK), { name: "RSASSA-PKCS1-v1_5", hash: trad.hash }, false, ["verify"]),
|
|
113
|
+
function (k) { return _subtleVerify(subtle, { name: "RSASSA-PKCS1-v1_5" }, k, tradSig, mprime); });
|
|
111
114
|
}
|
|
112
115
|
return _promiseResolve(_Promise, false);
|
|
113
116
|
}
|
|
@@ -132,13 +135,21 @@ function compositeVerify(spkiBytes, sigBytes, message, d, E, unsupported, badSig
|
|
|
132
135
|
}
|
|
133
136
|
var mldsaPK = rawKey.subarray(0, d.mldsaPk), tradPK = rawKey.subarray(d.mldsaPk);
|
|
134
137
|
var mldsaSig = sigBytes.subarray(0, d.mldsaSig), tradSig = sigBytes.subarray(d.mldsaSig);
|
|
135
|
-
|
|
138
|
+
var combined = _intrinsic.chain(subtle.digest({ name: d.ph }, message), function (phBuf) {
|
|
136
139
|
var mprime = compositeMprime(d, phBuf);
|
|
137
|
-
var mldsaP = subtle.importKey("spki", _mldsaSpki(d.mldsaOid, mldsaPK), { name: d.mldsa }, false, ["verify"])
|
|
138
|
-
|
|
140
|
+
var mldsaP = _intrinsic.chain(subtle.importKey("spki", _mldsaSpki(d.mldsaOid, mldsaPK), { name: d.mldsa }, false, ["verify"]),
|
|
141
|
+
function (mk) { return _subtleVerify(subtle, { name: d.mldsa, context: d.label }, mk, mldsaSig, mprime); });
|
|
139
142
|
var tradP = _verifyTradComponent(d.trad, tradPK, tradSig, mprime, E, badSig);
|
|
140
|
-
|
|
141
|
-
|
|
143
|
+
/** @internal The conjunction is read from an aggregate that consults nothing replaceable: both
|
|
144
|
+
* components must answer `true`, so a settled value in place of either is a composite signature
|
|
145
|
+
* reported as verified on one half or on neither. A captured `Promise.all` is not enough, since
|
|
146
|
+
* it reads `resolve` off the constructor at each call and a replacement there answers for every
|
|
147
|
+
* member without any component being awaited. */
|
|
148
|
+
return _intrinsic.chain(_intrinsic.allOf([mldsaP, tradP]),
|
|
149
|
+
function (r) { return _verdictOf({ ok: r[0] === true && r[1] === true }); });
|
|
150
|
+
});
|
|
151
|
+
return _intrinsic.chain(combined, undefined,
|
|
152
|
+
function (e) { return _verdictOf({ ok: false, code: _codeOf(e, badSig), error: e }); });
|
|
142
153
|
}
|
|
143
154
|
|
|
144
155
|
function resolveCompositeDescriptor(sigAlg, E, unsupported) {
|
|
@@ -151,27 +162,35 @@ function resolveCompositeDescriptor(sigAlg, E, unsupported) {
|
|
|
151
162
|
}
|
|
152
163
|
|
|
153
164
|
function compositeSign(d, keys, message, ctx) {
|
|
154
|
-
|
|
165
|
+
/** @internal The signing half is continued through the captures too. Its output is the signature a
|
|
166
|
+
* verifier is then held to, so a replacement settling a component hands back bytes neither key
|
|
167
|
+
* produced and the signature does not verify anywhere. */
|
|
168
|
+
return _intrinsic.chain(subtle.digest({ name: d.ph }, message), function (phBuf) {
|
|
155
169
|
var mprime = compositeMprime(d, phBuf, ctx);
|
|
156
|
-
var mldsaP = subtle.importKey("pkcs8", keys.mldsa, { name: d.mldsa }, false, ["sign"])
|
|
157
|
-
|
|
170
|
+
var mldsaP = _intrinsic.chain(subtle.importKey("pkcs8", keys.mldsa, { name: d.mldsa }, false, ["sign"]),
|
|
171
|
+
function (k) { return subtle.sign({ name: d.mldsa, context: d.label }, k, mprime); });
|
|
158
172
|
var tradP = _signTradComponent(d.trad, keys.trad, mprime);
|
|
159
|
-
return
|
|
173
|
+
return _intrinsic.chain(_intrinsic.allOf([mldsaP, tradP]),
|
|
174
|
+
function (s) { return Buffer.concat([Buffer.from(s[0]), Buffer.from(s[1])]); });
|
|
160
175
|
});
|
|
161
176
|
}
|
|
162
177
|
function _signTradComponent(trad, pkcs8, mprime) {
|
|
163
178
|
if (trad.ec) {
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
179
|
+
var ecSigned = _intrinsic.chain(subtle.importKey("pkcs8", pkcs8, { name: "ECDSA", namedCurve: trad.ec }, false, ["sign"]),
|
|
180
|
+
function (k) { return subtle.sign({ name: "ECDSA", hash: trad.hash }, k, mprime); });
|
|
181
|
+
return _intrinsic.chain(ecSigned,
|
|
182
|
+
function (raw) { var r = Buffer.from(raw); return validator.sig.rawToEcdsaDer(r, r.length / 2); });
|
|
167
183
|
}
|
|
168
184
|
if (trad.eddsa) {
|
|
169
|
-
|
|
170
|
-
|
|
185
|
+
var edSigned = _intrinsic.chain(subtle.importKey("pkcs8", pkcs8, { name: trad.eddsa }, false, ["sign"]),
|
|
186
|
+
function (k) { return subtle.sign({ name: trad.eddsa }, k, mprime); });
|
|
187
|
+
return _intrinsic.chain(edSigned, function (s) { return Buffer.from(s); });
|
|
171
188
|
}
|
|
172
189
|
var imp = trad.rsaPss ? { name: "RSA-PSS", hash: trad.hash } : { name: "RSASSA-PKCS1-v1_5", hash: trad.hash };
|
|
173
190
|
var alg = trad.rsaPss ? { name: "RSA-PSS", saltLength: trad.salt } : { name: "RSASSA-PKCS1-v1_5" };
|
|
174
|
-
|
|
191
|
+
var rsaSigned = _intrinsic.chain(subtle.importKey("pkcs8", pkcs8, imp, false, ["sign"]),
|
|
192
|
+
function (k) { return subtle.sign(alg, k, mprime); });
|
|
193
|
+
return _intrinsic.chain(rsaSigned, function (s) { return Buffer.from(s); });
|
|
175
194
|
}
|
|
176
195
|
|
|
177
196
|
module.exports = {
|
package/lib/constants.js
CHANGED
|
@@ -319,10 +319,15 @@ Object.freeze(NAMES);
|
|
|
319
319
|
|
|
320
320
|
var VERSION = require("../package.json").version;
|
|
321
321
|
|
|
322
|
-
|
|
322
|
+
/** @internal Frozen, because these tables are read BY NAME at call time to decide an admission.
|
|
323
|
+
* `cms.sign` asks `NAMES.WEAK_DIGESTS` whether a digest is weak and `NAMES.TIMESTAMP_IMPRINT_DIGESTS`
|
|
324
|
+
* whether one is permitted at all, so a caller able to assign `constants.NAMES` a copy with an empty
|
|
325
|
+
* weak list turns the refusal off and a SHA-1 timestamp imprint is accepted. Freezing the tables
|
|
326
|
+
* alone left the PROPERTIES naming them writable, which is the same hole one level out. */
|
|
327
|
+
module.exports = Object.freeze({
|
|
323
328
|
TIME: TIME,
|
|
324
329
|
BYTES: BYTES,
|
|
325
330
|
LIMITS: LIMITS,
|
|
326
331
|
NAMES: NAMES,
|
|
327
332
|
version: VERSION,
|
|
328
|
-
};
|
|
333
|
+
});
|
package/lib/crl-verify.js
CHANGED
|
@@ -12,4 +12,4 @@ function verifyCrlSignature(crl, spkiBytes) {
|
|
|
12
12
|
return _seam.verify(crl.signatureAlgorithm, crl.signatureValue, spkiBytes, crl.tbsBytes);
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
module.exports = { setEngine: _seam.setEngine, verifyCrlSignature: verifyCrlSignature };
|
|
15
|
+
module.exports = Object.freeze({ setEngine: _seam.setEngine, verifyCrlSignature: verifyCrlSignature });
|
package/lib/crmf-sign.js
CHANGED
|
@@ -43,10 +43,9 @@ var _Promise = intrinsic.Promise;
|
|
|
43
43
|
var _promiseResolve = intrinsic.uncurry(intrinsic.promiseResolve);
|
|
44
44
|
/** @internal `verifyPop`'s verdict is the aggregate of the per-message results, so a replaced `all`
|
|
45
45
|
* that resolves a fabricated array reports an unverified proof of possession as verified. */
|
|
46
|
-
var _promiseAll = intrinsic.uncurry(intrinsic.promiseAll);
|
|
47
46
|
var _hasOwn = intrinsic.hasOwn;
|
|
48
47
|
var _isBuffer = intrinsic.isBuffer;
|
|
49
|
-
var
|
|
48
|
+
var _String = intrinsic.String;
|
|
50
49
|
var _stringify = intrinsic.stringify;
|
|
51
50
|
var cms = require("./schema-cms");
|
|
52
51
|
var possession = require("./possession");
|
|
@@ -108,7 +107,7 @@ function _ctlPossession(v) {
|
|
|
108
107
|
b.raw(_b.reqDer(issuerRaw, "statementOfPossession signer.issuer (the signature certificate's issuer Name DER)")),
|
|
109
108
|
b.integer(guard.range.authoredInteger(signer.serialNumber, _err, "crmf/bad-controls", "statementOfPossession signer.serialNumber")),
|
|
110
109
|
])];
|
|
111
|
-
if (v.certificate != null)
|
|
110
|
+
if (v.certificate != null) guard.list.append(fields, b.raw(_b.reqDer(v.certificate, "statementOfPossession certificate")));
|
|
112
111
|
var der = b.sequence(fields);
|
|
113
112
|
try { possession.parse(der); }
|
|
114
113
|
catch (e) { throw _err("crmf/bad-controls", "statementOfPossession: " + ((e && e.message) || _String(e)), e); }
|
|
@@ -177,8 +176,8 @@ function _encodeOptionalValidity(validity) {
|
|
|
177
176
|
var nb = validity.notBefore, na = validity.notAfter;
|
|
178
177
|
if (nb == null && na == null) throw _err("crmf/bad-validity", "validity must contain notBefore or notAfter (RFC 4211 sec. 5)");
|
|
179
178
|
var parts = [];
|
|
180
|
-
if (nb != null)
|
|
181
|
-
if (na != null)
|
|
179
|
+
if (nb != null) guard.list.append(parts, b.explicit(0, _b.timeDer(nb, "validity notBefore")));
|
|
180
|
+
if (na != null) guard.list.append(parts, b.explicit(1, _b.timeDer(na, "validity notAfter")));
|
|
182
181
|
// allow:nan-date-comparison-unguarded -- both instants passed timeDer's guard.time.assertEncodable above.
|
|
183
182
|
if (nb != null && na != null && guard.time.instantOf(nb) > guard.time.instantOf(na)) throw _err("crmf/bad-validity", "notBefore must not be after notAfter");
|
|
184
183
|
return b.implicit(4, b.sequence(parts));
|
|
@@ -190,19 +189,22 @@ function _encodeCertTemplate(tpl, opts) {
|
|
|
190
189
|
var fields = [];
|
|
191
190
|
if (tpl.version != null) {
|
|
192
191
|
if (tpl.version !== 2) throw _err("crmf/bad-version", "certTemplate version MUST be 2 (v3) if supplied (RFC 4211 sec. 5)");
|
|
193
|
-
|
|
192
|
+
guard.list.append(fields, b.implicit(0, b.integer(2n)));
|
|
194
193
|
}
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
if (tpl.
|
|
194
|
+
/** @internal Appended through the guard. These members are the template a proof of possession is
|
|
195
|
+
* computed over and a CA issues from, so a replaced append that drops or substitutes one changes
|
|
196
|
+
* what was requested from what was proven. */
|
|
197
|
+
if (tpl.serialNumber != null) guard.list.append(fields, b.implicit(1, _b.serialInteger(tpl.serialNumber)));
|
|
198
|
+
if (tpl.issuer != null) guard.list.append(fields, b.explicit(3, _b.encodeName(tpl.issuer)));
|
|
199
|
+
if (tpl.validity != null) guard.list.append(fields, _encodeOptionalValidity(tpl.validity));
|
|
200
|
+
if (tpl.subject != null) guard.list.append(fields, b.explicit(5, _b.encodeName(tpl.subject)));
|
|
199
201
|
var spki = null;
|
|
200
202
|
if (tpl.publicKey != null) {
|
|
201
203
|
spki = _b.reqDer(tpl.publicKey, "certTemplate.publicKey (the SPKI DER of the requested key)");
|
|
202
204
|
_b.assertValidSpki(spki, "certTemplate.publicKey");
|
|
203
|
-
|
|
205
|
+
guard.list.append(fields, b.implicit(6, spki));
|
|
204
206
|
}
|
|
205
|
-
if (tpl.extensions != null)
|
|
207
|
+
if (tpl.extensions != null) guard.list.append(fields, b.implicit(9, _b.requestedExtensions(tpl.extensions, spki)));
|
|
206
208
|
return { der: b.sequence(fields), spki: spki, complete: tpl.subject != null && tpl.publicKey != null };
|
|
207
209
|
}
|
|
208
210
|
|
|
@@ -237,7 +239,7 @@ function _buildAttrTypeAndValues(spec, code, label, valueMap, collect) {
|
|
|
237
239
|
var typeOid = O(k);
|
|
238
240
|
if (seen[typeOid]) throw _err(code, "duplicate " + label + " type " + k);
|
|
239
241
|
seen[typeOid] = true;
|
|
240
|
-
|
|
242
|
+
guard.list.append(out, b.sequence([b.oid(typeOid), enc(spec[k])]));
|
|
241
243
|
});
|
|
242
244
|
if (!out.length) throw _err(code, label + " must carry at least one entry");
|
|
243
245
|
return b.sequence(out);
|
|
@@ -916,19 +918,23 @@ function _buildEncryptedKeyPop(pop, outerTag, template) {
|
|
|
916
918
|
"the proof is that the enclosed private key is the one being certified (RFC 4211 sec. 4.2)");
|
|
917
919
|
}
|
|
918
920
|
encKeyWithIdDer = _encKeyWithID(privateKeyDer, pop.identifier);
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
921
|
+
/** @internal Each step is continued through the capture. The first decides whether the enclosed
|
|
922
|
+
* private key IS the one being certified, which is the whole proof, and the last is what wipes the
|
|
923
|
+
* key material whichever way the chain settles. */
|
|
924
|
+
var enveloped = intrinsic.chain(_assertEnclosedKeyMatches(privateKeyDer, template.spki), function () {
|
|
925
|
+
var encrypted = cmsEncrypt.encrypt(encKeyWithIdDer, recipients,
|
|
926
|
+
{ contentType: "encKeyWithID", contentEncryptionAlgorithm: cea });
|
|
927
|
+
return intrinsic.chain(encrypted, null, function (e) {
|
|
928
|
+
if (e instanceof CrmfError) throw e;
|
|
929
|
+
throw _err("crmf/bad-input", "the encryptedKey proof of possession could not envelope the private key to " +
|
|
930
|
+
"pop.recipients: " + ((e && e.message) || e), e);
|
|
931
|
+
});
|
|
932
|
+
});
|
|
933
|
+
var wrapped = intrinsic.chain(enveloped, function (contentInfo) {
|
|
934
|
+
var inner = _bareEnvelopedData(contentInfo);
|
|
935
|
+
return b.explicit(outerTag, b.implicit(4, inner));
|
|
936
|
+
});
|
|
937
|
+
return intrinsic.chain(wrapped, function (out) { wipe(); return out; }, function (e) { wipe(); throw e; });
|
|
932
938
|
}
|
|
933
939
|
}
|
|
934
940
|
|
|
@@ -964,9 +970,9 @@ function _assertEnclosedKeyMatches(privateKeyDer, templateSpki) {
|
|
|
964
970
|
* cannot use it, so those are proven by USING the key against the template. */
|
|
965
971
|
var enclosedAlg = key.algorithmOidAt(privateKeyDer, 1);
|
|
966
972
|
if (enclosedAlg !== null && !key.isDhOid(enclosedAlg)) return _assertEnclosedKeyCorresponds(privateKeyDer, templateSpki);
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
973
|
+
var derivedP = intrinsic.chain(_promiseResolve(_Promise, undefined),
|
|
974
|
+
function () { return key.publicFromPrivate(privateKeyDer); });
|
|
975
|
+
return intrinsic.chain(derivedP, function (derivedSpki) {
|
|
970
976
|
var derived = guard.bytes.view(derivedSpki, CrmfError, "crmf/bad-input", "the derived public key");
|
|
971
977
|
var wanted = guard.bytes.view(templateSpki, CrmfError, "crmf/bad-input", "certTemplate.publicKey");
|
|
972
978
|
/** @internal A finite-field key names itself in either encoding here too, and an enclosed key
|
|
@@ -1074,12 +1080,20 @@ function _buildProofOfPossession(pop, certReqDer, template, signingKey, opts, po
|
|
|
1074
1080
|
signedRegion = poposkSeq;
|
|
1075
1081
|
poposkInputField = b.implicit(0, poposkSeq);
|
|
1076
1082
|
}
|
|
1077
|
-
|
|
1078
|
-
|
|
1083
|
+
/** @internal Both continuations are captured. The inner one runs after the proof's own signature
|
|
1084
|
+
* has been verified against the key being certified, so a replacement settling it emits a proof
|
|
1085
|
+
* whose signature was never checked against that key. */
|
|
1086
|
+
return intrinsic.chain(signScheme.signOverTbs(scheme, signingKey, signedRegion, _signE), function (sig) {
|
|
1087
|
+
var selfChecked = _promiseResolve(_Promise, _b.assertSignatureVerifies(signedRegion, sig, provingSpki, scheme));
|
|
1088
|
+
return intrinsic.chain(selfChecked, function () {
|
|
1079
1089
|
var popoChildren = [];
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
|
-
|
|
1090
|
+
/** @internal Appended through the guard, which defines the index rather than calling a method
|
|
1091
|
+
* the prototype answers for. These three members ARE the proof: the signature value is added
|
|
1092
|
+
* AFTER it has been verified against the key being certified, so a replaced append that alters
|
|
1093
|
+
* it emits a proof whose bytes nothing checked. */
|
|
1094
|
+
if (poposkInputField) guard.list.append(popoChildren, poposkInputField);
|
|
1095
|
+
guard.list.append(popoChildren, scheme.sigAlgId);
|
|
1096
|
+
guard.list.append(popoChildren, b.bitString(sig, 0));
|
|
1083
1097
|
return b.implicit(1, b.sequence(popoChildren));
|
|
1084
1098
|
});
|
|
1085
1099
|
}, function (e) {
|
|
@@ -1171,7 +1185,7 @@ function _buildCertReqMsg(spec, key, opts) {
|
|
|
1171
1185
|
var template = _encodeCertTemplate(spec.certTemplate);
|
|
1172
1186
|
var certReqChildren = [b.integer(_certReqId(spec.certReqId)), template.der];
|
|
1173
1187
|
var encodedControls = [];
|
|
1174
|
-
if (spec.controls != null)
|
|
1188
|
+
if (spec.controls != null) guard.list.append(certReqChildren, _buildAttrTypeAndValues(spec.controls, "crmf/bad-controls", "controls", CONTROL_VALUE, encodedControls));
|
|
1175
1189
|
var certReqDer = b.sequence(certReqChildren);
|
|
1176
1190
|
|
|
1177
1191
|
/** @internal The key the RFC 9883 control names, when the request carries one: that key makes the
|
|
@@ -1196,10 +1210,12 @@ function _buildCertReqMsg(spec, key, opts) {
|
|
|
1196
1210
|
possessionSpki = _encodedPossessionSpki(encodedControls);
|
|
1197
1211
|
}
|
|
1198
1212
|
|
|
1199
|
-
|
|
1213
|
+
var popoP = _promiseResolve(_Promise,
|
|
1214
|
+
_buildProofOfPossession(spec.pop, certReqDer, template, signingKey, opts, possessionSpki));
|
|
1215
|
+
return intrinsic.chain(popoP, function (popoDer) {
|
|
1200
1216
|
var msgChildren = [certReqDer];
|
|
1201
|
-
if (popoDer)
|
|
1202
|
-
if (spec.regInfo != null)
|
|
1217
|
+
if (popoDer) guard.list.append(msgChildren, popoDer);
|
|
1218
|
+
if (spec.regInfo != null) guard.list.append(msgChildren, _buildAttrTypeAndValues(spec.regInfo, "crmf/bad-reg-info", "regInfo", REGINFO_VALUE));
|
|
1203
1219
|
return b.sequence(msgChildren);
|
|
1204
1220
|
});
|
|
1205
1221
|
}
|
|
@@ -1218,7 +1234,9 @@ function _build(spec, key, opts) {
|
|
|
1218
1234
|
specs = [spec];
|
|
1219
1235
|
}
|
|
1220
1236
|
if (!specs.length) throw _err("crmf/bad-input", "at least one certificate request message is required (RFC 4211 sec. 3)");
|
|
1221
|
-
return
|
|
1237
|
+
return intrinsic.chain(intrinsic.allOf(intrinsic.mapList(specs, function (s) {
|
|
1238
|
+
return _buildCertReqMsg(s, key, opts);
|
|
1239
|
+
})), function (msgs) {
|
|
1222
1240
|
var der = b.sequence(msgs);
|
|
1223
1241
|
if (opts.pem != null) {
|
|
1224
1242
|
if (typeof opts.pem !== "string" || !opts.pem) throw _err("crmf/bad-input", "opts.pem must be a non-empty PEM label string");
|
|
@@ -1310,7 +1328,10 @@ function _verifyOne(msg) {
|
|
|
1310
1328
|
spki = sopSpki;
|
|
1311
1329
|
bound = false;
|
|
1312
1330
|
}
|
|
1313
|
-
|
|
1331
|
+
/** @internal The continuation comes from the capture. It is where the signature answer becomes this
|
|
1332
|
+
* message's verdict, so a replacement settling it hands back a record stating `verified: true` for
|
|
1333
|
+
* a proof nothing checked, and the aggregate above then reports the whole set as verified. */
|
|
1334
|
+
return intrinsic.chain(crmfVerify.verifyPopSignature(popo, spki, preimage), function (ok) {
|
|
1314
1335
|
return guard.verdict.of(base, {
|
|
1315
1336
|
valid: ok === true, verified: ok === true, method: "signature", cryptographicallyVerified: ok === true,
|
|
1316
1337
|
subject: bound ? base.subject : null,
|
|
@@ -1368,9 +1389,17 @@ function _verifyOne(msg) {
|
|
|
1368
1389
|
function verifyPop(messages) { return guard.async.deferred(function () { return _verifyPop(messages); }); }
|
|
1369
1390
|
function _verifyPop(messages) {
|
|
1370
1391
|
var parsed = _coerceMessages(messages);
|
|
1371
|
-
|
|
1372
|
-
|
|
1373
|
-
|
|
1392
|
+
/** @internal The aggregate, the projection into it and the universal test over its results all come
|
|
1393
|
+
* from the captures. This IS the proof-of-possession verdict for a set of requests: the aggregate's
|
|
1394
|
+
* static form reads `resolve` off the constructor at each call, so a replacement answers for every
|
|
1395
|
+
* message without one being verified, and the test below is what requires all of them to have
|
|
1396
|
+
* verified. */
|
|
1397
|
+
return intrinsic.chain(intrinsic.allOf(intrinsic.mapList(parsed.messages, _verifyOne)), function (out) {
|
|
1398
|
+
var allVerified = out.length > 0 && intrinsic.everyOwn(out, function (m) { return m && m.verified === true; });
|
|
1399
|
+
/** @internal Copied before it is handed back. The aggregate's own list carries no prototype, so
|
|
1400
|
+
* that a `then` installed on `Array.prototype` cannot settle the aggregate with something else;
|
|
1401
|
+
* a caller reading `result.messages` expects an ordinary array it can iterate and map. */
|
|
1402
|
+
return guard.verdict.of({ valid: allVerified, verified: allVerified, messages: intrinsic.copyList(out) });
|
|
1374
1403
|
});
|
|
1375
1404
|
}
|
|
1376
1405
|
|
package/lib/crmf-verify.js
CHANGED
|
@@ -12,4 +12,4 @@ function verifyPopSignature(popo, spkiBytes, preimage) {
|
|
|
12
12
|
return _seam.verify(popo.algorithmIdentifier, popo.signature, spkiBytes, preimage);
|
|
13
13
|
}
|
|
14
14
|
|
|
15
|
-
module.exports = { setEngine: _seam.setEngine, verifyPopSignature: verifyPopSignature };
|
|
15
|
+
module.exports = Object.freeze({ setEngine: _seam.setEngine, verifyPopSignature: verifyPopSignature });
|
package/lib/csr-verify.js
CHANGED
|
@@ -13,4 +13,4 @@ function verifyCsrSignature(parsed) {
|
|
|
13
13
|
parsed.subjectPublicKeyInfo.bytes, parsed.certificationRequestInfoBytes);
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
module.exports = { setEngine: _seam.setEngine, verifyCsrSignature: verifyCsrSignature };
|
|
16
|
+
module.exports = Object.freeze({ setEngine: _seam.setEngine, verifyCsrSignature: verifyCsrSignature });
|
package/lib/ct.js
CHANGED
|
@@ -2253,7 +2253,7 @@ async function fetchLogList(opts) {
|
|
|
2253
2253
|
});
|
|
2254
2254
|
}
|
|
2255
2255
|
|
|
2256
|
-
module.exports = {
|
|
2256
|
+
module.exports = intrinsic.freeze({
|
|
2257
2257
|
parseSctList: parseSctList,
|
|
2258
2258
|
reconstructSignedData: reconstructSignedData,
|
|
2259
2259
|
verifySct: verifySct,
|
|
@@ -2276,4 +2276,4 @@ module.exports = {
|
|
|
2276
2276
|
addPreChain: addPreChain,
|
|
2277
2277
|
HASH_ALGORITHMS: HASH_ALGORITHMS,
|
|
2278
2278
|
SIGNATURE_ALGORITHMS: SIGNATURE_ALGORITHMS,
|
|
2279
|
-
};
|
|
2279
|
+
});
|
package/lib/edwards-point.js
CHANGED
package/lib/est.js
CHANGED
|
@@ -287,7 +287,7 @@ function _findMultipartMarks(text, boundary) {
|
|
|
287
287
|
if (lsN !== -1) { var r1 = _matchDelimAt(text, lsN, boundary); if (r1) { found = r1; foundAt = p; break; } }
|
|
288
288
|
}
|
|
289
289
|
if (!found) break;
|
|
290
|
-
marks
|
|
290
|
+
guard.list.append(marks, { at: foundAt, bodyStart: found.end, close: found.close });
|
|
291
291
|
searchStart = found.end === foundAt ? found.end + 1 : found.end;
|
|
292
292
|
}
|
|
293
293
|
return marks;
|
|
@@ -328,9 +328,9 @@ function _splitCrlf(s) {
|
|
|
328
328
|
var nlLen = 0;
|
|
329
329
|
if (_charCodeAt(s, i) === 0x0d && i + 1 < n && _charCodeAt(s, i + 1) === 0x0a) nlLen = 2;
|
|
330
330
|
else if (_charCodeAt(s, i) === 0x0a) nlLen = 1;
|
|
331
|
-
if (nlLen > 0) { out
|
|
331
|
+
if (nlLen > 0) { guard.list.append(out, _strSlice(s, last, i)); i += nlLen; last = i; } else i += 1;
|
|
332
332
|
}
|
|
333
|
-
out
|
|
333
|
+
guard.list.append(out, _strSlice(s, last, n));
|
|
334
334
|
return out;
|
|
335
335
|
}
|
|
336
336
|
|
package/lib/guard-async.js
CHANGED
|
@@ -22,6 +22,26 @@ function deferred(body) {
|
|
|
22
22
|
catch (e) { return _reject(_Promise, e); }
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
// @internal
|
|
26
|
+
/** @internal A continuation taken from the capture, for a module that holds the guards rather than
|
|
27
|
+
* the intrinsic captures directly. `p.then(f)` reads `then` off the promise at the call, so a
|
|
28
|
+
* replacement settles the chain without running `f`, and `f` is where a step's result becomes the
|
|
29
|
+
* next step's input. */
|
|
30
|
+
// @enforced-by behavioral -- the RED vectors live with each consumer's own verdict
|
|
31
|
+
function chain(p, onOk, onFail) {
|
|
32
|
+
return _intrinsic.chain(p, onOk, onFail);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// @internal
|
|
36
|
+
/** @internal Run `body` once the work settles, either way, and pass the outcome through unchanged.
|
|
37
|
+
* `Promise.prototype.finally` is not this: it calls the receiver's own `then`, which is the live
|
|
38
|
+
* method, so a replacement there settles the chain with a value of its own AND skips the callback.
|
|
39
|
+
* Cleanup that wipes key material is exactly the callback that must not be skipped. */
|
|
40
|
+
// @enforced-by behavioral -- each consumer's RED vector drives its own cleanup
|
|
41
|
+
function cleanup(p, body) {
|
|
42
|
+
return _intrinsic.chain(p, function (out) { body(); return out; }, function (e) { body(); throw e; });
|
|
43
|
+
}
|
|
44
|
+
|
|
25
45
|
// @internal
|
|
26
46
|
// @enforced-by behavioral -- a RED vector in each client suite refuses a transport yielding no thenable
|
|
27
47
|
function awaited(value, E, code, label) {
|
|
@@ -96,4 +116,5 @@ function bounded(value, ms, E, code, label) {
|
|
|
96
116
|
});
|
|
97
117
|
}
|
|
98
118
|
|
|
99
|
-
module.exports = _intrinsic.freeze({ deferred: deferred, awaited: awaited, invoked: invoked, bounded: bounded
|
|
119
|
+
module.exports = _intrinsic.freeze({ deferred: deferred, awaited: awaited, invoked: invoked, bounded: bounded,
|
|
120
|
+
chain: chain, cleanup: cleanup });
|
package/lib/guard-bytes.js
CHANGED
|
@@ -34,7 +34,6 @@ var _mapForEach = intrinsic.uncurry(Map.prototype.forEach);
|
|
|
34
34
|
var _String = intrinsic.String;
|
|
35
35
|
var _Date = intrinsic.Date;
|
|
36
36
|
var _apply = intrinsic.apply;
|
|
37
|
-
var _promiseFinally = intrinsic.promiseFinally;
|
|
38
37
|
var _ArrayBuffer = intrinsic.ArrayBuffer;
|
|
39
38
|
var _Uint8Array = intrinsic.Uint8Array;
|
|
40
39
|
var _DataView = intrinsic.DataView;
|
|
@@ -559,10 +558,14 @@ function fixArguments(ErrorClass, code, args) {
|
|
|
559
558
|
// @enforced-by behavioral -- an arrangement of two calls has no rename-proof shape to detect. The
|
|
560
559
|
function fixedCall(ErrorClass, code, args, body) {
|
|
561
560
|
var handle = null;
|
|
562
|
-
|
|
561
|
+
/** @internal The release is attached on BOTH outcomes rather than through `finally`, which calls
|
|
562
|
+
* the receiver's own `then` and so reads the live method: a replacement there settles the chain
|
|
563
|
+
* with a value of its own AND skips this callback, so the fixed views stay pinned. */
|
|
564
|
+
var ran = async.deferred(function () {
|
|
563
565
|
handle = fixArguments(ErrorClass, code, args);
|
|
564
566
|
return _apply(body, null, handle.values);
|
|
565
|
-
})
|
|
567
|
+
});
|
|
568
|
+
return async.cleanup(ran, function () { if (handle) handle.release(); });
|
|
566
569
|
}
|
|
567
570
|
|
|
568
571
|
/**
|
package/lib/guard-identifier.js
CHANGED
|
@@ -69,7 +69,7 @@ function assertCanonicalOid(str, E, code, label, boundsCode, countCode) {
|
|
|
69
69
|
}
|
|
70
70
|
if (boundsCode === null) return str;
|
|
71
71
|
var bcode = boundsCode === undefined ? code : boundsCode;
|
|
72
|
-
var parts =
|
|
72
|
+
var parts = intrinsic.splitChar(str, 46);
|
|
73
73
|
if (parts.length - 1 > constants.LIMITS.OID_MAX_SUBIDENTIFIERS) {
|
|
74
74
|
throw E(countCode || bcode, who + " carries more than " + constants.LIMITS.OID_MAX_SUBIDENTIFIERS + " sub-identifiers");
|
|
75
75
|
}
|