@blamejs/pki 0.5.7 → 0.5.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 +418 -386
- package/MIGRATING.md +43 -0
- package/README.md +12 -12
- package/lib/acme.js +31 -31
- package/lib/asn1-der.js +10 -10
- package/lib/attrcert-sign.js +19 -19
- package/lib/byte-reader.js +6 -6
- package/lib/byte-writer.js +5 -5
- package/lib/cbor-det.js +27 -24
- package/lib/cmc-build.js +97 -92
- package/lib/cmc-verify.js +106 -30
- package/lib/cmp-build.js +25 -25
- package/lib/cmp-session.js +70 -70
- package/lib/cmp-verify.js +71 -57
- package/lib/cms-compress.js +7 -7
- package/lib/cms-decrypt.js +90 -72
- package/lib/cms-encrypt.js +32 -32
- package/lib/cms-sign.js +74 -55
- package/lib/cms-verify.js +97 -75
- package/lib/composite-sig.js +13 -13
- package/lib/constants.js +4 -4
- package/lib/crl-sign.js +22 -22
- package/lib/crl-verify.js +7 -6
- package/lib/crmf-sign.js +14 -14
- package/lib/csr-sign.js +8 -8
- package/lib/ct.js +37 -37
- package/lib/edwards-point.js +7 -7
- package/lib/est.js +98 -55
- package/lib/framework-error.js +5 -5
- package/lib/guard-all.js +5 -3
- package/lib/guard-async.js +4 -4
- package/lib/guard-bytes.js +79 -79
- package/lib/guard-compress.js +17 -17
- package/lib/guard-crypto.js +1 -1
- package/lib/guard-der.js +152 -0
- package/lib/guard-encoding.js +15 -15
- package/lib/guard-header.js +3 -3
- package/lib/guard-identifier.js +16 -16
- package/lib/guard-json.js +15 -15
- package/lib/guard-limits.js +7 -7
- package/lib/guard-name.js +81 -16
- package/lib/guard-parsed.js +80 -80
- package/lib/guard-range.js +19 -19
- package/lib/guard-secret.js +11 -10
- package/lib/guard-text.js +6 -6
- package/lib/guard-time.js +10 -10
- package/lib/hpke.js +18 -17
- package/lib/http-digest.js +35 -35
- package/lib/http-retry-after.js +13 -13
- package/lib/http-transport.js +20 -19
- package/lib/inspect.js +53 -53
- package/lib/ip-utils.js +2 -2
- package/lib/jose.js +13 -13
- package/lib/key.js +16 -16
- package/lib/lint.js +51 -51
- package/lib/merkle.js +51 -36
- package/lib/mime.js +18 -18
- package/lib/ocsp-verify.js +10 -10
- package/lib/ocsp.js +13 -13
- package/lib/oid.js +29 -29
- package/lib/path-validate.js +114 -113
- package/lib/pbes2.js +16 -16
- package/lib/pkcs12-build.js +53 -53
- package/lib/pki-build.js +48 -20
- package/lib/rc2.js +1 -1
- package/lib/rfc3339.js +5 -5
- package/lib/schema-all.js +31 -31
- package/lib/schema-attrcert.js +12 -12
- package/lib/schema-c509.js +149 -197
- package/lib/schema-cmc.js +58 -58
- package/lib/schema-cmp.js +43 -43
- package/lib/schema-cms.js +45 -45
- package/lib/schema-crl.js +7 -7
- package/lib/schema-crmf.js +28 -28
- package/lib/schema-csr.js +12 -12
- package/lib/schema-csrattrs.js +16 -16
- package/lib/schema-engine.js +18 -18
- package/lib/schema-ocsp.js +15 -15
- package/lib/schema-pkcs12.js +20 -20
- package/lib/schema-pkcs8.js +2 -2
- package/lib/schema-pkix.js +131 -126
- package/lib/schema-smime.js +19 -19
- package/lib/schema-tsp.js +12 -12
- package/lib/schema-x509.js +3 -3
- package/lib/shbs.js +18 -18
- package/lib/sign-scheme.js +13 -13
- package/lib/sigstore.js +10 -11
- package/lib/sleep.js +1 -1
- package/lib/smime.js +308 -96
- package/lib/tls-cert-compress.js +18 -18
- package/lib/trust.js +27 -27
- package/lib/tsp-sign.js +17 -17
- package/lib/validator-all.js +1 -1
- package/lib/validator-attcert.js +1 -1
- package/lib/validator-cose.js +43 -44
- package/lib/validator-keydesc.js +3 -3
- package/lib/validator-sig.js +13 -13
- package/lib/validator-tls.js +11 -11
- package/lib/validator-tpm.js +20 -19
- package/lib/webauthn-mds.js +66 -66
- package/lib/webauthn.js +33 -33
- package/lib/webcrypto.js +15 -15
- package/lib/x509-sign.js +13 -13
- package/package.json +3 -2
- package/sbom.cdx.json +6 -6
package/lib/schema-csrattrs.js
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* The EST CSR Attributes wire format per RFC 8951 sec. 3.5 (the RFC 7030
|
|
13
13
|
* sec. 4.5.2 ASN.1 was syntactically broken, erratum 4384) with the RFC 9908
|
|
14
14
|
* template structures. `parse` turns a DER `Buffer` into
|
|
15
|
-
* `{ items }
|
|
15
|
+
* `{ items }`, where `CsrAttrs ::= SEQUENCE SIZE (0..MAX) OF AttrOrOID` and
|
|
16
16
|
* `AttrOrOID ::= CHOICE { oid OBJECT IDENTIFIER, attribute Attribute }`
|
|
17
17
|
* disambiguates on the universal tag. An empty SEQUENCE is a COMPLETE valid
|
|
18
18
|
* document ("no additional information desired"). Each item surfaces its
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
* attributes carrying at most one `id-aa-extensionReqTemplate` and never both
|
|
32
32
|
* extension-request kinds. Template PRIORITY (a client that understands the
|
|
33
33
|
* template ignores the legacy elements, RFC 9908 sec. 4) is a `pki.est` builder
|
|
34
|
-
* rule, not a parse rejection
|
|
34
|
+
* rule, not a parse rejection: parse surfaces everything.
|
|
35
35
|
*
|
|
36
36
|
* There is NO `pemDecode` / `pemEncode`: no RFC 7468 label exists for
|
|
37
37
|
* CsrAttrs; the wire encoding is bare RFC 4648 base64 handled by the EST
|
|
@@ -55,9 +55,9 @@ var NS = pkix.makeNS("csrattrs", CsrattrsError, oid);
|
|
|
55
55
|
var T = asn1.TAGS;
|
|
56
56
|
|
|
57
57
|
// The base Attribute is SET SIZE(1..MAX); ATTRIBUTE_KEYTYPE lowers the floor to 0
|
|
58
|
-
//
|
|
59
|
-
// means "any key of this type" (RFC 9908 sec. 3.2). Every other attribute
|
|
60
|
-
// every template inner attribute
|
|
58
|
+
// only for the ecPublicKey / rsaEncryption key-type hints, whose empty values SET
|
|
59
|
+
// means "any key of this type" (RFC 9908 sec. 3.2). Every other attribute, and
|
|
60
|
+
// every template inner attribute, keeps the non-empty floor, so an empty
|
|
61
61
|
// challengePassword or unknown attribute still fails closed.
|
|
62
62
|
// ATTRIBUTE keeps the base SET SIZE(1..MAX); ATTRIBUTE_OPTIONAL_VALUES lowers the
|
|
63
63
|
// floor to 0. Only the recognized NON-KEY attributes that require a value
|
|
@@ -109,7 +109,7 @@ var TEMPLATE_VERSION = schema.decode(function (n, ctx) {
|
|
|
109
109
|
return 0;
|
|
110
110
|
}, function () { return asn1.build.integer(0n); });
|
|
111
111
|
|
|
112
|
-
// SingleAttributeTemplate ::= SEQUENCE { type OID, value ANY OPTIONAL }
|
|
112
|
+
// SingleAttributeTemplate ::= SEQUENCE { type OID, value ANY OPTIONAL }, where a
|
|
113
113
|
// value-absent element means "the client fills this in" (RFC 9908 sec. 3.4). The
|
|
114
114
|
// trailing OPTIONAL ANY is the algorithmIdentifier-parameters shape.
|
|
115
115
|
var SINGLE_ATTR_TEMPLATE = schema.seq([
|
|
@@ -136,14 +136,14 @@ var NAME_TEMPLATE = schema.seqOf(RDN_TEMPLATE, {
|
|
|
136
136
|
});
|
|
137
137
|
|
|
138
138
|
// SubjectPublicKeyInfoTemplate ::= SEQUENCE { algorithm AlgorithmIdentifier,
|
|
139
|
-
// subjectPublicKey BIT STRING OPTIONAL }
|
|
140
|
-
// as an RSA modulus-size placeholder), so pkix.spki (key required, arity 2)
|
|
139
|
+
// subjectPublicKey BIT STRING OPTIONAL }, where the key is OPTIONAL (present
|
|
140
|
+
// only as an RSA modulus-size placeholder), so pkix.spki (key required, arity 2)
|
|
141
141
|
// cannot be reused.
|
|
142
142
|
var SPKI_TEMPLATE = schema.seq([
|
|
143
143
|
schema.field("algorithm", ALGORITHM_IDENTIFIER),
|
|
144
144
|
schema.optional("placeholderKey", schema.bitString(), { whenUniversal: [T.BIT_STRING] }),
|
|
145
145
|
], {
|
|
146
|
-
// subjectPKInfo is [0] IMPLICIT (RFC 9908 sec. 3.4)
|
|
146
|
+
// subjectPKInfo is [0] IMPLICIT (RFC 9908 sec. 3.4), so the context tag replaces
|
|
147
147
|
// the universal SEQUENCE tag, so the node is context-[0] constructed and its
|
|
148
148
|
// children are read directly (the pwri keyDerivationAlgorithm [0] precedent).
|
|
149
149
|
assert: "implicit", implicitTag: 0, arity: { min: 1, max: 2 }, code: "csrattrs/bad-spki-template", what: "SubjectPublicKeyInfoTemplate",
|
|
@@ -154,7 +154,7 @@ var SPKI_TEMPLATE = schema.seq([
|
|
|
154
154
|
});
|
|
155
155
|
|
|
156
156
|
// ExtensionTemplate ::= SEQUENCE { extnID OID, critical BOOLEAN DEFAULT FALSE,
|
|
157
|
-
// extnValue OCTET STRING OPTIONAL }
|
|
157
|
+
// extnValue OCTET STRING OPTIONAL }, where extnValue absent means "client supplies";
|
|
158
158
|
// an explicit critical FALSE is non-DER (BOOLEAN DEFAULT FALSE). Not reusable
|
|
159
159
|
// from pkix.extension (whose extnValue is required), so the DER-critical rule
|
|
160
160
|
// is applied here directly.
|
|
@@ -245,15 +245,15 @@ function _enrichAttribute(item, ctx) {
|
|
|
245
245
|
item.extensions = schema.walk(EXTENSIONS, asn1.decode(item.values[0]), ctx).result;
|
|
246
246
|
} else if (item.oid === OID_EC_PUBLIC_KEY) {
|
|
247
247
|
// A key-type hint's values SET is empty ("any curve") or a singleton naming
|
|
248
|
-
//
|
|
249
|
-
// closed
|
|
248
|
+
// one curve (RFC 9908 sec. 3.2); a multi-valued SET is ambiguous, so it fails
|
|
249
|
+
// closed instead of letting DER ordering pick the advertised constraint.
|
|
250
250
|
if (item.values.length > 1) throw ctx.E("csrattrs/bad-key-type-attr", "an ecPublicKey attribute values must be empty or a SET of exactly one named-curve OBJECT IDENTIFIER (RFC 9908 sec. 3.2)");
|
|
251
251
|
if (item.values.length === 1) {
|
|
252
252
|
try { item.curve = asn1.read.oid(asn1.decode(item.values[0])); }
|
|
253
253
|
catch (e) { throw ctx.E("csrattrs/bad-key-type-attr", "an ecPublicKey attribute value must be a named-curve OBJECT IDENTIFIER (RFC 9908 sec. 3.2)", e); }
|
|
254
254
|
}
|
|
255
255
|
} else if (item.oid === OID_RSA_ENCRYPTION) {
|
|
256
|
-
// Empty ("any size") or a singleton naming
|
|
256
|
+
// Empty ("any size") or a singleton naming one key size; reject a multi-valued SET.
|
|
257
257
|
if (item.values.length > 1) throw ctx.E("csrattrs/bad-key-type-attr", "an rsaEncryption attribute values must be empty or a SET of exactly one INTEGER key size (RFC 9908 sec. 3.2)");
|
|
258
258
|
if (item.values.length === 1) {
|
|
259
259
|
var sz;
|
|
@@ -292,12 +292,12 @@ var ATTR_OR_OID = schema.decode(function (n, ctx) {
|
|
|
292
292
|
throw ctx.E("csrattrs/bad-attr-or-oid", "each CsrAttrs element must be an OBJECT IDENTIFIER or an Attribute SEQUENCE (RFC 8951 sec. 3.5)");
|
|
293
293
|
}, function (item) {
|
|
294
294
|
// Paired encoder (one structure, both directions): reconstruct from the arm's
|
|
295
|
-
// identifying fields
|
|
295
|
+
// identifying fields plus raw values, since the typed enrichment is decode-only.
|
|
296
296
|
if (item.kind === "oid") return asn1.build.oid(item.oid);
|
|
297
297
|
return asn1.build.sequence([asn1.build.oid(item.oid), asn1.build.set(item.values)]);
|
|
298
298
|
});
|
|
299
299
|
|
|
300
|
-
// CsrAttrs ::= SEQUENCE SIZE (0..MAX) OF AttrOrOID. min:0
|
|
300
|
+
// CsrAttrs ::= SEQUENCE SIZE (0..MAX) OF AttrOrOID. min:0, because an empty SEQUENCE is
|
|
301
301
|
// a complete valid document. The cross-element MUSTs (RFC 9908 sec. 3.2 single
|
|
302
302
|
// id-ExtensionReq; sec. 3.4 single template) are enforced in the build.
|
|
303
303
|
var CSR_ATTRS = schema.seqOf(ATTR_OR_OID, {
|
|
@@ -325,7 +325,7 @@ var CSR_ATTRS = schema.seqOf(ATTR_OR_OID, {
|
|
|
325
325
|
* @related pki.schema.parse, pki.est.buildEnrollAttributes
|
|
326
326
|
*
|
|
327
327
|
* Parse a DER `Buffer` of EST CSR Attributes (`CsrAttrs`, RFC 8951 sec. 3.5) into
|
|
328
|
-
* `{ items }`. Each item is `{ kind, oid, name }
|
|
328
|
+
* `{ items }`. Each item is `{ kind, oid, name }`, with `kind` `"oid"` for a bare
|
|
329
329
|
* OID, `"attribute"` for an `Attribute`, which adds raw `values` plus, for the
|
|
330
330
|
* RFC 9908 meaningful types, `extensions` (id-ExtensionReq), `curve` / `keySize`
|
|
331
331
|
* (EC / RSA key-type conventions), or `template` (the request-info template). An
|
package/lib/schema-engine.js
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
* base the certificate parser (and, later, CRL / CMS) composes.
|
|
22
22
|
*
|
|
23
23
|
* @card
|
|
24
|
-
* Declarative ASN.1 structure schemas
|
|
24
|
+
* Declarative ASN.1 structure schemas plus one walk engine: the shared base the
|
|
25
25
|
* certificate / CRL / CMS parsers compose instead of hand-writing.
|
|
26
26
|
*/
|
|
27
27
|
|
|
@@ -96,7 +96,7 @@ function _assertArity(schema, kids, ctx) {
|
|
|
96
96
|
// the OID / INTEGER / string reads). `decode(fn)` hands the whole node to fn,
|
|
97
97
|
// which owns its try/catch and code mapping. `any()` yields the node itself.
|
|
98
98
|
|
|
99
|
-
// Leaves carry
|
|
99
|
+
// Leaves carry both directions: `read(node) -> value` and `write(value) -> DER TLV`,
|
|
100
100
|
// so a single leaf definition drives decode (walk) and encode (build). A [tag]
|
|
101
101
|
// IMPLICIT leaf's write emits the context-tagged TLV directly, mirroring its read.
|
|
102
102
|
function _implicitIntContent(v) { return asn1.decode(asn1.build.integer(v)).content; }
|
|
@@ -105,19 +105,19 @@ function integerLeaf() { return { kind: "leaf", read: asn1.read.integer, writ
|
|
|
105
105
|
function boolean() { return { kind: "leaf", read: asn1.read.boolean, write: function (v) { return asn1.build.boolean(v); } }; }
|
|
106
106
|
function octetString() { return { kind: "leaf", read: asn1.read.octetString, write: function (v) { return asn1.build.octetString(v); } }; }
|
|
107
107
|
function bitString() { return { kind: "leaf", read: function (n) { var b = asn1.read.bitString(n); return { unusedBits: b.unusedBits, bytes: b.bytes }; }, write: function (v) { return asn1.build.bitString(v.bytes, v.unusedBits); } }; }
|
|
108
|
-
// A [tag] IMPLICIT BIT STRING leaf (context-class primitive)
|
|
108
|
+
// A [tag] IMPLICIT BIT STRING leaf (context-class primitive), the primitive-leaf
|
|
109
109
|
// counterpart to implicitSetOf, for e.g. the PKCS#8 publicKey [1] (RFC 5958 sec. 2).
|
|
110
110
|
function implicitBitString(tag) { return { kind: "leaf", read: function (n) { var b = asn1.read.bitStringImplicit(n, tag); return { unusedBits: b.unusedBits, bytes: b.bytes }; }, write: function (v) { return asn1.build.contextPrimitive(tag, Buffer.concat([Buffer.from([v.unusedBits]), v.bytes])); } }; }
|
|
111
|
-
// A [tag] IMPLICIT OCTET STRING leaf (context-class primitive)
|
|
111
|
+
// A [tag] IMPLICIT OCTET STRING leaf (context-class primitive), the sibling of
|
|
112
112
|
// implicitBitString, for e.g. the CMS SignerIdentifier subjectKeyIdentifier [0]
|
|
113
113
|
// (RFC 5652 sec. 5.3). Yields the raw content bytes.
|
|
114
114
|
function implicitOctetString(tag) { return { kind: "leaf", read: function (n) { return asn1.read.octetStringImplicit(n, tag); }, write: function (v) { return asn1.build.contextPrimitive(tag, v); } }; }
|
|
115
|
-
// A [tag] IMPLICIT NULL leaf (context-class primitive, empty content)
|
|
115
|
+
// A [tag] IMPLICIT NULL leaf (context-class primitive, empty content), the sibling
|
|
116
116
|
// of implicitBitString/implicitOctetString, for e.g. the OCSP CertStatus good [0] /
|
|
117
117
|
// unknown [2] arms (RFC 6960 sec. 4.2.1). Yields null; rejects a constructed or
|
|
118
118
|
// non-empty [tag] node fail-closed.
|
|
119
119
|
function implicitNull(tag) { return { kind: "leaf", read: function (n) { return asn1.read.nullImplicit(n, tag); }, write: function () { return asn1.build.contextPrimitive(tag, Buffer.alloc(0)); } }; }
|
|
120
|
-
// A [tag] IMPLICIT INTEGER leaf (context-class primitive)
|
|
120
|
+
// A [tag] IMPLICIT INTEGER leaf (context-class primitive), the integer sibling of
|
|
121
121
|
// implicitBitString, for the RFC 3161 Accuracy millis [0] / micros [1] fields
|
|
122
122
|
// (context-tagged primitive INTEGERs). Yields a BigInt; a constructed or wrong-tag
|
|
123
123
|
// node fails asn1/* at the codec.
|
|
@@ -152,14 +152,14 @@ function optional(name, schema, opts) {
|
|
|
152
152
|
opts = opts || {};
|
|
153
153
|
// How the optional field is recognized at its position:
|
|
154
154
|
// - default: a context [tag] (the certificate version [0] shape).
|
|
155
|
-
// - tags: a context tag in the set
|
|
155
|
+
// - tags: a context tag in the set, for an OPTIONAL field whose type is
|
|
156
156
|
// itself a CHOICE of several context alternatives, e.g. the CRMF CertReqMsg
|
|
157
157
|
// popo ProofOfPossession ([0]..[3]) sitting before the universal-SEQUENCE
|
|
158
158
|
// regInfo (RFC 4211 sec. 3), where ANY of the CHOICE's tags marks it present.
|
|
159
|
-
// - whenUniversal: the next element iff its
|
|
159
|
+
// - whenUniversal: the next element iff its universal tag is in the set, for
|
|
160
160
|
// the CRL TBSCertList shape (bare INTEGER version, Time nextUpdate,
|
|
161
|
-
// SEQUENCE revokedCertificates), disambiguated by tag
|
|
162
|
-
// - whenAny: the next element whatever its tag
|
|
161
|
+
// SEQUENCE revokedCertificates), disambiguated by tag and not a context [n].
|
|
162
|
+
// - whenAny: the next element whatever its tag, for an OPTIONAL ANY like
|
|
163
163
|
// AlgorithmIdentifier.parameters.
|
|
164
164
|
// The recognizer lets _walkSeq CONSUME the element so a closed sequence can
|
|
165
165
|
// reject whatever is left over (without it, a trailing ANY looks unconsumed).
|
|
@@ -172,7 +172,7 @@ function optional(name, schema, opts) {
|
|
|
172
172
|
: function (n) { return isContext(n, opts.tag); };
|
|
173
173
|
// default/defaultCode: `default` binds the DEFAULT value when the field is
|
|
174
174
|
// absent. `defaultCode` opts the field into the X.690 sec. 11.5 walk-side reject
|
|
175
|
-
// (DER: a component equal to its DEFAULT shall not be included)
|
|
175
|
+
// (DER: a component equal to its DEFAULT shall not be included), so a present
|
|
176
176
|
// value equal to `default` (strict equality; Buffers by bytes) fails with
|
|
177
177
|
// that code, so each format keeps its own reject-code family.
|
|
178
178
|
return { fkind: "optional", name: name, schema: schema, tag: opts.tag, match: match,
|
|
@@ -224,7 +224,7 @@ function setOf(item, opts) {
|
|
|
224
224
|
function setOfUnique(item, keyFn, opts) {
|
|
225
225
|
return setOf(item, Object.assign({ unique: keyFn }, opts || {}));
|
|
226
226
|
}
|
|
227
|
-
// [tag] IMPLICIT SET OF item
|
|
227
|
+
// [tag] IMPLICIT SET OF item: the context tag replaces the universal SET tag,
|
|
228
228
|
// so the node is a context-class constructed [tag] whose direct children are the
|
|
229
229
|
// items (RFC 2986 sec. 4.1 CSR attributes). No inner SET, no EXPLICIT unwrap.
|
|
230
230
|
function implicitSetOf(tag, item, opts) {
|
|
@@ -233,9 +233,9 @@ function implicitSetOf(tag, item, opts) {
|
|
|
233
233
|
min: opts.min, max: opts.max, maxCode: opts.maxCode,
|
|
234
234
|
unique: opts.unique, dupCode: opts.dupCode, build: opts.build };
|
|
235
235
|
}
|
|
236
|
-
// [tag] IMPLICIT SEQUENCE OF item
|
|
236
|
+
// [tag] IMPLICIT SEQUENCE OF item: the context tag replaces the universal SEQUENCE
|
|
237
237
|
// tag, so the node is a context-class constructed [tag] whose direct children are the
|
|
238
|
-
// items. Order-preserving: the SEQUENCE-OF sibling of implicitSetOf
|
|
238
|
+
// items. Order-preserving: the SEQUENCE-OF sibling of implicitSetOf without the SET
|
|
239
239
|
// ascending-DER-order rule (RFC 3161 extensions [1] IMPLICIT Extensions).
|
|
240
240
|
function implicitSeqOf(tag, item, opts) {
|
|
241
241
|
opts = opts || {};
|
|
@@ -262,7 +262,7 @@ function implicitSeqOf(tag, item, opts) {
|
|
|
262
262
|
* supplies the typed-error constructor, the error-code family prefix, and the
|
|
263
263
|
* OID registry a build fn resolves names through.
|
|
264
264
|
*
|
|
265
|
-
* The schema is assembled from the combinators this module exports
|
|
265
|
+
* The schema is assembled from the combinators this module exports: structural
|
|
266
266
|
* (`seq` / `field` / `optional` / `explicit` / `trailing` / `seqOf` / `setOf` /
|
|
267
267
|
* `setOfUnique` / `implicitSeqOf` / `implicitSetOf` / `choice`) and value
|
|
268
268
|
* (`oidLeaf` / `integerLeaf` / `boolean` / `octetString` / `bitString` /
|
|
@@ -473,8 +473,8 @@ function _encFail(message) { throw new Error("schema.encode: " + message); }
|
|
|
473
473
|
* @spec X.690, X.680
|
|
474
474
|
* @related pki.schema.engine.walk
|
|
475
475
|
*
|
|
476
|
-
* Encode a structural value to canonical DER by interpreting the
|
|
477
|
-
* `walk` decodes
|
|
476
|
+
* Encode a structural value to canonical DER by interpreting the same schema
|
|
477
|
+
* `walk` decodes, in the constructor direction. `value` mirrors the schema: a `seq`
|
|
478
478
|
* takes `{ fieldName: value }`, a leaf its natural JS value (an OID string, a
|
|
479
479
|
* BigInt, a `{ unusedBits, bytes }` BIT STRING, a `Date`), a `repeat` an array, a
|
|
480
480
|
* `choice` `{ arm, value }`. EXPLICIT wrappers and IMPLICIT `[tag]` retagging are
|
|
@@ -610,7 +610,7 @@ function _encodeChoice(schema, value, ctx) {
|
|
|
610
610
|
* @opts
|
|
611
611
|
* code: string, // typed code wrapping a codec failure (required)
|
|
612
612
|
* what: string, // human label for the wrapped message
|
|
613
|
-
* ber: boolean, // default false
|
|
613
|
+
* ber: boolean, // default false; BER content region (RFC 7292 sec. 4.1)
|
|
614
614
|
* budget: object, // { remaining: n } shared across a parse's re-decodes
|
|
615
615
|
* budgetCode: string, // typed code when the budget is exhausted
|
|
616
616
|
*
|
package/lib/schema-ocsp.js
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*
|
|
11
11
|
* @intro
|
|
12
12
|
* OCSP request and response handling per RFC 6960 (sec. 4.1 OCSPRequest, sec. 4.2
|
|
13
|
-
* OCSPResponse). Two entry points
|
|
13
|
+
* OCSPResponse). Two entry points, `parseRequest` and `parseResponse`, turn a
|
|
14
14
|
* DER or PEM message into a structured object. A response is a two-stage
|
|
15
15
|
* OID-dispatch: `OCSPResponse` carries an ENUMERATED `responseStatus` and an
|
|
16
16
|
* OPTIONAL `responseBytes`; when the `responseType` is `id-pkix-ocsp-basic` its
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* decoded and walked, so the per-certificate statuses surface structurally.
|
|
19
19
|
*
|
|
20
20
|
* OCSP is a signed protocol: the bytes an external verifier must hash are surfaced
|
|
21
|
-
*
|
|
21
|
+
* raw and never re-serialized. `tbsRequestBytes` and `tbsResponseDataBytes` are the
|
|
22
22
|
* exact on-wire `tbsRequest` / `ResponseData` TLVs; each `CertID` surfaces its
|
|
23
23
|
* `issuerNameHash` / `issuerKeyHash` as raw octets, and the responder's `byKey`
|
|
24
24
|
* hash and the raw `signature` bytes are left for the caller to verify. Embedded
|
|
@@ -63,12 +63,12 @@ var OID_OCSP_BASIC = oid.byName("ocspBasic");
|
|
|
63
63
|
// RFC 9654 sec. 2.1 (updating RFC 6960 sec. 4.4.1) fixes to OCTET STRING (SIZE(1..128)).
|
|
64
64
|
var OID_OCSP_NONCE = oid.byName("ocspNonce");
|
|
65
65
|
|
|
66
|
-
// OCSPResponseStatus ::= ENUMERATED
|
|
66
|
+
// OCSPResponseStatus ::= ENUMERATED. Value 4 is "not used" and >= 7 is undefined,
|
|
67
67
|
// so both are rejected (RFC 6960 sec. 4.2.1).
|
|
68
68
|
// OCSPResponseStatus value names -- single source pki.C.NAMES.OCSP_STATUS.
|
|
69
69
|
var STATUS_NAMES = constants.NAMES.OCSP_STATUS;
|
|
70
70
|
|
|
71
|
-
// CRLReason ::= ENUMERATED
|
|
71
|
+
// CRLReason ::= ENUMERATED. Value 7 is "not used"; the rest are RFC 5280
|
|
72
72
|
// sec. 5.3.1. The legal set + names live once in pkix.CRL_REASON_NAMES (shared
|
|
73
73
|
// with the CRL reasonCode decoder, which surfaces the numeric code).
|
|
74
74
|
var CRL_REASONS = pkix.CRL_REASON_NAMES;
|
|
@@ -98,14 +98,14 @@ var CRL_REASON = schema.decode(function (n, ctx) {
|
|
|
98
98
|
});
|
|
99
99
|
|
|
100
100
|
// A certs [0] SEQUENCE OF Certificate element. Unlike the CMS CertificateChoices
|
|
101
|
-
// (a tagged CHOICE), an OCSP certs element is a plain Certificate
|
|
102
|
-
// SEQUENCE (RFC 5280 sec. 4.1)
|
|
103
|
-
// reject a non-SEQUENCE element
|
|
101
|
+
// (a tagged CHOICE), an OCSP certs element is a plain Certificate, a universal
|
|
102
|
+
// SEQUENCE (RFC 5280 sec. 4.1), so assert that shape before surfacing its raw DER, and
|
|
103
|
+
// reject a non-SEQUENCE element instead of reporting arbitrary bytes as a cert.
|
|
104
104
|
function certificateBytes() {
|
|
105
105
|
return pkix.rawNonEmptySequence(NS, { code: "ocsp/bad-certs", message: "each certs element must be a non-empty Certificate SEQUENCE (RFC 6960 sec. 4.1.1/sec. 4.2.1)" });
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
-
// requestorName [1] EXPLICIT GeneralName (RFC 6960 sec. 4.1.1)
|
|
108
|
+
// requestorName [1] EXPLICIT GeneralName (RFC 6960 sec. 4.1.1), validated and surfaced raw
|
|
109
109
|
// via the shared pkix.generalName primitive (RFC 5280 sec. 4.2.1.6), so a malformed
|
|
110
110
|
// GeneralName fails closed and the OCSP + TSP parsers cannot drift on this grammar.
|
|
111
111
|
var GENERAL_NAME_RAW = pkix.generalName(NS, { code: "ocsp/bad-requestor-name" });
|
|
@@ -119,18 +119,18 @@ function _rawSignature(field) {
|
|
|
119
119
|
return sig.bytes;
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
-
// certs [0] EXPLICIT SEQUENCE OF Certificate
|
|
122
|
+
// certs [0] EXPLICIT SEQUENCE OF Certificate, each element raw. Shared by the
|
|
123
123
|
// request Signature and the BasicOCSPResponse.
|
|
124
124
|
// The certs list is capped: the delegated-responder authorization loop verifies
|
|
125
|
-
// each candidate
|
|
125
|
+
// each candidate before the response signature is checked, so an unbounded list in
|
|
126
126
|
// a relayed / stapled response would drive unbounded pre-auth signature verifies.
|
|
127
127
|
var CERTS = schema.seqOf(certificateBytes(), { assert: "sequence", code: "ocsp/bad-certs", what: "certs", max: constants.LIMITS.OCSP_MAX_CERTS, maxCode: "ocsp/too-many-certs" });
|
|
128
128
|
|
|
129
|
-
// Validate the OCSP protocol extension values in a decoded extension list
|
|
129
|
+
// Validate the OCSP protocol extension values in a decoded extension list,
|
|
130
130
|
// applied to every extension surface (request / single-request / response /
|
|
131
131
|
// single-response) so a hostile placement cannot dodge the syntax rule. The
|
|
132
132
|
// nonce is the one extension whose value the module names: Nonce ::= OCTET
|
|
133
|
-
// STRING (SIZE(1..128)) (RFC 9654 sec. 2.1, updating RFC 6960 sec. 4.4.1
|
|
133
|
+
// STRING (SIZE(1..128)) (RFC 9654 sec. 2.1, updating RFC 6960 sec. 4.4.1; the 128
|
|
134
134
|
// upper bound is the RFC 9654 responder rule; RFC 8954's was 32). The decoded
|
|
135
135
|
// nonce bytes are surfaced on the extension as `nonce` alongside the raw value;
|
|
136
136
|
// other extension values stay opaque (an unknown extension is representable,
|
|
@@ -240,9 +240,9 @@ var SINGLE_RESPONSE = schema.seq([
|
|
|
240
240
|
},
|
|
241
241
|
});
|
|
242
242
|
|
|
243
|
-
// ResponderID ::= CHOICE { byName [1] Name, byKey [2] KeyHash } (RFC 6960 sec. 4.2.1)
|
|
243
|
+
// ResponderID ::= CHOICE { byName [1] Name, byKey [2] KeyHash } (RFC 6960 sec. 4.2.1),
|
|
244
244
|
// both EXPLICIT (the module is EXPLICIT TAGS). byKey is an EXPLICIT-wrapped universal
|
|
245
|
-
// OCTET STRING (0xA2 04 ...)
|
|
245
|
+
// OCTET STRING (0xA2 04 ...) and not an IMPLICIT primitive [2].
|
|
246
246
|
var RESPONDER_ID = schema.choice([
|
|
247
247
|
{ when: { tagClass: "context", tagNumber: 1 }, schema: schema.explicit(1, NAME, { code: "ocsp/bad-responder-id" }) },
|
|
248
248
|
{ when: { tagClass: "context", tagNumber: 2 }, schema: schema.explicit(2, schema.octetString(), { code: "ocsp/bad-responder-id" }) },
|
|
@@ -284,7 +284,7 @@ var RESPONSE_DATA = schema.seq([
|
|
|
284
284
|
// BasicOCSPResponse ::= SEQUENCE { tbsResponseData ResponseData, signatureAlgorithm
|
|
285
285
|
// AlgorithmIdentifier, signature BIT STRING, certs [0] EXPLICIT SEQUENCE OF
|
|
286
286
|
// Certificate OPTIONAL } (RFC 6960 sec. 4.2.1). tbsResponseData.node.bytes is the exact
|
|
287
|
-
// signed region (no CMS-style re-tag divergence
|
|
287
|
+
// signed region (no CMS-style re-tag divergence, the clean case).
|
|
288
288
|
var BASIC_OCSP_RESPONSE = schema.seq([
|
|
289
289
|
schema.field("tbsResponseData", RESPONSE_DATA),
|
|
290
290
|
schema.field("signatureAlgorithm", ALGORITHM_IDENTIFIER),
|
package/lib/schema-pkcs12.js
CHANGED
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
*
|
|
11
11
|
* @intro
|
|
12
12
|
* PKCS#12 (PFX) key-and-certificate store handling per RFC 7292. `parse`
|
|
13
|
-
* decodes a `.p12` / `.pfx` container
|
|
14
|
-
* format OpenSSL, Windows CAPI, macOS Keychain, and NSS emit
|
|
13
|
+
* decodes a `.p12` / `.pfx` container, the personal-information-exchange
|
|
14
|
+
* format OpenSSL, Windows CAPI, macOS Keychain, and NSS emit, into its
|
|
15
15
|
* bags: private keys (delegated to the PKCS#8 parser), shrouded keys
|
|
16
16
|
* (algorithm surfaced, ciphertext kept opaque), certificates, CRLs,
|
|
17
17
|
* secrets, and nested safe contents, each with its `friendlyName` /
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
*
|
|
34
34
|
* @card
|
|
35
35
|
* Parse DER / BER / PEM RFC 7292 PKCS#12 (PFX) stores into key / cert /
|
|
36
|
-
* CRL / secret bags with their attributes
|
|
36
|
+
* CRL / secret bags with their attributes: keys via the PKCS#8 parser,
|
|
37
37
|
* encrypted safes via CMS, MAC inputs surfaced raw for external
|
|
38
38
|
* verification, fail-closed.
|
|
39
39
|
*/
|
|
@@ -86,7 +86,7 @@ var DIGEST_INFO = schema.seq([
|
|
|
86
86
|
|
|
87
87
|
// PBKDF2-params + PBMAC1-params (RFC 8018 sec. 5.2 / App. A.5, RFC 9579 sec. 4) constrained to the PBMAC1
|
|
88
88
|
// profile -- keyLength MUST be present, the prf DEFAULT is enforced non-canonical. Shared with CMP PBMAC1
|
|
89
|
-
// protection verification, so the reader lives once in schema-pkix (ns-parameterized)
|
|
89
|
+
// protection verification, so the reader lives once in schema-pkix (ns-parameterized) instead of a second
|
|
90
90
|
// copy per format; composed here with the pkcs12 namespace so it emits pkcs12/bad-mac-data.
|
|
91
91
|
var PBMAC1_PARAMS = pkix.pbmac1Params(NS);
|
|
92
92
|
|
|
@@ -235,14 +235,14 @@ var SAFE_BAG = schema.seq([
|
|
|
235
235
|
},
|
|
236
236
|
});
|
|
237
237
|
|
|
238
|
-
// SafeContents ::= SEQUENCE OF SafeBag (sec. 4.2). Strictly a SEQUENCE
|
|
238
|
+
// SafeContents ::= SEQUENCE OF SafeBag (sec. 4.2). Strictly a SEQUENCE: a SET OF
|
|
239
239
|
// here is a known producer divergence and rejects.
|
|
240
240
|
var SAFE_CONTENTS = schema.seqOf(SAFE_BAG, {
|
|
241
241
|
code: "pkcs12/bad-safe-contents", what: "SafeContents",
|
|
242
242
|
max: C.LIMITS.PKCS12_MAX_ELEMENTS, maxCode: "pkcs12/too-many-elements",
|
|
243
243
|
});
|
|
244
244
|
|
|
245
|
-
// AuthenticatedSafe ::= SEQUENCE OF ContentInfo (sec. 4.1)
|
|
245
|
+
// AuthenticatedSafe ::= SEQUENCE OF ContentInfo (sec. 4.1), each element parsed
|
|
246
246
|
// structurally here and dispatched by contentType in _dispatchSafes.
|
|
247
247
|
var AS_ELEMENT = schema.seq([
|
|
248
248
|
schema.field("contentType", schema.oidLeaf()),
|
|
@@ -292,9 +292,9 @@ var PFX = schema.seq([
|
|
|
292
292
|
// STRING (the AuthenticatedSafe encoding), excluding the TLV header.
|
|
293
293
|
// MacData itself is OPTIONAL in the PFX syntax: a store without it
|
|
294
294
|
// (OpenSSL `pkcs12 -export -nomac`) carries no integrity protection at
|
|
295
|
-
// all, which is a policy concern for the caller
|
|
296
|
-
// integrityMode "none", never rejected by a parser
|
|
297
|
-
// integrity inputs
|
|
295
|
+
// all, which is a policy concern for the caller. It is surfaced as
|
|
296
|
+
// integrityMode "none", never rejected by a parser whose job is to
|
|
297
|
+
// surface integrity inputs and not to verify them.
|
|
298
298
|
var macedBytes = _octetContent(authSafe.innerNode, ctx, "an id-data authSafe content", "pkcs12/bad-authsafe");
|
|
299
299
|
var dispatched = _dispatchSafes(_walkAuthenticatedSafe(macedBytes, state, ctx), state, ctx);
|
|
300
300
|
return {
|
|
@@ -312,7 +312,7 @@ var PFX = schema.seq([
|
|
|
312
312
|
if (signed.encapContentInfo.eContent === null) {
|
|
313
313
|
throw ctx.E("pkcs12/bad-authsafe", "a public-key-integrity authSafe must carry attached eContent (RFC 7292 sec. 4.1)");
|
|
314
314
|
}
|
|
315
|
-
// A signer-less SignedData carries no integrity at all
|
|
315
|
+
// A signer-less SignedData carries no integrity at all, the one thing
|
|
316
316
|
// public-key-integrity mode exists to provide.
|
|
317
317
|
if (signed.signerInfos.length < 1) {
|
|
318
318
|
throw ctx.E("pkcs12/bad-authsafe", "a public-key-integrity authSafe must carry at least one SignerInfo (RFC 7292 sec. 4)");
|
|
@@ -340,7 +340,7 @@ function _octetContent(node, ctx, what, code) {
|
|
|
340
340
|
// RFC 7292 sec. 4.1 -- a privacy-mode safe wraps a SafeContents, so the encrypted
|
|
341
341
|
// content's declared type must be id-data whichever CMS privacy structure
|
|
342
342
|
// carries it, and the ciphertext must be attached: CMS permits a detached
|
|
343
|
-
// EncryptedContentInfo, but here the ciphertext
|
|
343
|
+
// EncryptedContentInfo, but here the ciphertext is the safe's contents, and a
|
|
344
344
|
// safe without it holds nothing a passphrase could ever recover.
|
|
345
345
|
function _privacySafe(content, ctx) {
|
|
346
346
|
if (content.encryptedContentInfo.contentType !== OID_DATA) {
|
|
@@ -377,10 +377,10 @@ function _walkAuthenticatedSafe(bytes, state, ctx) {
|
|
|
377
377
|
// full CMS structures validated by the CMS module on the already-decoded node
|
|
378
378
|
// -- ciphertext stays opaque inside the CMS surface.
|
|
379
379
|
// @internal -- re-parse a DECRYPTED privacy-safe's plaintext (a SafeContents ::= SEQUENCE OF SafeBag) through
|
|
380
|
-
// the
|
|
380
|
+
// the same strict SAFE_CONTENTS walk and bag dispatch the plaintext path uses, so a decrypted blob shares every
|
|
381
381
|
// PKCS12_MAX_* cap and produces the identical bag records. Consumed by pki.pkcs12.open for an encrypted safe.
|
|
382
382
|
function walkSafeContents(der) {
|
|
383
|
-
// PKCS#12 content regions are normatively BER (RFC 7292 sec. 4.1)
|
|
383
|
+
// PKCS#12 content regions are normatively BER (RFC 7292 sec. 4.1), so a decrypted SafeContents may use an
|
|
384
384
|
// indefinite-length SEQUENCE, exactly as the plaintext-safe path (_dispatchSafes) decodes it with ber:true.
|
|
385
385
|
var walked = schema.walk(SAFE_CONTENTS, asn1.decode(der, { ber: true }), NS);
|
|
386
386
|
var state = { budget: { remaining: C.LIMITS.PKCS12_MAX_REDECODES }, bagDepth: 0 };
|
|
@@ -407,7 +407,7 @@ function _dispatchSafes(asMatch, state, ctx) {
|
|
|
407
407
|
} else if (el.contentType === OID_ENVELOPED_DATA) {
|
|
408
408
|
// Surface the raw EnvelopedData DER alongside the walked structure: public-key privacy opens by driving
|
|
409
409
|
// pki.cms.decrypt, which re-parses strict DER (it takes no pre-parsed object), so pkcs12.open reconstructs
|
|
410
|
-
// the ContentInfo around these bytes
|
|
410
|
+
// the ContentInfo around these bytes and never re-serializes the recipientInfos the integrity check trusts.
|
|
411
411
|
encryptedSafes.push({ type: "envelopedData", content: _privacySafe(cms.walkEnvelopedData(el.innerNode), ctx), envelopedDataDer: el.innerNode.bytes });
|
|
412
412
|
} else {
|
|
413
413
|
throw ctx.E("pkcs12/bad-safe-contentinfo-type", "an AuthenticatedSafe element must be id-data, id-encryptedData, or id-envelopedData (RFC 7292 sec. 4.1), got " +
|
|
@@ -425,7 +425,7 @@ function _buildBag(rec, state, ctx) {
|
|
|
425
425
|
type: null, bagId: rec.bagId,
|
|
426
426
|
friendlyName: rec.friendlyName, localKeyId: rec.localKeyId, attributes: rec.attributes,
|
|
427
427
|
};
|
|
428
|
-
// Key bags are walked from the
|
|
428
|
+
// Key bags are walked from the decoded node, since their wire bytes may carry
|
|
429
429
|
// BER shapes the strict pkcs8 parse entry refuses, and the node already
|
|
430
430
|
// exists (no re-decode).
|
|
431
431
|
if (rec.bagId === OID_KEY_BAG) {
|
|
@@ -493,17 +493,17 @@ function _buildBag(rec, state, ctx) {
|
|
|
493
493
|
* decoded onto `pbmac1` (`{ kdf: { salt, iterationCount, keyLength, prfOid,
|
|
494
494
|
* prfName }, schemeOid, schemeName }`) with `hashParameters` keeping the raw
|
|
495
495
|
* bytes, and `macedBytes` is the exact byte range the HMAC covers),
|
|
496
|
-
* `"none"` (id-data authSafe without MacData
|
|
496
|
+
* `"none"` (id-data authSafe without MacData, the shape
|
|
497
497
|
* `openssl pkcs12 -export -nomac` emits; `mac` is `null` and the store
|
|
498
498
|
* carries no integrity protection, a policy decision left to the caller),
|
|
499
|
-
* or `"public-key"` (id-signedData authSafe
|
|
499
|
+
* or `"public-key"` (id-signedData authSafe, the CMS SignedData surfaced
|
|
500
500
|
* on `authSafeSigned`, signature not verified here). Each of `safeBags` is
|
|
501
501
|
* `{ type, bagId, friendlyName, localKeyId, attributes }` plus its arm:
|
|
502
502
|
* a `keyBag` carries `key` (the PKCS#8 parse), a `pkcs8ShroudedKeyBag`
|
|
503
503
|
* carries `encrypted` (algorithm surfaced, ciphertext opaque), `certBag` /
|
|
504
504
|
* `crlBag` / `secretBag` carry their values raw and byte-exact, and a
|
|
505
505
|
* `safeContentsBag` carries `nested` bags. Encrypted / enveloped safes are
|
|
506
|
-
* surfaced structurally on `encryptedSafes` via the CMS module
|
|
506
|
+
* surfaced structurally on `encryptedSafes` via the CMS module: recipient
|
|
507
507
|
* infos and algorithms decoded, ciphertext never parsed. MAC verification
|
|
508
508
|
* and bag decryption are passphrase operations for an external layer; the
|
|
509
509
|
* inputs are surfaced exactly.
|
|
@@ -512,7 +512,7 @@ function _buildBag(rec, state, ctx) {
|
|
|
512
512
|
* `Asn1Error` when the underlying encoding is malformed. Faults inside a
|
|
513
513
|
* delegated CMS structure (a signedData authSafe, an encrypted / enveloped
|
|
514
514
|
* safe) surface as `CmsError` (`cms/*`) and inside a key bag as `Pkcs8Error`
|
|
515
|
-
* (`pkcs8/*`)
|
|
515
|
+
* (`pkcs8/*`), all of them `PkiError` subclasses.
|
|
516
516
|
*
|
|
517
517
|
* @example
|
|
518
518
|
* var pair = await pki.key.generate("Ed25519");
|
|
@@ -542,7 +542,7 @@ var parse = pkix.makeRecordingParser({
|
|
|
542
542
|
* @related pki.schema.pkcs12.parse
|
|
543
543
|
*
|
|
544
544
|
* Extract the DER bytes from a PEM block (default label `PKCS12`). A
|
|
545
|
-
* `.p12` / `.pfx` file is almost always binary
|
|
545
|
+
* `.p12` / `.pfx` file is almost always binary, so the PEM path is a
|
|
546
546
|
* convenience for stores that transit text channels.
|
|
547
547
|
*
|
|
548
548
|
* @example
|
package/lib/schema-pkcs8.js
CHANGED
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* PKCS#8 private-key handling per RFC 5208 sec. 5 (PrivateKeyInfo) and RFC 5958 sec. 2
|
|
13
13
|
* (OneAsymmetricKey). `parse` turns a DER or PEM (`PRIVATE KEY`) key into a
|
|
14
14
|
* structured object: version, the private-key algorithm identifier, the raw
|
|
15
|
-
* private-key bytes, the optional attributes, and
|
|
15
|
+
* private-key bytes, the optional attributes, and (for a v2 OneAsymmetricKey)
|
|
16
16
|
* the optional public key. It composes the same schema engine and shared PKIX
|
|
17
17
|
* sub-schemas (AlgorithmIdentifier, Attribute) the other parsers use.
|
|
18
18
|
*
|
|
@@ -46,7 +46,7 @@ var NS = pkix.makeNS("pkcs8", Pkcs8Error, oid);
|
|
|
46
46
|
var ALGORITHM_IDENTIFIER = pkix.algorithmIdentifier(NS);
|
|
47
47
|
var ATTRIBUTE = pkix.attribute(NS);
|
|
48
48
|
|
|
49
|
-
// version ::= INTEGER { v1(0), v2(1) }
|
|
49
|
+
// version ::= INTEGER { v1(0), v2(1) }, where 0 and 1 are both legal (the divergence
|
|
50
50
|
// from every other reader; cert/CRL reject 0, CSR accepts only 0). Surface as the
|
|
51
51
|
// RFC's vN number.
|
|
52
52
|
var PKCS8_VERSION = pkix.versionReader(NS, { "0": 1, "1": 2 });
|