@blamejs/pki 0.1.22 → 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 +35 -0
- package/README.md +16 -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 +57 -34
- package/lib/oid.js +110 -59
- package/lib/path-validate.js +302 -135
- package/lib/schema-all.js +49 -41
- 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 +283 -100
- package/lib/schema-smime.js +39 -39
- 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,27 +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,
|
|
145
|
-
friendlyName: 20, localKeyId: 21 } },
|
|
144
|
+
countersignature: 6, challengePassword: 7, extensionRequest: 14,
|
|
145
|
+
smimeCapabilities: 15, friendlyName: 20, localKeyId: 21 } },
|
|
146
146
|
|
|
147
|
-
// 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).
|
|
148
148
|
pkcs9CertTypes: { base: [1, 2, 840, 113549, 1, 9, 22], of: { x509Certificate: 1, sdsiCertificate: 2 } },
|
|
149
149
|
pkcs9CrlTypes: { base: [1, 2, 840, 113549, 1, 9, 23], of: { x509CRL: 1 } },
|
|
150
150
|
|
|
151
151
|
// PKCS#5 password-based schemes (RFC 8018) + the PBMAC1 MacData arm (RFC 9579).
|
|
152
152
|
pkcs5: { base: [1, 2, 840, 113549, 1, 5], of: { pbkdf2: 12, pbes2: 13, pbmac1: 14 } },
|
|
153
153
|
|
|
154
|
-
// CMP InfoTypeAndValue types
|
|
154
|
+
// CMP InfoTypeAndValue types -- id-it under id-pkix (RFC 9810 sec. 5.3.19; the
|
|
155
155
|
// PKIXCMP-2023 module assigns these leaves, 8/9 unassigned).
|
|
156
156
|
idIt: { base: [1, 3, 6, 1, 5, 5, 7, 4], of: {
|
|
157
157
|
caProtEncCert: 1, signKeyPairTypes: 2, encKeyPairTypes: 3, preferredSymmAlg: 4,
|
|
@@ -162,15 +162,15 @@ var FAMILIES = {
|
|
|
162
162
|
crls: 23, kemCiphertextInfo: 24 } },
|
|
163
163
|
|
|
164
164
|
// CMP message-protection MAC algorithms on the Entrust arc (RFC 9810
|
|
165
|
-
//
|
|
165
|
+
// sec. 5.1.3.1/.2/.4; RFC 9481 sec. 6.1.1).
|
|
166
166
|
entrustAlg: { base: [1, 2, 840, 113533, 7, 66], of: {
|
|
167
167
|
passwordBasedMac: 13, kemBasedMac: 16, dhBasedMac: 30 } },
|
|
168
168
|
|
|
169
|
-
// PKCS#12 bag types (RFC 7292
|
|
169
|
+
// PKCS#12 bag types (RFC 7292 sec. 4.2, Appendix D).
|
|
170
170
|
pkcs12BagTypes: { base: [1, 2, 840, 113549, 1, 12, 10, 1], of: {
|
|
171
171
|
keyBag: 1, pkcs8ShroudedKeyBag: 2, certBag: 3, crlBag: 4, secretBag: 5, safeContentsBag: 6 } },
|
|
172
172
|
|
|
173
|
-
// PKCS#12 password-based encryption schemes (RFC 7292 Appendix C)
|
|
173
|
+
// PKCS#12 password-based encryption schemes (RFC 7292 Appendix C) -- legacy
|
|
174
174
|
// PBE identifiers still emitted by deployed exporters; recognized so a
|
|
175
175
|
// shrouded bag's algorithm resolves to a name, never decrypted here.
|
|
176
176
|
pkcs12Pbe: { base: [1, 2, 840, 113549, 1, 12, 1], of: {
|
|
@@ -178,17 +178,37 @@ var FAMILIES = {
|
|
|
178
178
|
"pbeWithSHAAnd3-KeyTripleDES-CBC": 3, "pbeWithSHAAnd2-KeyTripleDES-CBC": 4,
|
|
179
179
|
"pbeWithSHAAnd128BitRC2-CBC": 5, "pbeWithSHAAnd40BitRC2-CBC": 6 } },
|
|
180
180
|
|
|
181
|
-
// RSADSI digest / HMAC algorithms (RFC 8018
|
|
181
|
+
// RSADSI digest / HMAC algorithms (RFC 8018 sec. B.1) -- the PBKDF2 / PBMAC1 PRFs.
|
|
182
182
|
rsadsiDigest: { base: [1, 2, 840, 113549, 2], of: {
|
|
183
183
|
hmacWithSHA1: 7, hmacWithSHA224: 8, hmacWithSHA256: 9,
|
|
184
184
|
hmacWithSHA384: 10, hmacWithSHA512: 11 } },
|
|
185
185
|
|
|
186
186
|
// S/MIME content types on the PKCS#9 smime arc (RFC 5652, RFC 3161): id-ct.
|
|
187
|
-
|
|
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 } },
|
|
188
208
|
|
|
189
209
|
// S/MIME authenticated attributes (id-aa, RFC 2634 / RFC 5035 / RFC 5816). The ESS
|
|
190
210
|
// signing-certificate attributes bind a CMS / TSP SignerInfo to its signing cert;
|
|
191
|
-
// 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).
|
|
192
212
|
// The RFC 2634 originals (receiptRequest .. contentReference) are name-only: they
|
|
193
213
|
// resolve to a name so an unsupported-attribute diagnostic is legible, not decoded.
|
|
194
214
|
smimeAa: { base: [1, 2, 840, 113549, 1, 9, 16, 2], of: {
|
|
@@ -207,22 +227,23 @@ var FAMILIES = {
|
|
|
207
227
|
// Edwards / Montgomery curves (RFC 8410).
|
|
208
228
|
edwards: { base: [1, 3, 101], of: { X25519: 110, X448: 111, Ed25519: 112, Ed448: 113 } },
|
|
209
229
|
|
|
210
|
-
// 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;
|
|
211
231
|
// nistHash covers only SHA-256 and above.
|
|
212
232
|
oiwSecsig: { base: [1, 3, 14, 3, 2], of: { sha1: 26 } },
|
|
213
233
|
|
|
214
|
-
// 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
|
|
215
235
|
// modern PBES2 / CMS content ciphers a PKCS#12 or EnvelopedData names.
|
|
216
236
|
nistAes: { base: [2, 16, 840, 1, 101, 3, 4, 1], of: {
|
|
217
|
-
"aes128-CBC": 2, "aes128-
|
|
218
|
-
"
|
|
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 } },
|
|
219
240
|
|
|
220
241
|
// NIST hash functions (SHA-2, SHA-3, SHAKE).
|
|
221
242
|
nistHash: { base: [2, 16, 840, 1, 101, 3, 4, 2], of: {
|
|
222
243
|
sha256: 1, sha384: 2, sha512: 3, "sha3-256": 8, "sha3-512": 10, shake256: 12 } },
|
|
223
244
|
|
|
224
|
-
// NIST signature algorithms
|
|
225
|
-
// 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
|
|
226
247
|
// sets .20-.31 (SHA-2 .20-.25, SHAKE .26-.31) and the 12 pre-hash HashSLH-DSA
|
|
227
248
|
// sets .35-.46, each pairing a parameter set with its message-digest hash. The
|
|
228
249
|
// parameters MUST be absent for every one of them (enforced via paramsMustBeAbsent).
|
|
@@ -241,7 +262,7 @@ var FAMILIES = {
|
|
|
241
262
|
"id-hash-slh-dsa-shake-192s-with-shake256": 43, "id-hash-slh-dsa-shake-192f-with-shake256": 44,
|
|
242
263
|
"id-hash-slh-dsa-shake-256s-with-shake256": 45, "id-hash-slh-dsa-shake-256f-with-shake256": 46 } },
|
|
243
264
|
|
|
244
|
-
// NIST KEM
|
|
265
|
+
// NIST KEM -- FIPS 203 ML-KEM (arc 2.16.840.1.101.3.4.4).
|
|
245
266
|
nistKem: { base: [2, 16, 840, 1, 101, 3, 4, 4], of: {
|
|
246
267
|
"id-ml-kem-512": 1, "id-ml-kem-768": 2, "id-ml-kem-1024": 3 } },
|
|
247
268
|
|
|
@@ -266,7 +287,7 @@ function _isArc(a) {
|
|
|
266
287
|
return typeof a === "number" && Number.isSafeInteger(a) && a >= 0;
|
|
267
288
|
}
|
|
268
289
|
|
|
269
|
-
// Seed the registry family by family
|
|
290
|
+
// Seed the registry family by family -- the built-in set is registered through
|
|
270
291
|
// the exact same primitive an operator uses (registerFamily), so there is one
|
|
271
292
|
// path from a declared family to indexed OIDs and no dotted literals anywhere.
|
|
272
293
|
Object.keys(FAMILIES).forEach(function (fam) {
|
|
@@ -274,11 +295,27 @@ Object.keys(FAMILIES).forEach(function (fam) {
|
|
|
274
295
|
});
|
|
275
296
|
|
|
276
297
|
function _assertDotted(dotted, who) {
|
|
277
|
-
|
|
278
|
-
|
|
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)");
|
|
279
302
|
}
|
|
280
303
|
}
|
|
281
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
|
+
|
|
282
319
|
/**
|
|
283
320
|
* @primitive pki.oid.name
|
|
284
321
|
* @signature pki.oid.name(dotted) -> string | undefined
|
|
@@ -317,10 +354,10 @@ function has(dotted) {
|
|
|
317
354
|
* @spec X.660, RFC 5280
|
|
318
355
|
* @related pki.oid.registerFamily, pki.oid.name
|
|
319
356
|
*
|
|
320
|
-
* Add (or override) an OID
|
|
357
|
+
* Add (or override) an OID -> name mapping so an operator's private or
|
|
321
358
|
* newly-standardized arc resolves through the same registry as the seed
|
|
322
359
|
* set. A later registration of the same OID replaces the forward name;
|
|
323
|
-
* the reverse (name
|
|
360
|
+
* the reverse (name -> OID) keeps the first registration as canonical.
|
|
324
361
|
*
|
|
325
362
|
* @example
|
|
326
363
|
* pki.oid.register("1.3.6.1.4.1.99999.1", "acmeWidgetPolicy");
|
|
@@ -328,6 +365,7 @@ function has(dotted) {
|
|
|
328
365
|
function register(dotted, n) {
|
|
329
366
|
_assertDotted(dotted, "register");
|
|
330
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");
|
|
331
369
|
_index(dotted, n);
|
|
332
370
|
}
|
|
333
371
|
|
|
@@ -341,7 +379,7 @@ function register(dotted, n) {
|
|
|
341
379
|
*
|
|
342
380
|
* Register a whole OID family in one call. `base` is the shared arc prefix
|
|
343
381
|
* (the starting variable a class of OIDs has in common) and `members` maps
|
|
344
|
-
* each name to its trailing arc
|
|
382
|
+
* each name to its trailing arc -- a number, or a short arc array for a
|
|
345
383
|
* multi-level leaf. Each full OID is derived as `base` followed by the leaf,
|
|
346
384
|
* so a family is declared as its hierarchy rather than as re-spelled full
|
|
347
385
|
* paths. This is the primitive the built-in seed set itself is built from.
|
|
@@ -372,6 +410,7 @@ function registerFamily(base, members) {
|
|
|
372
410
|
if (!arcs.every(_isArc)) {
|
|
373
411
|
throw new OidError("oid/bad-arc", "registerFamily: member " + JSON.stringify(nm) + " has a non-arc leaf");
|
|
374
412
|
}
|
|
413
|
+
_assertEncodableArcs(arcs, "registerFamily");
|
|
375
414
|
_index(arcs.join("."), nm);
|
|
376
415
|
});
|
|
377
416
|
}
|
|
@@ -382,7 +421,7 @@ function all() {
|
|
|
382
421
|
return out;
|
|
383
422
|
}
|
|
384
423
|
|
|
385
|
-
// toArcs / fromArcs
|
|
424
|
+
// toArcs / fromArcs -- dotted <-> numeric arc array. Arcs come back as
|
|
386
425
|
// Number where safe and BigInt where an arc exceeds 2^53 (rare, but a
|
|
387
426
|
// UUID-based OID arc can), so the round-trip never loses precision.
|
|
388
427
|
function toArcs(dotted) {
|
|
@@ -405,7 +444,7 @@ function fromArcs(arcs) {
|
|
|
405
444
|
}).join(".");
|
|
406
445
|
}
|
|
407
446
|
|
|
408
|
-
// DER convenience
|
|
447
|
+
// DER convenience -- thin pass-throughs to the codec so callers reach for
|
|
409
448
|
// one namespace when they have a dotted string in hand.
|
|
410
449
|
function toDER(dotted) { _assertDotted(dotted, "toDER"); return asn1.build.oid(dotted); }
|
|
411
450
|
function fromDER(input) {
|
|
@@ -414,11 +453,11 @@ function fromDER(input) {
|
|
|
414
453
|
return asn1.read.oid(node);
|
|
415
454
|
}
|
|
416
455
|
|
|
417
|
-
// Algorithm identifiers whose `parameters` field MUST be absent
|
|
456
|
+
// Algorithm identifiers whose `parameters` field MUST be absent -- no explicit
|
|
418
457
|
// NULL, no bytes. The FIPS 204 ML-DSA and FIPS 205 SLH-DSA signature families
|
|
419
|
-
// and the RFC 8410 Edwards / Montgomery curves each carry this MUST: RFC 9909
|
|
420
|
-
// (SLH-DSA in X.509), RFC 9814
|
|
421
|
-
// 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
|
|
422
461
|
// registry every caller uses, so a typo fails closed at load rather than silently
|
|
423
462
|
// dropping a member. One set drives the single shared AlgorithmIdentifier reject
|
|
424
463
|
// (schema-pkix), so every format consumer inherits the rule with no per-format code.
|
|
@@ -429,7 +468,7 @@ var _PARAMS_ABSENT = new Set();
|
|
|
429
468
|
"id-slh-dsa-sha2-192f", "id-slh-dsa-sha2-256s", "id-slh-dsa-sha2-256f",
|
|
430
469
|
"id-slh-dsa-shake-128s", "id-slh-dsa-shake-128f", "id-slh-dsa-shake-192s",
|
|
431
470
|
"id-slh-dsa-shake-192f", "id-slh-dsa-shake-256s", "id-slh-dsa-shake-256f",
|
|
432
|
-
// Pre-hash HashSLH-DSA sets (RFC 9909
|
|
471
|
+
// Pre-hash HashSLH-DSA sets (RFC 9909 sec. 3) -- parameters MUST be absent too.
|
|
433
472
|
"id-hash-slh-dsa-sha2-128s-with-sha256", "id-hash-slh-dsa-sha2-128f-with-sha256",
|
|
434
473
|
"id-hash-slh-dsa-sha2-192s-with-sha512", "id-hash-slh-dsa-sha2-192f-with-sha512",
|
|
435
474
|
"id-hash-slh-dsa-sha2-256s-with-sha512", "id-hash-slh-dsa-sha2-256f-with-sha512",
|
|
@@ -437,7 +476,19 @@ var _PARAMS_ABSENT = new Set();
|
|
|
437
476
|
"id-hash-slh-dsa-shake-192s-with-shake256", "id-hash-slh-dsa-shake-192f-with-shake256",
|
|
438
477
|
"id-hash-slh-dsa-shake-256s-with-shake256", "id-hash-slh-dsa-shake-256f-with-shake256",
|
|
439
478
|
"Ed25519", "Ed448", "X25519", "X448",
|
|
440
|
-
|
|
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
|
+
});
|
|
441
492
|
|
|
442
493
|
/**
|
|
443
494
|
* @primitive pki.oid.paramsMustBeAbsent
|