@blamejs/pki 0.1.22 → 0.1.24

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.
@@ -16,10 +16,10 @@
16
16
  * `{ name, code, message, permanent, isPkiError: true }`.
17
17
  *
18
18
  * `code` is a stable, greppable `domain/reason` string
19
- * (`asn1/indefinite-length`, `x509/not-a-certificate`) safe to switch
19
+ * (`asn1/indefinite-length`, `x509/not-a-certificate`) -- safe to switch
20
20
  * on and safe to log. Because every failure here is a deterministic
21
21
  * verdict on the bytes in hand (a malformed length, an unknown OID
22
- * shape, a truncated certificate), errors are `permanent: true` the
22
+ * shape, a truncated certificate), errors are `permanent: true` -- the
23
23
  * same input will never parse on retry.
24
24
  *
25
25
  * @card
@@ -27,6 +27,10 @@
27
27
  * classes the toolkit throws.
28
28
  */
29
29
 
30
+ // The frozen shape of every error code: a `domain/reason` string of
31
+ // lowercase alphanumerics and dashes.
32
+ var CODE_SHAPE = /^[a-z0-9-]+\/[a-z0-9-]+$/;
33
+
30
34
  /**
31
35
  * @primitive pki.errors.PkiError
32
36
  * @signature new PkiError(message, code)
@@ -36,6 +40,11 @@
36
40
  *
37
41
  * Base class every toolkit error extends. Provides the unified
38
42
  * `instanceof` check plus the `{ name, code, isPkiError }` shape.
43
+ * A supplied `code` must be a `domain/reason` string (lowercase
44
+ * alphanumerics and dashes) -- the construction throws a `TypeError`
45
+ * otherwise, which catches an argument-order swap with the
46
+ * `defineClass` subclasses' `(code, message)` convention at the call
47
+ * site instead of shipping prose into a code-switching consumer.
39
48
  *
40
49
  * @example
41
50
  * try { pki.asn1.decode(bytes); }
@@ -47,7 +56,14 @@ class PkiError extends Error {
47
56
  constructor(message, code) {
48
57
  super(message);
49
58
  this.name = "PkiError";
50
- this.code = code || "pki/invalid";
59
+ var c = code || "pki/invalid";
60
+ if (typeof c !== "string" || !CODE_SHAPE.test(c)) {
61
+ throw new TypeError(
62
+ "PkiError code must be a domain/reason string, got " + String(c) +
63
+ " (PkiError takes (message, code); defineClass subclasses take (code, message))"
64
+ );
65
+ }
66
+ this.code = c;
51
67
  this.isPkiError = true;
52
68
  this.permanent = true;
53
69
  }
@@ -60,13 +76,16 @@ class PkiError extends Error {
60
76
  * @status stable
61
77
  * @spec internal (design: error-class factory)
62
78
  *
63
- * Factory that produces a `PkiError` subclass with the standard shape
79
+ * Factory that produces a `PkiError` subclass with the standard shape --
64
80
  * eliminating the per-domain boilerplate. The returned constructor takes
65
81
  * `(code, message)`, stamps `name`, sets an `is<Name>` flag, and exposes
66
82
  * a `.factory` static for the common `var _err = XxxError.factory` shape.
83
+ * The `code` must be a `domain/reason` string (the base-class contract);
84
+ * without `withCause`, a third constructor argument throws a `TypeError`
85
+ * rather than silently discarding a cause the caller meant to thread.
67
86
  *
68
87
  * @opts
69
- * withCause: boolean, // default: false constructor becomes (code, message, cause)
88
+ * withCause: boolean, // default: false -- constructor becomes (code, message, cause)
70
89
  *
71
90
  * @example
72
91
  * var MyError = pki.errors.defineClass("MyError");
@@ -85,7 +104,11 @@ function defineClass(name, opts) {
85
104
  super(message, code);
86
105
  this.name = name;
87
106
  this[flagKey] = true;
88
- if (withCause && arg3 !== undefined) this.cause = arg3;
107
+ if (withCause) {
108
+ if (arg3 !== undefined) this.cause = arg3;
109
+ } else if (arg3 !== undefined) {
110
+ throw new TypeError(name + " takes (code, message); to thread a cause, define the class with { withCause: true }");
111
+ }
89
112
  }
90
113
  };
91
114
  Object.defineProperty(GeneratedError, "name", { value: name, configurable: true });
@@ -97,105 +120,120 @@ function defineClass(name, opts) {
97
120
 
98
121
  // ---- Per-domain error classes ----
99
122
 
100
- // ConstantsError a bad scale argument to C.TIME.* / C.BYTES.* (an
123
+ // ConstantsError -- a bad scale argument to C.TIME.* / C.BYTES.* (an
101
124
  // authoring bug caught at config time).
102
125
  var ConstantsError = defineClass("ConstantsError");
103
126
 
104
- // Asn1Error malformed / non-canonical DER: truncated TLV, indefinite
127
+ // Asn1Error -- malformed / non-canonical DER: truncated TLV, indefinite
105
128
  // length, non-minimal length or integer, leftover trailing bytes, depth
106
129
  // or size cap exceeded. DER is a canonical encoding, so anything the
107
130
  // decoder rejects is permanently invalid.
108
131
  var Asn1Error = defineClass("Asn1Error");
109
132
 
110
- // OidError a malformed object-identifier: fewer than two arcs, a first
133
+ // OidError -- a malformed object-identifier: fewer than two arcs, a first
111
134
  // arc outside 0..2, a second arc >= 40 under arcs 0/1, or a non-minimal
112
135
  // base-128 sub-identifier.
113
136
  var OidError = defineClass("OidError");
114
137
 
115
- // PemError a malformed PEM envelope: missing / mismatched BEGIN/END
138
+ // PemError -- a malformed PEM envelope: missing / mismatched BEGIN/END
116
139
  // markers, a bad label, or non-base64 body.
117
140
  var PemError = defineClass("PemError");
118
141
 
119
- // CertificateError a byte sequence that is not a well-formed X.509
142
+ // CertificateError -- a byte sequence that is not a well-formed X.509
120
143
  // certificate (wrong outer structure, unparseable field, unsupported
121
144
  // version).
122
145
  var CertificateError = defineClass("CertificateError", { withCause: true });
123
146
 
124
- // CrlError a byte sequence that is not a well-formed X.509 CRL
125
- // (CertificateList / TBSCertList RFC 5280 §5).
147
+ // CrlError -- a byte sequence that is not a well-formed X.509 CRL
148
+ // (CertificateList / TBSCertList -- RFC 5280 sec. 5).
126
149
  var CrlError = defineClass("CrlError", { withCause: true });
127
150
 
128
- // SchemaError the schema-family orchestrator's own errors (input that matches
151
+ // SchemaError -- the schema-family orchestrator's own errors (input that matches
129
152
  // no registered format / does not decode). (code, message) shape like the rest.
130
153
  var SchemaError = defineClass("SchemaError", { withCause: true });
131
154
 
132
- // CsrError a byte sequence that is not a well-formed PKCS#10 CertificationRequest
155
+ // CsrError -- a byte sequence that is not a well-formed PKCS#10 CertificationRequest
133
156
  // (RFC 2986).
134
157
  var CsrError = defineClass("CsrError", { withCause: true });
135
158
 
136
- // Pkcs8Error a byte sequence that is not a well-formed PKCS#8 PrivateKeyInfo /
137
- // OneAsymmetricKey or EncryptedPrivateKeyInfo (RFC 5208 §5, RFC 5958 §23).
159
+ // Pkcs8Error -- a byte sequence that is not a well-formed PKCS#8 PrivateKeyInfo /
160
+ // OneAsymmetricKey or EncryptedPrivateKeyInfo (RFC 5208 sec. 5, RFC 5958 sec. 2/sec. 3).
138
161
  var Pkcs8Error = defineClass("Pkcs8Error", { withCause: true });
139
162
 
140
- // CmsError a byte sequence that is not a well-formed CMS ContentInfo /
163
+ // CmsError -- a byte sequence that is not a well-formed CMS ContentInfo /
141
164
  // SignedData (RFC 5652). Carries the underlying leaf fault as `.cause`.
142
165
  var CmsError = defineClass("CmsError", { withCause: true });
143
166
 
144
- // OcspError a byte sequence that is not a well-formed OCSP request or response
145
- // (OCSPRequest / OCSPResponse RFC 6960 §4). Carries the leaf fault as `.cause`.
167
+ // OcspError -- a byte sequence that is not a well-formed OCSP request or response
168
+ // (OCSPRequest / OCSPResponse -- RFC 6960 sec. 4). Carries the leaf fault as `.cause`.
146
169
  var OcspError = defineClass("OcspError", { withCause: true });
147
170
 
148
- // TspError a byte sequence that is not a well-formed RFC 3161 timestamp token,
171
+ // TspError -- a byte sequence that is not a well-formed RFC 3161 timestamp token,
149
172
  // TSTInfo, or TimeStampResp. Carries the underlying leaf fault as `.cause`.
150
173
  var TspError = defineClass("TspError", { withCause: true });
151
174
 
152
- // AttrCertError a byte sequence that is not a well-formed X.509 Attribute
153
- // Certificate (AttributeCertificate / AttributeCertificateInfo RFC 5755 §4),
175
+ // AttrCertError -- a byte sequence that is not a well-formed X.509 Attribute
176
+ // Certificate (AttributeCertificate / AttributeCertificateInfo -- RFC 5755 sec. 4),
154
177
  // or a recognized-and-deferred legacy AttributeCertificateV1. Carries the
155
178
  // underlying leaf fault as `.cause`.
156
179
  var AttrCertError = defineClass("AttrCertError", { withCause: true });
157
180
 
158
- // CrmfError a byte sequence that is not a well-formed RFC 4211 CertReqMessages
181
+ // CrmfError -- a byte sequence that is not a well-formed RFC 4211 CertReqMessages
159
182
  // / CertReqMsg / CertRequest / CertTemplate. Carries the underlying leaf fault as
160
183
  // `.cause`.
161
184
  var CrmfError = defineClass("CrmfError", { withCause: true });
162
185
 
163
- // Pkcs12Error a byte sequence that is not a well-formed RFC 7292 PFX
164
- // (AuthenticatedSafe / SafeContents / SafeBag), or a PFX violating a §4
186
+ // Pkcs12Error -- a byte sequence that is not a well-formed RFC 7292 PFX
187
+ // (AuthenticatedSafe / SafeContents / SafeBag), or a PFX violating a sec. 4
165
188
  // coherence rule (version, integrity mode, bag dispatch, MacData). Carries
166
189
  // the underlying leaf fault as `.cause`.
167
190
  var Pkcs12Error = defineClass("Pkcs12Error", { withCause: true });
168
191
 
169
- // CmpError a byte sequence that is not a well-formed RFC 9810 PKIMessage
170
- // (PKIHeader / PKIBody / protection / extraCerts), or one violating a §5
171
- // coherence rule (protectionprotectionAlg, certConf-hashAlgpvno). Carries
192
+ // CmpError -- a byte sequence that is not a well-formed RFC 9810 PKIMessage
193
+ // (PKIHeader / PKIBody / protection / extraCerts), or one violating a sec. 5
194
+ // coherence rule (protection<=>protectionAlg, certConf-hashAlg<=>pvno). Carries
172
195
  // the underlying leaf fault as `.cause`.
173
196
  var CmpError = defineClass("CmpError", { withCause: true });
174
197
 
175
- // PathError a certification path that fails RFC 5280 §6 validation, or a
198
+ // PathError -- a certification path that fails RFC 5280 sec. 6 validation, or a
176
199
  // malformed input handed to the validator (an extension value that does not
177
200
  // decode, an empty path, an unsupported signature algorithm). Carries the
178
201
  // per-check reason in `.code` (`path/*`) and the underlying leaf fault as
179
202
  // `.cause`.
180
203
  var PathError = defineClass("PathError", { withCause: true });
181
204
 
182
- // SmimeError a byte sequence that is not a well-formed RFC 5035 ESS
205
+ // SmimeError -- a byte sequence that is not a well-formed RFC 5035 ESS
183
206
  // signing-certificate attribute (SigningCertificate / SigningCertificateV2 /
184
207
  // ESSCertID(v2) / IssuerSerial) or RFC 8551 SMIMECapabilities, or a CMS
185
- // attribute violating a §2.5 coherence rule (single-AttributeValue, certs
208
+ // attribute violating a sec. 2.5 coherence rule (single-AttributeValue, certs
186
209
  // non-empty, non-canonical DEFAULT hashAlgorithm). Carries the underlying leaf
187
210
  // fault (e.g. the inner asn1/* decode error) as `.cause`.
188
211
  var SmimeError = defineClass("SmimeError", { withCause: true });
189
212
 
190
- // CtError a byte sequence that is not a well-formed RFC 6962 Certificate
213
+ // CtError -- a byte sequence that is not a well-formed RFC 6962 Certificate
191
214
  // Transparency SCT list: a malformed inner DER OCTET-STRING wrap, or a TLS
192
215
  // presentation-language framing violation (a lying vector length, a field read
193
216
  // past its bound, a truncated element). An SCT whose version this parser does
194
- // not define is NOT an error RFC 6962 §3.3 makes unknown versions skippable,
217
+ // not define is NOT an error -- RFC 6962 sec. 3.3 makes unknown versions skippable,
195
218
  // so they are preserved opaque. Carries the underlying leaf fault (e.g. the
196
219
  // inner `asn1/*` decode error) as `.cause`.
197
220
  var CtError = defineClass("CtError", { withCause: true });
198
221
 
222
+ // CsrattrsError -- a byte sequence that is not a well-formed RFC 8951 sec. 3.5
223
+ // CsrAttrs (SEQUENCE OF AttrOrOID), or one violating an RFC 9908 semantic rule
224
+ // (a repeated id-ExtensionReq, an extension-request values SET that is not
225
+ // exactly one Extensions, a template version other than v1(0), a mixed
226
+ // extension-request template). Carries the underlying leaf fault as `.cause`.
227
+ var CsrattrsError = defineClass("CsrattrsError", { withCause: true });
228
+
229
+ // EstError -- an RFC 7030 / 8951 / 9908 Enrollment-over-Secure-Transport
230
+ // protocol fault: a payload that fails a per-operation validator (a non-certs-
231
+ // only /cacerts response, a serverkeygen recipient-arm mismatch), a transfer /
232
+ // multipart framing violation, or an HTTP response the classifier rejects.
233
+ // Carries the underlying leaf / delegated fault (e.g. a cms/* or asn1/*) as
234
+ // `.cause`.
235
+ var EstError = defineClass("EstError", { withCause: true });
236
+
199
237
  module.exports = {
200
238
  PkiError: PkiError,
201
239
  defineClass: defineClass,
@@ -218,4 +256,6 @@ module.exports = {
218
256
  PathError: PathError,
219
257
  CtError: CtError,
220
258
  SmimeError: SmimeError,
259
+ CsrattrsError: CsrattrsError,
260
+ EstError: EstError,
221
261
  };