@blamejs/pki 0.8.6 → 0.8.9
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 +143 -76
- package/README.md +4 -2
- package/index.js +11 -0
- package/lib/acme.js +15 -78
- package/lib/asn1-der.js +58 -6
- package/lib/cbor-det.js +11 -1
- package/lib/cmc-build.js +1 -1
- package/lib/cmc-verify.js +3 -3
- package/lib/cmp-session.js +1 -1
- package/lib/cms-sign.js +3 -3
- package/lib/cms-verify.js +5 -5
- package/lib/constants.js +11 -0
- package/lib/est.js +1 -1
- package/lib/framework-error.js +8 -0
- package/lib/guard-async.js +53 -2
- package/lib/guard-encoding.js +105 -1
- package/lib/guard-identifier.js +74 -1
- package/lib/guard-intrinsic.js +2 -0
- package/lib/guard-json.js +1 -6
- package/lib/guard-limits.js +40 -1
- package/lib/guard-list.js +25 -0
- package/lib/guard-name.js +134 -22
- package/lib/guard-text.js +33 -1
- package/lib/http-transport.js +39 -7
- package/lib/identity-match.js +561 -0
- package/lib/ip-utils.js +52 -1
- package/lib/key.js +250 -5
- package/lib/ocsp.js +125 -22
- package/lib/oid.js +1 -1
- package/lib/path-validate.js +199 -61
- package/lib/pkcs11-uri.js +646 -0
- package/lib/pkcs12-build.js +6 -1
- package/lib/revocation-fetch.js +772 -0
- package/lib/schema-all.js +124 -0
- package/lib/schema-attrcert.js +4 -2
- package/lib/schema-crmf.js +4 -2
- package/lib/schema-pkcs1.js +335 -0
- package/lib/schema-pkcs8.js +15 -0
- package/lib/schema-pkix.js +322 -40
- package/lib/schema-sec1.js +244 -0
- package/lib/schema-tsp.js +4 -2
- package/lib/schema-x509.js +4 -2
- package/lib/trust.js +2 -2
- package/lib/tsp-sign.js +1 -1
- package/lib/webauthn.js +4 -4
- package/lib/webcrypto.js +17 -5
- package/package.json +1 -1
- package/sbom.cdx.json +6 -6
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
// SPDX-License-Identifier: Apache-2.0
|
|
2
|
+
// Copyright (c) blamejs contributors
|
|
3
|
+
"use strict";
|
|
4
|
+
/**
|
|
5
|
+
* @module pki.schema.sec1
|
|
6
|
+
* @nav Schema
|
|
7
|
+
* @title SEC1
|
|
8
|
+
* @fullname SEC1 EC private keys, the EC PRIVATE KEY encoding
|
|
9
|
+
* @order 146
|
|
10
|
+
* @slug sec1
|
|
11
|
+
*
|
|
12
|
+
* @intro
|
|
13
|
+
* The elliptic-curve private-key encoding of RFC 5915: `ECPrivateKey`, the
|
|
14
|
+
* `EC PRIVATE KEY` PEM block OpenSSL writes and appliances still emit. `parse`
|
|
15
|
+
* reads one into its version, scalar, curve and stored public point, and
|
|
16
|
+
* `encode` writes it back.
|
|
17
|
+
*
|
|
18
|
+
* The curve is what fixes the scalar's width, so the parameters field is
|
|
19
|
+
* required here even though the ASN.1 marks it optional: without it there is no
|
|
20
|
+
* width to hold the scalar to, and a scalar of the wrong width is a different
|
|
21
|
+
* key. RFC 5915 sec. 3 states the scalar as `ceiling(log2(n)/8)` octets with its
|
|
22
|
+
* leading zeros intact, so a short one is refused and never padded into place.
|
|
23
|
+
*
|
|
24
|
+
* The parameters field carries a named curve and nothing else. RFC 5480
|
|
25
|
+
* sec. 2.1.1 says a specified curve and an implicit curve MUST NOT appear, and
|
|
26
|
+
* each is refused by name, so the message says which one arrived.
|
|
27
|
+
*
|
|
28
|
+
* The stored public key is surfaced as the bytes it carries. It is the
|
|
29
|
+
* encoding's own copy of the public half, not the key's identity: a verb that
|
|
30
|
+
* needs that half derives it from the scalar, so a stored point that disagrees
|
|
31
|
+
* cannot decide anything.
|
|
32
|
+
*
|
|
33
|
+
* @card
|
|
34
|
+
* Read and write the RFC 5915 `ECPrivateKey`, DER or PEM, with the scalar held
|
|
35
|
+
* to its curve's width and the parameters field held to a named curve.
|
|
36
|
+
*/
|
|
37
|
+
|
|
38
|
+
var asn1 = require("./asn1-der");
|
|
39
|
+
var schema = require("./schema-engine");
|
|
40
|
+
var pkix = require("./schema-pkix");
|
|
41
|
+
var oid = require("./oid");
|
|
42
|
+
var frameworkError = require("./framework-error");
|
|
43
|
+
var intrinsic = require("./guard-intrinsic");
|
|
44
|
+
|
|
45
|
+
var Sec1Error = frameworkError.Sec1Error;
|
|
46
|
+
var PemError = frameworkError.PemError;
|
|
47
|
+
|
|
48
|
+
var NS = pkix.makeNS("sec1", Sec1Error, oid);
|
|
49
|
+
|
|
50
|
+
var LABEL = "EC PRIVATE KEY";
|
|
51
|
+
|
|
52
|
+
/** @internal The scalar width each curve fixes, `ceiling(log2(n)/8)` over the curve's order
|
|
53
|
+
* (RFC 5915 sec. 3). A curve with no row here is one this toolkit cannot hold a scalar to, which
|
|
54
|
+
* is a refusal, since guessing the width would accept a key of the wrong size. */
|
|
55
|
+
var CURVE_SCALAR_BYTES = intrinsic.assign(intrinsic.create(null), {
|
|
56
|
+
"prime256v1": 32,
|
|
57
|
+
"secp384r1": 48,
|
|
58
|
+
"secp521r1": 66,
|
|
59
|
+
"secp256k1": 32,
|
|
60
|
+
"brainpoolP256r1": 32,
|
|
61
|
+
"brainpoolP384r1": 48,
|
|
62
|
+
"brainpoolP512r1": 64,
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
/** @internal RFC 5480 sec. 2.2 writes the point's first octet as the form: 0x04 uncompressed,
|
|
66
|
+
* 0x02 and 0x03 compressed. The hybrid forms 0x06 and 0x07 are named there as MUST NOT, and every
|
|
67
|
+
* other value names no form at all. The width follows from the form and the curve. */
|
|
68
|
+
function _assertPoint(point, scalarBytes) {
|
|
69
|
+
if (point.length === 0) {
|
|
70
|
+
throw NS.E("sec1/bad-public-key", "the stored public key is empty (RFC 5480 sec. 2.2)");
|
|
71
|
+
}
|
|
72
|
+
var form = point[0];
|
|
73
|
+
if (form === 0x06 || form === 0x07) {
|
|
74
|
+
throw NS.E("sec1/bad-public-key", "the hybrid point forms 0x06 and 0x07 are refused (RFC 5480 sec. 2.2)");
|
|
75
|
+
}
|
|
76
|
+
if (form === 0x04) {
|
|
77
|
+
if (point.length !== 1 + 2 * scalarBytes) {
|
|
78
|
+
throw NS.E("sec1/bad-public-key", "an uncompressed point is 1 + 2 * " + scalarBytes + " octets on this curve, got " + point.length);
|
|
79
|
+
}
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
if (form === 0x02 || form === 0x03) {
|
|
83
|
+
if (point.length !== 1 + scalarBytes) {
|
|
84
|
+
throw NS.E("sec1/bad-public-key", "a compressed point is 1 + " + scalarBytes + " octets on this curve, got " + point.length);
|
|
85
|
+
}
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
throw NS.E("sec1/bad-public-key", "the stored public key's first octet names no point form (RFC 5480 sec. 2.2)");
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
var EC_PRIVATE_KEY = schema.seq([
|
|
92
|
+
schema.field("version", schema.integerLeaf()),
|
|
93
|
+
schema.field("privateKey", schema.octetString()),
|
|
94
|
+
/** @internal RFC 5915's module is DEFINITIONS EXPLICIT TAGS, so `[0]` and `[1]` wrap their
|
|
95
|
+
* values, and do not replace their tags. */
|
|
96
|
+
/** @internal Read as ANY so the two shapes RFC 5480 sec. 2.1.1 names as MUST NOT, a SEQUENCE
|
|
97
|
+
* (specifiedCurve) and a NULL (implicitCurve), each get a verdict naming it. The OID reader
|
|
98
|
+
* would answer both with "expected tag 6", which says nothing about which one arrived. */
|
|
99
|
+
schema.optional("parameters", schema.any(), { tag: 0, explicit: true }),
|
|
100
|
+
schema.optional("publicKey", schema.bitString(), { tag: 1, explicit: true }),
|
|
101
|
+
], {
|
|
102
|
+
assert: "sequence", arity: { min: 2, max: 4 }, code: "sec1/not-an-ec-private-key", what: "ECPrivateKey",
|
|
103
|
+
build: function (m) {
|
|
104
|
+
var version = m.fields.version.value;
|
|
105
|
+
/** @internal RFC 5915 sec. 3 fixes the version at 1. A PKCS#8 PrivateKeyInfo opens with a
|
|
106
|
+
* version 0 INTEGER and an OCTET STRING too, so this is also what keeps one from reading as
|
|
107
|
+
* the other. */
|
|
108
|
+
if (version !== 1n) {
|
|
109
|
+
throw NS.E("sec1/bad-version", "an ECPrivateKey is version 1 (RFC 5915 sec. 3), got " + version);
|
|
110
|
+
}
|
|
111
|
+
if (!m.fields.parameters.present) {
|
|
112
|
+
throw NS.E("sec1/missing-curve", "an ECPrivateKey read on its own carries its [0] parameters, since the curve is what fixes the scalar's width (RFC 5915 sec. 3)");
|
|
113
|
+
}
|
|
114
|
+
var paramNode = m.fields.parameters.value;
|
|
115
|
+
if (paramNode.tagClass !== "universal" || paramNode.tagNumber !== asn1.TAGS.OBJECT_IDENTIFIER) {
|
|
116
|
+
throw NS.E("sec1/bad-curve", paramNode.tagClass === "universal" && paramNode.tagNumber === asn1.TAGS.SEQUENCE
|
|
117
|
+
? "the parameters field carries a specified curve, which RFC 5480 sec. 2.1.1 refuses; name the curve instead"
|
|
118
|
+
: (paramNode.tagClass === "universal" && paramNode.tagNumber === asn1.TAGS.NULL
|
|
119
|
+
? "the parameters field carries an implicit curve, which RFC 5480 sec. 2.1.1 refuses; name the curve instead"
|
|
120
|
+
: "the parameters field carries a named curve OBJECT IDENTIFIER and nothing else (RFC 5480 sec. 2.1.1)"));
|
|
121
|
+
}
|
|
122
|
+
var curveOid = asn1.read.oid(paramNode);
|
|
123
|
+
var curve = oid.name(curveOid);
|
|
124
|
+
var scalarBytes = curve === undefined ? undefined : CURVE_SCALAR_BYTES[curve];
|
|
125
|
+
if (scalarBytes === undefined) {
|
|
126
|
+
throw NS.E("sec1/unsupported-curve", "this toolkit holds no scalar width for the curve " + curveOid +
|
|
127
|
+
(curve === undefined ? "" : " (" + curve + ")"));
|
|
128
|
+
}
|
|
129
|
+
var scalar = m.fields.privateKey.value;
|
|
130
|
+
if (scalar.length !== scalarBytes) {
|
|
131
|
+
throw NS.E("sec1/bad-private-key", "the private key is " + scalarBytes + " octets on " + curve +
|
|
132
|
+
", with its leading zeros (RFC 5915 sec. 3), got " + scalar.length);
|
|
133
|
+
}
|
|
134
|
+
var out = { version: intrinsic.Number(version), privateKey: scalar, curve: curve, curveOid: curveOid };
|
|
135
|
+
if (m.fields.publicKey.present) {
|
|
136
|
+
var bits = m.fields.publicKey.value;
|
|
137
|
+
if (bits.unusedBits !== 0) {
|
|
138
|
+
throw NS.E("sec1/bad-public-key", "the stored public key's BIT STRING holds whole octets");
|
|
139
|
+
}
|
|
140
|
+
_assertPoint(bits.bytes, scalarBytes);
|
|
141
|
+
out.publicKey = bits.bytes;
|
|
142
|
+
}
|
|
143
|
+
return out;
|
|
144
|
+
},
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
var PARSE_OPTS = intrinsic.assign(intrinsic.create(null), {
|
|
148
|
+
pemLabel: LABEL, PemError: PemError, ErrorClass: Sec1Error, prefix: "sec1",
|
|
149
|
+
what: "EC private key", topSchema: EC_PRIVATE_KEY, ns: NS,
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* @primitive pki.schema.sec1.parse
|
|
154
|
+
* @signature pki.schema.sec1.parse(input, opts) -> key
|
|
155
|
+
* @since 0.8.8
|
|
156
|
+
* @status stable
|
|
157
|
+
* @spec RFC 5915
|
|
158
|
+
* @related pki.schema.sec1.encode, pki.schema.pkcs8.parse
|
|
159
|
+
*
|
|
160
|
+
* Read an RFC 5915 `ECPrivateKey`, as DER bytes or an `EC PRIVATE KEY` PEM block,
|
|
161
|
+
* into `{ version, privateKey, curve, curveOid, publicKey }`. The scalar and the
|
|
162
|
+
* stored point are `Buffer`s, and `curve` is the registry name of the named curve
|
|
163
|
+
* the key carries.
|
|
164
|
+
*
|
|
165
|
+
* The parameters field is required, because the curve is what fixes the scalar's
|
|
166
|
+
* width and a scalar of the wrong width is a different key. It carries a named
|
|
167
|
+
* curve and nothing else: a specified curve and an implicit curve are both refused
|
|
168
|
+
* with `sec1/bad-curve`, which RFC 5480 sec. 2.1.1 states as a MUST NOT.
|
|
169
|
+
*
|
|
170
|
+
* The stored public key is the encoding's own copy of the public half, not the key's
|
|
171
|
+
* identity. A verb that needs that half derives it from the scalar.
|
|
172
|
+
*
|
|
173
|
+
* @example
|
|
174
|
+
* // requires: der -- an ECPrivateKey, from `openssl ecparam -genkey` or an appliance
|
|
175
|
+
* var key = pki.schema.sec1.parse(der);
|
|
176
|
+
* key.version; // 1
|
|
177
|
+
* key.curve; // "prime256v1"
|
|
178
|
+
*/
|
|
179
|
+
var parse = pkix.makeParser(PARSE_OPTS);
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* @primitive pki.schema.sec1.encode
|
|
183
|
+
* @signature pki.schema.sec1.encode(key) -> Buffer
|
|
184
|
+
* @since 0.8.8
|
|
185
|
+
* @status stable
|
|
186
|
+
* @spec RFC 5915
|
|
187
|
+
* @related pki.schema.sec1.parse
|
|
188
|
+
*
|
|
189
|
+
* Write an `ECPrivateKey` back to DER from the shape `parse` returns, with the
|
|
190
|
+
* parameters field always present, which RFC 5915 sec. 3 asks of a generator. A key
|
|
191
|
+
* read and written again produces the bytes it came from.
|
|
192
|
+
*
|
|
193
|
+
* @example
|
|
194
|
+
* // requires: der -- an ECPrivateKey, from `openssl ecparam -genkey` or an appliance
|
|
195
|
+
* pki.schema.sec1.encode(pki.schema.sec1.parse(der)).equals(der); // true
|
|
196
|
+
*/
|
|
197
|
+
function encode(key) {
|
|
198
|
+
if (key === null || typeof key !== "object") {
|
|
199
|
+
throw NS.E("sec1/bad-input", "encode takes the object parse returns");
|
|
200
|
+
}
|
|
201
|
+
var curveOid = key.curveOid;
|
|
202
|
+
if (typeof curveOid !== "string") {
|
|
203
|
+
var named = typeof key.curve === "string" ? oid.byName(key.curve) : undefined;
|
|
204
|
+
if (typeof named !== "string") {
|
|
205
|
+
throw NS.E("sec1/bad-input", "encode needs the key's named curve, as curveOid or a registered curve name");
|
|
206
|
+
}
|
|
207
|
+
curveOid = named;
|
|
208
|
+
}
|
|
209
|
+
var kids = [asn1.build.integer(intrinsic.BigInt(key.version === undefined ? 1 : key.version)),
|
|
210
|
+
asn1.build.octetString(key.privateKey),
|
|
211
|
+
asn1.build.explicit(0, asn1.build.oid(curveOid))];
|
|
212
|
+
if (key.publicKey !== undefined && key.publicKey !== null) {
|
|
213
|
+
kids[3] = asn1.build.explicit(1, asn1.build.bitString(key.publicKey, 0));
|
|
214
|
+
}
|
|
215
|
+
return asn1.build.sequence(kids);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function pemDecode(text) { return pkix.pemDecode(text, LABEL, PemError); }
|
|
219
|
+
function pemEncode(der) { return pkix.pemEncode(der, LABEL, PemError); }
|
|
220
|
+
|
|
221
|
+
/** @internal RFC 5915 sec. 3: `ECPrivateKey ::= SEQUENCE { version INTEGER, privateKey OCTET
|
|
222
|
+
* STRING, parameters [0] ECParameters OPTIONAL, publicKey [1] BIT STRING OPTIONAL }`. Structure
|
|
223
|
+
* alone does not separate this from every other SEQUENCE opening that way, which is why nothing
|
|
224
|
+
* routes to it from bare bytes; it answers for a caller that already has the armor label. */
|
|
225
|
+
function matches(root) {
|
|
226
|
+
var k = pkix.rootSequenceChildren(root, 2, 4);
|
|
227
|
+
if (!k) return false;
|
|
228
|
+
if (!schema.isUniversal(k[0], asn1.TAGS.INTEGER)) return false;
|
|
229
|
+
if (!schema.isUniversal(k[1], asn1.TAGS.OCTET_STRING)) return false;
|
|
230
|
+
var last = -1;
|
|
231
|
+
for (var i = 2; i < k.length; i++) {
|
|
232
|
+
if (!schema.isContextInRange(k[i], 0, 1) || k[i].tagNumber <= last) return false;
|
|
233
|
+
last = k[i].tagNumber;
|
|
234
|
+
}
|
|
235
|
+
return true;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
module.exports = {
|
|
239
|
+
parse: parse,
|
|
240
|
+
matches: matches,
|
|
241
|
+
encode: encode,
|
|
242
|
+
pemDecode: pemDecode,
|
|
243
|
+
pemEncode: pemEncode,
|
|
244
|
+
};
|
package/lib/schema-tsp.js
CHANGED
|
@@ -455,8 +455,10 @@ function parseToken(input, callerOpts) {
|
|
|
455
455
|
* @related pki.schema.tsp.parse
|
|
456
456
|
*
|
|
457
457
|
* Extract the DER bytes from a PEM block (RFC 3161 defines no standard label, so the
|
|
458
|
-
*
|
|
459
|
-
*
|
|
458
|
+
* a block of any label is accepted unless `label` is given). The text holds one
|
|
459
|
+
* object: a file of several is refused with `pem/multiple-blocks` and read with
|
|
460
|
+
* `pki.schema.pem.decodeBundle`. Throws `PemError` on a missing envelope or a
|
|
461
|
+
* non-base64 body.
|
|
460
462
|
*
|
|
461
463
|
* @example
|
|
462
464
|
* var req = pki.tsp.request({ hashAlgorithm: "sha256", hashedMessage: Buffer.from(await pki.webcrypto.subtle.digest("SHA-256", Buffer.from("hello"))) }, {});
|
package/lib/schema-x509.js
CHANGED
|
@@ -51,8 +51,10 @@ var PemError = frameworkError.PemError;
|
|
|
51
51
|
* Extract the DER bytes from a PEM block (default label `CERTIFICATE`, the
|
|
52
52
|
* RFC 7468 sec. 5 armor, the canonical-label default every sibling format
|
|
53
53
|
* applies). Pass a `label` to enforce a different block type, or an explicit
|
|
54
|
-
* `null` to
|
|
55
|
-
*
|
|
54
|
+
* `null` to accept a block of any type. The text holds one object: a file of
|
|
55
|
+
* several is refused with `pem/multiple-blocks` and read with
|
|
56
|
+
* `pki.schema.pem.decodeBundle`. Throws `PemError` on a missing / mismatched
|
|
57
|
+
* envelope or a non-base64 body.
|
|
56
58
|
*
|
|
57
59
|
* @example
|
|
58
60
|
* var pair = await pki.key.generate("Ed25519");
|
package/lib/trust.js
CHANGED
|
@@ -383,8 +383,8 @@ function _copyDistrustAfter(src) {
|
|
|
383
383
|
function _copyName(name) {
|
|
384
384
|
if (!name || !Array.isArray(name.rdns)) return name;
|
|
385
385
|
var out = Object.assign({}, name);
|
|
386
|
-
out.rdns = name.rdns
|
|
387
|
-
return Array.isArray(rdn) ?
|
|
386
|
+
out.rdns = guard.list.copyMap(name.rdns, function (rdn) {
|
|
387
|
+
return Array.isArray(rdn) ? guard.list.copyMap(rdn, function (atv) { return Object.assign({}, atv); }) : rdn;
|
|
388
388
|
});
|
|
389
389
|
out.bytes = Buffer.isBuffer(name.bytes) ? Buffer.from(name.bytes) : name.bytes;
|
|
390
390
|
return out;
|
package/lib/tsp-sign.js
CHANGED
|
@@ -76,7 +76,7 @@ function _certDer(c) {
|
|
|
76
76
|
c = buf.toString("latin1");
|
|
77
77
|
}
|
|
78
78
|
if (typeof c !== "string") throw _err("tsp/bad-input", "the TSA certificate must be a DER BufferSource or a PEM string");
|
|
79
|
-
var der = pkix.pemDecodeLenient(c, "CERTIFICATE");
|
|
79
|
+
var der = pkix.pemDecodeLenient(c, "CERTIFICATE", _err, "tsp/bad-input");
|
|
80
80
|
if (der === null) throw _err("tsp/bad-input", "the TSA certificate PEM is not a CERTIFICATE block");
|
|
81
81
|
return der;
|
|
82
82
|
}
|
package/lib/webauthn.js
CHANGED
|
@@ -350,7 +350,7 @@ var _FORMAT_SCOPED_BOOLEAN_OPTS = ["verifySafetyNetJws", "requireCtsProfileMatch
|
|
|
350
350
|
function _cloneParsed(v, depth) {
|
|
351
351
|
if (depth > 64) throw _err("webauthn/bad-input", "opts.rootCertificates[] is nested too deeply to be a parsed certificate");
|
|
352
352
|
if (guard.bytes.isByteSource(v)) return guard.bytes.snapshotSource(v, _err, "webauthn/bad-input", "a byte field of opts.rootCertificates[]");
|
|
353
|
-
if (Array.isArray(v)) return
|
|
353
|
+
if (Array.isArray(v)) return guard.list.copyMap(v, function (x) { return _cloneParsed(x, depth + 1); });
|
|
354
354
|
if (guard.time.isDate(v)) return new Date(guard.time.instantOf(v));
|
|
355
355
|
if (v && typeof v === "object") {
|
|
356
356
|
var out = intrinsic.create(null);
|
|
@@ -1497,9 +1497,9 @@ function _snapshotAssertion(input) {
|
|
|
1497
1497
|
}
|
|
1498
1498
|
out.credentialPublicKey = key;
|
|
1499
1499
|
}
|
|
1500
|
-
if (Array.isArray(out.allowedAlgorithms)) out.allowedAlgorithms = out.allowedAlgorithms
|
|
1501
|
-
if (Array.isArray(out.expectedOrigin)) out.expectedOrigin = out.expectedOrigin
|
|
1502
|
-
if (Array.isArray(out.expectedTopOrigin)) out.expectedTopOrigin = out.expectedTopOrigin
|
|
1500
|
+
if (Array.isArray(out.allowedAlgorithms)) out.allowedAlgorithms = guard.list.snapshot(out.allowedAlgorithms);
|
|
1501
|
+
if (Array.isArray(out.expectedOrigin)) out.expectedOrigin = guard.list.snapshot(out.expectedOrigin);
|
|
1502
|
+
if (Array.isArray(out.expectedTopOrigin)) out.expectedTopOrigin = guard.list.snapshot(out.expectedTopOrigin);
|
|
1503
1503
|
return out;
|
|
1504
1504
|
}
|
|
1505
1505
|
|
package/lib/webcrypto.js
CHANGED
|
@@ -1148,13 +1148,24 @@ function isCryptoKeyLike(x) {
|
|
|
1148
1148
|
}
|
|
1149
1149
|
|
|
1150
1150
|
// @internal
|
|
1151
|
-
|
|
1152
|
-
|
|
1151
|
+
/** @internal `want` names the WebCrypto export format, defaulting to the DER one the key's type
|
|
1152
|
+
* calls for. A key from another implementation can be reached three ways, and which of them works
|
|
1153
|
+
* is a property of the key rather than of the format asked for, so every format is exported
|
|
1154
|
+
* through the same three; a format that went straight to this engine's `exportKey` would refuse a
|
|
1155
|
+
* key this engine did not make while the others returned it. A JWK is an object rather than
|
|
1156
|
+
* bytes, so only the byte formats are wrapped. */
|
|
1157
|
+
function exportAnyKey(key, E, code, want) {
|
|
1158
|
+
var format = want || _EXPORT_FORMAT[key && key.type];
|
|
1153
1159
|
if (!format) throw E(code, "a CryptoKey with a private, public, or secret type is required");
|
|
1160
|
+
if (want === "jwk" && !_EXPORT_FORMAT[key && key.type]) {
|
|
1161
|
+
throw E(code, "a CryptoKey with a private, public, or secret type is required");
|
|
1162
|
+
}
|
|
1163
|
+
var asJwk = format === "jwk";
|
|
1164
|
+
function wrap(b) { return asJwk ? b : _bufferFrom(b); }
|
|
1154
1165
|
if (key instanceof CryptoKey) {
|
|
1155
1166
|
return _resolve(Promise)
|
|
1156
1167
|
.then(function () { return _crypto.subtle.exportKey(format, key); })
|
|
1157
|
-
.then(
|
|
1168
|
+
.then(wrap);
|
|
1158
1169
|
}
|
|
1159
1170
|
if (!key.extractable) {
|
|
1160
1171
|
throw E(code, "the CryptoKey comes from a different WebCrypto implementation and is not extractable, so its key material cannot be reached; import it through pki.webcrypto.subtle, or pass the key as DER");
|
|
@@ -1162,14 +1173,15 @@ function exportAnyKey(key, E, code) {
|
|
|
1162
1173
|
var handle = key._handle;
|
|
1163
1174
|
if (handle instanceof nodeCrypto.KeyObject && handle.type === key.type) {
|
|
1164
1175
|
return _resolve(Promise).then(function () {
|
|
1176
|
+
if (asJwk) return handle.export({ format: "jwk" });
|
|
1165
1177
|
return format === "raw" ? handle.export() : handle.export({ format: "der", type: format });
|
|
1166
|
-
}).then(
|
|
1178
|
+
}).then(wrap, function (e) {
|
|
1167
1179
|
throw E(code, "the CryptoKey comes from a different copy of this WebCrypto engine and its key material could not be read; import it through pki.webcrypto.subtle, or pass the key as DER", e);
|
|
1168
1180
|
});
|
|
1169
1181
|
}
|
|
1170
1182
|
return _resolve(Promise)
|
|
1171
1183
|
.then(function () { return nodeCrypto.webcrypto.subtle.exportKey(format, key); })
|
|
1172
|
-
.then(
|
|
1184
|
+
.then(wrap, function (e) {
|
|
1173
1185
|
throw E(code, "the CryptoKey comes from a different WebCrypto implementation and could not be exported for re-import; import it through pki.webcrypto.subtle, or pass the key as DER", e);
|
|
1174
1186
|
});
|
|
1175
1187
|
}
|
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:1d0c3725-eae5-4743-8430-5684e3e52ec7",
|
|
6
6
|
"version": 1,
|
|
7
7
|
"metadata": {
|
|
8
|
-
"timestamp": "2026-09-
|
|
8
|
+
"timestamp": "2026-09-23T19:11:33.586Z",
|
|
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.8.
|
|
22
|
+
"bom-ref": "@blamejs/pki@0.8.9",
|
|
23
23
|
"type": "application",
|
|
24
24
|
"name": "pki",
|
|
25
|
-
"version": "0.8.
|
|
25
|
+
"version": "0.8.9",
|
|
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.8.
|
|
29
|
+
"purl": "pkg:npm/%40blamejs/pki@0.8.9",
|
|
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.8.
|
|
57
|
+
"ref": "@blamejs/pki@0.8.9",
|
|
58
58
|
"dependsOn": []
|
|
59
59
|
}
|
|
60
60
|
]
|