@blamejs/pki 0.1.21 → 0.1.23
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 +47 -0
- package/README.md +17 -6
- package/index.js +16 -12
- package/lib/asn1-der.js +126 -68
- package/lib/constants.js +46 -21
- package/lib/ct.js +54 -39
- package/lib/framework-error.js +64 -32
- package/lib/oid.js +114 -58
- package/lib/path-validate.js +302 -135
- package/lib/schema-all.js +54 -40
- package/lib/schema-attrcert.js +101 -64
- package/lib/schema-cmp.js +152 -131
- package/lib/schema-cms.js +621 -163
- package/lib/schema-crl.js +43 -21
- package/lib/schema-crmf.js +136 -79
- package/lib/schema-csr.js +63 -14
- package/lib/schema-engine.js +92 -43
- package/lib/schema-ocsp.js +101 -55
- package/lib/schema-pkcs12.js +80 -64
- package/lib/schema-pkcs8.js +12 -12
- package/lib/schema-pkix.js +306 -111
- package/lib/schema-smime.js +363 -0
- package/lib/schema-tsp.js +108 -59
- package/lib/schema-x509.js +36 -25
- package/lib/webcrypto.js +156 -22
- package/package.json +3 -2
- package/sbom.cdx.json +6 -6
package/lib/oid.js
CHANGED
|
@@ -13,12 +13,12 @@
|
|
|
13
13
|
* OID strings and their human names, plus arc conversion and DER
|
|
14
14
|
* encode/decode convenience. Every algorithm, attribute type, and
|
|
15
15
|
* extension in PKI is named by an OID, and resolving them through one
|
|
16
|
-
* registry
|
|
17
|
-
* codebase
|
|
16
|
+
* registry -- rather than scattering magic dotted strings across the
|
|
17
|
+
* codebase -- is what lets a new algorithm be a data entry instead of a
|
|
18
18
|
* code change.
|
|
19
19
|
*
|
|
20
20
|
* The seed set is declared by FAMILY: an OID belongs to a class with a
|
|
21
|
-
* shared base arc (the "starting variable"
|
|
21
|
+
* shared base arc (the "starting variable" -- `2.5.4` for the RFC 5280
|
|
22
22
|
* attribute types, `2.5.29` for the extensions, `2.16.840.1.101.3.4` for
|
|
23
23
|
* the NIST algorithms), and each member names only its trailing arc. The
|
|
24
24
|
* full OID is derived from base + leaf at load, so the arc hierarchy that
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
* extend it with `register` (one OID) or `registerFamily` (a whole arc).
|
|
30
30
|
*
|
|
31
31
|
* @card
|
|
32
|
-
* Two-way OID
|
|
32
|
+
* Two-way OID <-> name registry with arc conversion, seeded by family from
|
|
33
33
|
* the RFC 5280 and NIST post-quantum object identifiers.
|
|
34
34
|
*/
|
|
35
35
|
|
|
@@ -38,72 +38,72 @@ var frameworkError = require("./framework-error");
|
|
|
38
38
|
|
|
39
39
|
var OidError = frameworkError.OidError;
|
|
40
40
|
|
|
41
|
-
// FAMILIES
|
|
41
|
+
// FAMILIES -- OIDs grouped by their shared base arc (the "similar starting
|
|
42
42
|
// variable" that defines a class). A member is `name: leaf`, where leaf is a
|
|
43
43
|
// trailing arc (number) or a short arc array for a multi-level leaf; the full
|
|
44
44
|
// arc is derived at load via base.concat(leaf). Declaring by family means no
|
|
45
45
|
// dotted-decimal OID literal appears in this source at all, and adding a
|
|
46
|
-
// member is one `name: leaf` line under its class
|
|
46
|
+
// member is one `name: leaf` line under its class -- no base to re-type.
|
|
47
47
|
var FAMILIES = {
|
|
48
48
|
// RFC 5280 attribute types.
|
|
49
49
|
attributeType: { base: [2, 5, 4], of: {
|
|
50
50
|
commonName: 3, surname: 4, serialNumber: 5, countryName: 6,
|
|
51
51
|
localityName: 7, stateOrProvinceName: 8, streetAddress: 9,
|
|
52
52
|
organizationName: 10, organizationalUnitName: 11, title: 12, givenName: 42,
|
|
53
|
-
// RFC 5755
|
|
53
|
+
// RFC 5755 sec. 4.4 attribute-certificate attribute types.
|
|
54
54
|
clearance: 55, role: 72 } },
|
|
55
55
|
|
|
56
56
|
// RFC 5280 certificate extensions.
|
|
57
57
|
certExtension: { base: [2, 5, 29], of: {
|
|
58
58
|
subjectKeyIdentifier: 14, keyUsage: 15, subjectAltName: 17, issuerAltName: 18,
|
|
59
59
|
basicConstraints: 19,
|
|
60
|
-
// CRL + CRL-entry extensions (RFC 5280
|
|
60
|
+
// CRL + CRL-entry extensions (RFC 5280 sec. 5.2, sec. 5.3)
|
|
61
61
|
cRLNumber: 20, reasonCode: 21, invalidityDate: 24, deltaCRLIndicator: 27,
|
|
62
62
|
issuingDistributionPoint: 28, certificateIssuer: 29,
|
|
63
63
|
nameConstraints: 30, cRLDistributionPoints: 31,
|
|
64
64
|
certificatePolicies: 32, policyMappings: 33, authorityKeyIdentifier: 35,
|
|
65
65
|
policyConstraints: 36, extKeyUsage: 37, freshestCRL: 46,
|
|
66
66
|
inhibitAnyPolicy: 54,
|
|
67
|
-
// The two special-OID leaves under extension arcs (RFC 5280
|
|
68
|
-
//
|
|
67
|
+
// The two special-OID leaves under extension arcs (RFC 5280 sec. 4.2.1.4 /
|
|
68
|
+
// sec. 4.2.1.12): the certificate-policies wildcard and the EKU wildcard.
|
|
69
69
|
anyPolicy: [32, 0], anyExtendedKeyUsage: [37, 0],
|
|
70
|
-
// RFC 5755 attribute-certificate extensions (
|
|
70
|
+
// RFC 5755 attribute-certificate extensions (sec. 4.3.2, sec. 4.3.6).
|
|
71
71
|
targetInformation: 55, noRevAvail: 56 } },
|
|
72
72
|
|
|
73
73
|
// PKIX private extensions on the id-pe arc (authorityInfoAccess et al, plus the
|
|
74
|
-
// RFC 5755 attribute-certificate id-pe extensions: ac-auditIdentity
|
|
75
|
-
// aaControls
|
|
74
|
+
// RFC 5755 attribute-certificate id-pe extensions: ac-auditIdentity sec. 4.3.1,
|
|
75
|
+
// aaControls sec. 7.4, ac-proxying sec. 7.2).
|
|
76
76
|
pkixAccess: { base: [1, 3, 6, 1, 5, 5, 7, 1], of: {
|
|
77
77
|
authorityInfoAccess: 1, acAuditIdentity: 4, aaControls: 6, acProxying: 10 } },
|
|
78
78
|
|
|
79
|
-
// id-aca
|
|
80
|
-
// authenticationInfo
|
|
79
|
+
// id-aca -- RFC 5755 attribute-certificate attribute types on the id-pkix 10 arc:
|
|
80
|
+
// authenticationInfo sec. 4.4.1 .. group sec. 4.4.4, plus encAttrs sec. 7.1 (the encrypted-
|
|
81
81
|
// attribute wrapper, syntax ContentInfo). { id-aca 5 } is reserved.
|
|
82
82
|
idAca: { base: [1, 3, 6, 1, 5, 5, 7, 10], of: {
|
|
83
83
|
authenticationInfo: 1, accessIdentity: 2, chargingIdentity: 3, group: 4, encAttrs: 6 } },
|
|
84
84
|
|
|
85
85
|
// The legacy RFC 3281 id-at-clearance on the X.501 selected-attribute-types arc.
|
|
86
|
-
// RFC 5755
|
|
86
|
+
// RFC 5755 sec. 4.4.6 says implementations MUST NOT OUTPUT this form but SHOULD ACCEPT
|
|
87
87
|
// it for decoding, so it is registered as an alias of "clearance". The canonical
|
|
88
88
|
// name -> OID reverse stays the RFC 5755 attributeType-arc 2.5.4.55 (registered
|
|
89
89
|
// first under attributeType, so it wins the reverse mapping).
|
|
90
90
|
selectedAttrType: { base: [2, 5, 1, 5], of: { clearance: 55 } },
|
|
91
91
|
|
|
92
|
-
// PKIX Access Descriptor methods (id-ad, RFC 5280
|
|
92
|
+
// PKIX Access Descriptor methods (id-ad, RFC 5280 sec. 4.2.2.1/sec. 4.2.2.2). id-ad-ocsp
|
|
93
93
|
// is the arc the OCSP responder OIDs hang under; id-ad-caIssuers names the AIA
|
|
94
94
|
// CA-issuers access method.
|
|
95
95
|
adAccess: { base: [1, 3, 6, 1, 5, 5, 7, 48], of: { ocsp: 1, caIssuers: 2 } },
|
|
96
96
|
|
|
97
97
|
// OCSP (RFC 6960) on the id-pkix-ocsp arc (= id-ad-ocsp). id-pkix-ocsp-basic is
|
|
98
|
-
// the ResponseBytes.responseType this build decodes; id-pkix-ocsp-nonce (
|
|
98
|
+
// the ResponseBytes.responseType this build decodes; id-pkix-ocsp-nonce (sec. 4.4.1)
|
|
99
99
|
// names the nonce extension; the remaining members name the other OCSP extensions
|
|
100
100
|
// (CRL references, acceptable-response-types, archive-cutoff, service-locator,
|
|
101
|
-
// preferred-signature-algorithms, extended-revoke
|
|
101
|
+
// preferred-signature-algorithms, extended-revoke -- RFC 6960 sec. 4.4, RFC 9654).
|
|
102
102
|
ocsp: { base: [1, 3, 6, 1, 5, 5, 7, 48, 1], of: {
|
|
103
103
|
ocspBasic: 1, ocspNonce: 2, ocspCrl: 3, ocspResponse: 4, ocspNoCheck: 5,
|
|
104
104
|
ocspArchiveCutoff: 6, ocspServiceLocator: 7, ocspPrefSigAlgs: 8, ocspExtendedRevoke: 9 } },
|
|
105
105
|
|
|
106
|
-
// CRMF (RFC 4211) registration controls (
|
|
106
|
+
// CRMF (RFC 4211) registration controls (sec. 6) and registration info (sec. 7) on the
|
|
107
107
|
// id-pkip arc (id-pkix 5). id-regCtrl (id-pkip 1) names the control types a
|
|
108
108
|
// CertRequest carries; id-regInfo (id-pkip 2) names the registration-info types.
|
|
109
109
|
// The parser surfaces each control/info value RAW keyed by these names.
|
|
@@ -111,15 +111,15 @@ var FAMILIES = {
|
|
|
111
111
|
regToken: 1, authenticator: 2, pkiPublicationInfo: 3, pkiArchiveOptions: 4, oldCertID: 5, protocolEncrKey: 6 } },
|
|
112
112
|
regInfo: { base: [1, 3, 6, 1, 5, 5, 7, 5, 2], of: { utf8Pairs: 1, certReq: 2 } },
|
|
113
113
|
|
|
114
|
-
// PKIX extended key purposes (id-kp, RFC 5280
|
|
115
|
-
//
|
|
114
|
+
// PKIX extended key purposes (id-kp, RFC 5280 sec. 4.2.1.12). timeStamping is required
|
|
115
|
+
// -- critical and sole -- on an RFC 3161 TSA signing certificate (sec. 2.3).
|
|
116
116
|
pkixKp: { base: [1, 3, 6, 1, 5, 5, 7, 3], of: {
|
|
117
117
|
serverAuth: 1, clientAuth: 2, codeSigning: 3, emailProtection: 4, timeStamping: 8, ocspSigning: 9 } },
|
|
118
118
|
|
|
119
119
|
// Google Certificate Transparency (RFC 6962) on the 1.3.6.1.4.1.11129.2.4 arc:
|
|
120
|
-
// the SCT-list X.509 extension (
|
|
121
|
-
// precert-signing EKU (
|
|
122
|
-
// (
|
|
120
|
+
// the SCT-list X.509 extension (sec. 3.3), the precertificate poison (sec. 3.1), the
|
|
121
|
+
// precert-signing EKU (sec. 3.1, naming only), and the OCSP-delivered SCT list
|
|
122
|
+
// (sec. 3.3). The SCT payload itself is TLS presentation language, not DER -- it is
|
|
123
123
|
// parsed by lib/ct.js (pki.ct), never routed through the DER schema engine.
|
|
124
124
|
ct: { base: [1, 3, 6, 1, 4, 1, 11129, 2, 4], of: {
|
|
125
125
|
signedCertificateTimestampList: 2, precertificatePoison: 3,
|
|
@@ -131,26 +131,27 @@ var FAMILIES = {
|
|
|
131
131
|
sha256WithRSAEncryption: 11,
|
|
132
132
|
sha384WithRSAEncryption: 12, sha512WithRSAEncryption: 13 } },
|
|
133
133
|
|
|
134
|
-
// PKCS#7 / CMS content types (RFC 5652
|
|
134
|
+
// PKCS#7 / CMS content types (RFC 5652 sec. 4, RFC 2315). id-signedData is the one
|
|
135
135
|
// this toolkit structurally decodes; the rest are recognized-and-deferred.
|
|
136
136
|
pkcs7: { base: [1, 2, 840, 113549, 1, 7], of: {
|
|
137
137
|
data: 1, signedData: 2, envelopedData: 3, signedAndEnvelopedData: 4,
|
|
138
138
|
digestedData: 5, encryptedData: 6 } },
|
|
139
139
|
|
|
140
|
-
// PKCS#9 attribute types
|
|
141
|
-
// and the PKCS#12 bag attributes friendlyName / localKeyId (RFC 7292
|
|
140
|
+
// PKCS#9 attribute types -- incl. the CMS signed-attribute OIDs (RFC 5652 sec. 11)
|
|
141
|
+
// and the PKCS#12 bag attributes friendlyName / localKeyId (RFC 7292 sec. 4.2).
|
|
142
142
|
pkcs9: { base: [1, 2, 840, 113549, 1, 9], of: {
|
|
143
143
|
emailAddress: 1, contentType: 3, messageDigest: 4, signingTime: 5,
|
|
144
|
-
challengePassword: 7, extensionRequest: 14,
|
|
144
|
+
countersignature: 6, challengePassword: 7, extensionRequest: 14,
|
|
145
|
+
smimeCapabilities: 15, friendlyName: 20, localKeyId: 21 } },
|
|
145
146
|
|
|
146
|
-
// PKCS#9 CertBag / CRLBag value discriminators (RFC 7292
|
|
147
|
+
// PKCS#9 CertBag / CRLBag value discriminators (RFC 7292 sec. 4.2.3-sec. 4.2.4).
|
|
147
148
|
pkcs9CertTypes: { base: [1, 2, 840, 113549, 1, 9, 22], of: { x509Certificate: 1, sdsiCertificate: 2 } },
|
|
148
149
|
pkcs9CrlTypes: { base: [1, 2, 840, 113549, 1, 9, 23], of: { x509CRL: 1 } },
|
|
149
150
|
|
|
150
151
|
// PKCS#5 password-based schemes (RFC 8018) + the PBMAC1 MacData arm (RFC 9579).
|
|
151
152
|
pkcs5: { base: [1, 2, 840, 113549, 1, 5], of: { pbkdf2: 12, pbes2: 13, pbmac1: 14 } },
|
|
152
153
|
|
|
153
|
-
// CMP InfoTypeAndValue types
|
|
154
|
+
// CMP InfoTypeAndValue types -- id-it under id-pkix (RFC 9810 sec. 5.3.19; the
|
|
154
155
|
// PKIXCMP-2023 module assigns these leaves, 8/9 unassigned).
|
|
155
156
|
idIt: { base: [1, 3, 6, 1, 5, 5, 7, 4], of: {
|
|
156
157
|
caProtEncCert: 1, signKeyPairTypes: 2, encKeyPairTypes: 3, preferredSymmAlg: 4,
|
|
@@ -161,15 +162,15 @@ var FAMILIES = {
|
|
|
161
162
|
crls: 23, kemCiphertextInfo: 24 } },
|
|
162
163
|
|
|
163
164
|
// CMP message-protection MAC algorithms on the Entrust arc (RFC 9810
|
|
164
|
-
//
|
|
165
|
+
// sec. 5.1.3.1/.2/.4; RFC 9481 sec. 6.1.1).
|
|
165
166
|
entrustAlg: { base: [1, 2, 840, 113533, 7, 66], of: {
|
|
166
167
|
passwordBasedMac: 13, kemBasedMac: 16, dhBasedMac: 30 } },
|
|
167
168
|
|
|
168
|
-
// PKCS#12 bag types (RFC 7292
|
|
169
|
+
// PKCS#12 bag types (RFC 7292 sec. 4.2, Appendix D).
|
|
169
170
|
pkcs12BagTypes: { base: [1, 2, 840, 113549, 1, 12, 10, 1], of: {
|
|
170
171
|
keyBag: 1, pkcs8ShroudedKeyBag: 2, certBag: 3, crlBag: 4, secretBag: 5, safeContentsBag: 6 } },
|
|
171
172
|
|
|
172
|
-
// PKCS#12 password-based encryption schemes (RFC 7292 Appendix C)
|
|
173
|
+
// PKCS#12 password-based encryption schemes (RFC 7292 Appendix C) -- legacy
|
|
173
174
|
// PBE identifiers still emitted by deployed exporters; recognized so a
|
|
174
175
|
// shrouded bag's algorithm resolves to a name, never decrypted here.
|
|
175
176
|
pkcs12Pbe: { base: [1, 2, 840, 113549, 1, 12, 1], of: {
|
|
@@ -177,18 +178,42 @@ var FAMILIES = {
|
|
|
177
178
|
"pbeWithSHAAnd3-KeyTripleDES-CBC": 3, "pbeWithSHAAnd2-KeyTripleDES-CBC": 4,
|
|
178
179
|
"pbeWithSHAAnd128BitRC2-CBC": 5, "pbeWithSHAAnd40BitRC2-CBC": 6 } },
|
|
179
180
|
|
|
180
|
-
// RSADSI digest / HMAC algorithms (RFC 8018
|
|
181
|
+
// RSADSI digest / HMAC algorithms (RFC 8018 sec. B.1) -- the PBKDF2 / PBMAC1 PRFs.
|
|
181
182
|
rsadsiDigest: { base: [1, 2, 840, 113549, 2], of: {
|
|
182
183
|
hmacWithSHA1: 7, hmacWithSHA224: 8, hmacWithSHA256: 9,
|
|
183
184
|
hmacWithSHA384: 10, hmacWithSHA512: 11 } },
|
|
184
185
|
|
|
185
186
|
// S/MIME content types on the PKCS#9 smime arc (RFC 5652, RFC 3161): id-ct.
|
|
186
|
-
|
|
187
|
+
// authData is RFC 5652 sec. 9 AuthenticatedData; authEnvelopedData is RFC 5083.
|
|
188
|
+
smimeCt: { base: [1, 2, 840, 113549, 1, 9, 16, 1], of: { authData: 2, tSTInfo: 4, authEnvelopedData: 23, encKeyWithID: 21 } },
|
|
189
|
+
|
|
190
|
+
// S/MIME other-recipient-info types (id-ori, RFC 5652 sec. 6.2.5). id-ori-kem
|
|
191
|
+
// carries a KEMRecipientInfo (RFC 9629) inside the ori [4] RecipientInfo arm.
|
|
192
|
+
smimeOri: { base: [1, 2, 840, 113549, 1, 9, 16, 13], of: { kem: 3 } },
|
|
193
|
+
|
|
194
|
+
// S/MIME algorithm identifiers (id-alg). The HKDF KDFs (RFC 8619) and the
|
|
195
|
+
// CEK-HKDF content-encryption wrapper (RFC 9709) a KEMRecipientInfo names, plus
|
|
196
|
+
// the RSA-KEM SPKI algorithm (RFC 9690). Parameters are absent for the HKDFs.
|
|
197
|
+
smimeAlg: { base: [1, 2, 840, 113549, 1, 9, 16, 3], of: {
|
|
198
|
+
"id-rsa-kem": 14, hkdfWithSha256: 28, hkdfWithSha384: 29, hkdfWithSha512: 30, cekHkdfSha256: 31 } },
|
|
199
|
+
|
|
200
|
+
// RSA-KEM key-transport algorithm (RFC 9690, obsoletes RFC 5990) on the ISO
|
|
201
|
+
// 18033-2 arc -- the kem OID an RSA KEMRecipientInfo carries (distinct from the
|
|
202
|
+
// id-rsa-kem SPKI algorithm above).
|
|
203
|
+
iso18033: { base: [1, 0, 18033, 2, 2], of: { "id-kem-rsa": 4 } },
|
|
204
|
+
|
|
205
|
+
// RFC 3370 HMAC-SHA-1 MAC algorithm (the AuthenticatedData macAlgorithm on the
|
|
206
|
+
// PKIX arc, distinct from the RSADSI hmacWithSHA1).
|
|
207
|
+
pkixHmac: { base: [1, 3, 6, 1, 5, 5, 8, 1], of: { "hmac-SHA1": 2 } },
|
|
187
208
|
|
|
188
209
|
// S/MIME authenticated attributes (id-aa, RFC 2634 / RFC 5035 / RFC 5816). The ESS
|
|
189
210
|
// signing-certificate attributes bind a CMS / TSP SignerInfo to its signing cert;
|
|
190
|
-
// signingCertificateV2 (ESSCertIDv2) carries a non-SHA-1 cert hash (RFC 5816
|
|
211
|
+
// signingCertificateV2 (ESSCertIDv2) carries a non-SHA-1 cert hash (RFC 5816 sec. 2.2.1).
|
|
212
|
+
// The RFC 2634 originals (receiptRequest .. contentReference) are name-only: they
|
|
213
|
+
// resolve to a name so an unsupported-attribute diagnostic is legible, not decoded.
|
|
191
214
|
smimeAa: { base: [1, 2, 840, 113549, 1, 9, 16, 2], of: {
|
|
215
|
+
receiptRequest: 1, eSSSecurityLabel: 2, mlExpansionHistory: 3, contentHints: 4,
|
|
216
|
+
msgSigDigest: 5, contentIdentifier: 7, equivalentLabels: 9, contentReference: 10,
|
|
192
217
|
signingCertificate: 12, timeStampToken: 14, signingCertificateV2: 47 } },
|
|
193
218
|
|
|
194
219
|
// ANSI X9.62 EC public key, named curve, and ECDSA signatures.
|
|
@@ -202,22 +227,23 @@ var FAMILIES = {
|
|
|
202
227
|
// Edwards / Montgomery curves (RFC 8410).
|
|
203
228
|
edwards: { base: [1, 3, 101], of: { X25519: 110, X448: 111, Ed25519: 112, Ed448: 113 } },
|
|
204
229
|
|
|
205
|
-
// OIW Secsig SHA-1 (1.3.14.3.2.26)
|
|
230
|
+
// OIW Secsig SHA-1 (1.3.14.3.2.26) -- the most common OCSP CertID hashAlgorithm;
|
|
206
231
|
// nistHash covers only SHA-256 and above.
|
|
207
232
|
oiwSecsig: { base: [1, 3, 14, 3, 2], of: { sha1: 26 } },
|
|
208
233
|
|
|
209
|
-
// NIST AES content-encryption algorithms (arc 2.16.840.1.101.3.4.1)
|
|
234
|
+
// NIST AES content-encryption algorithms (arc 2.16.840.1.101.3.4.1) -- the
|
|
210
235
|
// modern PBES2 / CMS content ciphers a PKCS#12 or EnvelopedData names.
|
|
211
236
|
nistAes: { base: [2, 16, 840, 1, 101, 3, 4, 1], of: {
|
|
212
|
-
"aes128-CBC": 2, "aes128-
|
|
213
|
-
"
|
|
237
|
+
"aes128-CBC": 2, "aes128-wrap": 5, "aes128-GCM": 6, "aes128-CCM": 7,
|
|
238
|
+
"aes192-CBC": 22, "aes192-wrap": 25, "aes192-GCM": 26, "aes192-CCM": 27,
|
|
239
|
+
"aes256-CBC": 42, "aes256-wrap": 45, "aes256-GCM": 46, "aes256-CCM": 47 } },
|
|
214
240
|
|
|
215
241
|
// NIST hash functions (SHA-2, SHA-3, SHAKE).
|
|
216
242
|
nistHash: { base: [2, 16, 840, 1, 101, 3, 4, 2], of: {
|
|
217
243
|
sha256: 1, sha384: 2, sha512: 3, "sha3-256": 8, "sha3-512": 10, shake256: 12 } },
|
|
218
244
|
|
|
219
|
-
// NIST signature algorithms
|
|
220
|
-
// signature arc 2.16.840.1.101.3.4.3. RFC 9909
|
|
245
|
+
// NIST signature algorithms -- FIPS 204 ML-DSA + FIPS 205 SLH-DSA share the
|
|
246
|
+
// signature arc 2.16.840.1.101.3.4.3. RFC 9909 sec. 3 assigns the 12 Pure SLH-DSA
|
|
221
247
|
// sets .20-.31 (SHA-2 .20-.25, SHAKE .26-.31) and the 12 pre-hash HashSLH-DSA
|
|
222
248
|
// sets .35-.46, each pairing a parameter set with its message-digest hash. The
|
|
223
249
|
// parameters MUST be absent for every one of them (enforced via paramsMustBeAbsent).
|
|
@@ -236,7 +262,7 @@ var FAMILIES = {
|
|
|
236
262
|
"id-hash-slh-dsa-shake-192s-with-shake256": 43, "id-hash-slh-dsa-shake-192f-with-shake256": 44,
|
|
237
263
|
"id-hash-slh-dsa-shake-256s-with-shake256": 45, "id-hash-slh-dsa-shake-256f-with-shake256": 46 } },
|
|
238
264
|
|
|
239
|
-
// NIST KEM
|
|
265
|
+
// NIST KEM -- FIPS 203 ML-KEM (arc 2.16.840.1.101.3.4.4).
|
|
240
266
|
nistKem: { base: [2, 16, 840, 1, 101, 3, 4, 4], of: {
|
|
241
267
|
"id-ml-kem-512": 1, "id-ml-kem-768": 2, "id-ml-kem-1024": 3 } },
|
|
242
268
|
|
|
@@ -261,7 +287,7 @@ function _isArc(a) {
|
|
|
261
287
|
return typeof a === "number" && Number.isSafeInteger(a) && a >= 0;
|
|
262
288
|
}
|
|
263
289
|
|
|
264
|
-
// Seed the registry family by family
|
|
290
|
+
// Seed the registry family by family -- the built-in set is registered through
|
|
265
291
|
// the exact same primitive an operator uses (registerFamily), so there is one
|
|
266
292
|
// path from a declared family to indexed OIDs and no dotted literals anywhere.
|
|
267
293
|
Object.keys(FAMILIES).forEach(function (fam) {
|
|
@@ -269,11 +295,27 @@ Object.keys(FAMILIES).forEach(function (fam) {
|
|
|
269
295
|
});
|
|
270
296
|
|
|
271
297
|
function _assertDotted(dotted, who) {
|
|
272
|
-
|
|
273
|
-
|
|
298
|
+
// No leading-zero components: "01.2.840" is a key no decoded OID can match,
|
|
299
|
+
// and the arc converters round-trip it to a DIFFERENT OID ("1.2.840").
|
|
300
|
+
if (typeof dotted !== "string" || !/^(0|[1-9]\d*)(\.(0|[1-9]\d*))+$/.test(dotted)) {
|
|
301
|
+
throw new OidError("oid/bad-input", who + ": expected a dotted-decimal OID string (no leading-zero components)");
|
|
274
302
|
}
|
|
275
303
|
}
|
|
276
304
|
|
|
305
|
+
// X.660 encodability: the root arc is 0..2 and, under roots 0 and 1, the
|
|
306
|
+
// second arc is 0..39 (the first two arcs pack into a single octet as
|
|
307
|
+
// 40*X+Y). An OID outside these bounds can never be DER-encoded, so a
|
|
308
|
+
// registration carrying one fails at config time rather than at first use.
|
|
309
|
+
function _assertEncodableArcs(arcs, who) {
|
|
310
|
+
if (arcs.length < 2) {
|
|
311
|
+
throw new OidError("oid/bad-input", who + ": an OID must have at least 2 arcs");
|
|
312
|
+
}
|
|
313
|
+
var root = typeof arcs[0] === "bigint" ? arcs[0] : BigInt(arcs[0]);
|
|
314
|
+
var second = typeof arcs[1] === "bigint" ? arcs[1] : BigInt(arcs[1]);
|
|
315
|
+
if (root > 2n) throw new OidError("oid/bad-arc", who + ": the root arc must be 0, 1, or 2 (X.660)");
|
|
316
|
+
if (root < 2n && second > 39n) throw new OidError("oid/bad-arc", who + ": the second arc must be 0..39 under roots 0 and 1 (X.660)");
|
|
317
|
+
}
|
|
318
|
+
|
|
277
319
|
/**
|
|
278
320
|
* @primitive pki.oid.name
|
|
279
321
|
* @signature pki.oid.name(dotted) -> string | undefined
|
|
@@ -312,10 +354,10 @@ function has(dotted) {
|
|
|
312
354
|
* @spec X.660, RFC 5280
|
|
313
355
|
* @related pki.oid.registerFamily, pki.oid.name
|
|
314
356
|
*
|
|
315
|
-
* Add (or override) an OID
|
|
357
|
+
* Add (or override) an OID -> name mapping so an operator's private or
|
|
316
358
|
* newly-standardized arc resolves through the same registry as the seed
|
|
317
359
|
* set. A later registration of the same OID replaces the forward name;
|
|
318
|
-
* the reverse (name
|
|
360
|
+
* the reverse (name -> OID) keeps the first registration as canonical.
|
|
319
361
|
*
|
|
320
362
|
* @example
|
|
321
363
|
* pki.oid.register("1.3.6.1.4.1.99999.1", "acmeWidgetPolicy");
|
|
@@ -323,6 +365,7 @@ function has(dotted) {
|
|
|
323
365
|
function register(dotted, n) {
|
|
324
366
|
_assertDotted(dotted, "register");
|
|
325
367
|
if (typeof n !== "string" || n.length === 0) throw new OidError("oid/bad-input", "register: name must be a non-empty string");
|
|
368
|
+
_assertEncodableArcs(dotted.split(".").map(BigInt), "register");
|
|
326
369
|
_index(dotted, n);
|
|
327
370
|
}
|
|
328
371
|
|
|
@@ -336,7 +379,7 @@ function register(dotted, n) {
|
|
|
336
379
|
*
|
|
337
380
|
* Register a whole OID family in one call. `base` is the shared arc prefix
|
|
338
381
|
* (the starting variable a class of OIDs has in common) and `members` maps
|
|
339
|
-
* each name to its trailing arc
|
|
382
|
+
* each name to its trailing arc -- a number, or a short arc array for a
|
|
340
383
|
* multi-level leaf. Each full OID is derived as `base` followed by the leaf,
|
|
341
384
|
* so a family is declared as its hierarchy rather than as re-spelled full
|
|
342
385
|
* paths. This is the primitive the built-in seed set itself is built from.
|
|
@@ -367,6 +410,7 @@ function registerFamily(base, members) {
|
|
|
367
410
|
if (!arcs.every(_isArc)) {
|
|
368
411
|
throw new OidError("oid/bad-arc", "registerFamily: member " + JSON.stringify(nm) + " has a non-arc leaf");
|
|
369
412
|
}
|
|
413
|
+
_assertEncodableArcs(arcs, "registerFamily");
|
|
370
414
|
_index(arcs.join("."), nm);
|
|
371
415
|
});
|
|
372
416
|
}
|
|
@@ -377,7 +421,7 @@ function all() {
|
|
|
377
421
|
return out;
|
|
378
422
|
}
|
|
379
423
|
|
|
380
|
-
// toArcs / fromArcs
|
|
424
|
+
// toArcs / fromArcs -- dotted <-> numeric arc array. Arcs come back as
|
|
381
425
|
// Number where safe and BigInt where an arc exceeds 2^53 (rare, but a
|
|
382
426
|
// UUID-based OID arc can), so the round-trip never loses precision.
|
|
383
427
|
function toArcs(dotted) {
|
|
@@ -400,7 +444,7 @@ function fromArcs(arcs) {
|
|
|
400
444
|
}).join(".");
|
|
401
445
|
}
|
|
402
446
|
|
|
403
|
-
// DER convenience
|
|
447
|
+
// DER convenience -- thin pass-throughs to the codec so callers reach for
|
|
404
448
|
// one namespace when they have a dotted string in hand.
|
|
405
449
|
function toDER(dotted) { _assertDotted(dotted, "toDER"); return asn1.build.oid(dotted); }
|
|
406
450
|
function fromDER(input) {
|
|
@@ -409,11 +453,11 @@ function fromDER(input) {
|
|
|
409
453
|
return asn1.read.oid(node);
|
|
410
454
|
}
|
|
411
455
|
|
|
412
|
-
// Algorithm identifiers whose `parameters` field MUST be absent
|
|
456
|
+
// Algorithm identifiers whose `parameters` field MUST be absent -- no explicit
|
|
413
457
|
// NULL, no bytes. The FIPS 204 ML-DSA and FIPS 205 SLH-DSA signature families
|
|
414
|
-
// and the RFC 8410 Edwards / Montgomery curves each carry this MUST: RFC 9909
|
|
415
|
-
// (SLH-DSA in X.509), RFC 9814
|
|
416
|
-
// RFC 8410
|
|
458
|
+
// and the RFC 8410 Edwards / Montgomery curves each carry this MUST: RFC 9909 sec. 3
|
|
459
|
+
// (SLH-DSA in X.509), RFC 9814 sec. 4 (SLH-DSA in CMS), RFC 9881 sec. 2 (ML-DSA in X.509),
|
|
460
|
+
// RFC 8410 sec. 3 (Ed25519 / Ed448 / X25519 / X448). Built by NAME through the same
|
|
417
461
|
// registry every caller uses, so a typo fails closed at load rather than silently
|
|
418
462
|
// dropping a member. One set drives the single shared AlgorithmIdentifier reject
|
|
419
463
|
// (schema-pkix), so every format consumer inherits the rule with no per-format code.
|
|
@@ -424,7 +468,7 @@ var _PARAMS_ABSENT = new Set();
|
|
|
424
468
|
"id-slh-dsa-sha2-192f", "id-slh-dsa-sha2-256s", "id-slh-dsa-sha2-256f",
|
|
425
469
|
"id-slh-dsa-shake-128s", "id-slh-dsa-shake-128f", "id-slh-dsa-shake-192s",
|
|
426
470
|
"id-slh-dsa-shake-192f", "id-slh-dsa-shake-256s", "id-slh-dsa-shake-256f",
|
|
427
|
-
// Pre-hash HashSLH-DSA sets (RFC 9909
|
|
471
|
+
// Pre-hash HashSLH-DSA sets (RFC 9909 sec. 3) -- parameters MUST be absent too.
|
|
428
472
|
"id-hash-slh-dsa-sha2-128s-with-sha256", "id-hash-slh-dsa-sha2-128f-with-sha256",
|
|
429
473
|
"id-hash-slh-dsa-sha2-192s-with-sha512", "id-hash-slh-dsa-sha2-192f-with-sha512",
|
|
430
474
|
"id-hash-slh-dsa-sha2-256s-with-sha512", "id-hash-slh-dsa-sha2-256f-with-sha512",
|
|
@@ -432,7 +476,19 @@ var _PARAMS_ABSENT = new Set();
|
|
|
432
476
|
"id-hash-slh-dsa-shake-192s-with-shake256", "id-hash-slh-dsa-shake-192f-with-shake256",
|
|
433
477
|
"id-hash-slh-dsa-shake-256s-with-shake256", "id-hash-slh-dsa-shake-256f-with-shake256",
|
|
434
478
|
"Ed25519", "Ed448", "X25519", "X448",
|
|
435
|
-
|
|
479
|
+
// FIPS 203 ML-KEM (RFC 9936 sec. 3: PARAMS ARE absent).
|
|
480
|
+
"id-ml-kem-512", "id-ml-kem-768", "id-ml-kem-1024",
|
|
481
|
+
// HKDF key-derivation identifiers (RFC 8619 sec. 2: when any of these appear
|
|
482
|
+
// within AlgorithmIdentifier, the parameters component SHALL be absent).
|
|
483
|
+
"hkdfWithSha256", "hkdfWithSha384", "hkdfWithSha512",
|
|
484
|
+
].forEach(function (nm) {
|
|
485
|
+
var d = byName(nm);
|
|
486
|
+
// A seed-list typo must fail at module load -- admitting undefined would
|
|
487
|
+
// make paramsMustBeAbsent(byName(sameTypo)) return TRUE for every other
|
|
488
|
+
// unregistered name (Set.has(undefined)), a fail-open guard.
|
|
489
|
+
if (typeof d !== "string") throw new OidError("oid/unknown-name", "paramsMustBeAbsent seed: " + JSON.stringify(nm) + " is not a registered name");
|
|
490
|
+
_PARAMS_ABSENT.add(d);
|
|
491
|
+
});
|
|
436
492
|
|
|
437
493
|
/**
|
|
438
494
|
* @primitive pki.oid.paramsMustBeAbsent
|