S/MIME (ESS)

S/MIME Enhanced Security Services signed-attribute values per RFC 5035 (ESS) and RFC 8551 (S/MIME 4.0). These are the DER-decoded VALUES of CMS signed attributes -- they ride inside a SignerInfo.signedAttrs, so this is a companion decoder a CMS consumer invokes by attribute OID, NOT a top-level format the schema orchestrator auto-routes.

parseSigningCertificate / parseSigningCertificateV2 decode the ESS signing-certificate attributes that bind a signature to the exact certificate that made it: each surfaces its list of ESSCertID(v2) -- the certificate hash (raw), the hash algorithm (decoded for v2, or the implied SHA-1 for v1), and the optional issuerSerial (issuer GeneralNames validated + surfaced raw, serial as a BigInt + hex) -- plus the optional certificate policies. parseSmimeCapabilities decodes the ordered SMIMECapabilities list (each a capability OID + raw parameters). decodeAttribute takes a CMS-shaped { type, values } attribute, enforces the single-AttributeValue rule (RFC 8551 sec. 2.5.2), routes on the attribute OID, and recognize-and-defers an unknown attribute type with its raw values intact.

Structure is decoded; verification is the consumer's -- the parser surfaces certHash + hashAlgorithm + issuerSerial so a verifier recomputes the certificate hash (compose webcrypto) and matches the issuer/serial against the actual signing certificate; it never recomputes a hash or trusts a cert. Whether an attribute is correctly placed in signedAttrs (vs unsignedAttrs) is the CMS consumer's knowledge. DER-only, fail-closed.

pki.schema.smime.parseSigningCertificate

since 0.1.22 experimental
pki.schema.smime.parseSigningCertificate(der) -> { certs, policies }

Decode an ESS v1 SigningCertificate attribute value (RFC 5035 sec. 5.4.2) -- the raw AttributeValue a CMS consumer plucks off SignerInfo.signedAttrs. Returns { certs, policies }: each certs entry is { certHash, hashAlgorithm, issuerSerial } in wire order (the first is the signing certificate), where hashAlgorithm is the implied SHA-1 (v1 carries no algorithm field) and issuerSerial (or null) surfaces the issuer GeneralNames + serial. Throws a typed smime/* (or leaf asn1/*) error on malformed input.

Example

var b = pki.asn1.build;
var essCertId = b.sequence([b.octetString(Buffer.alloc(20, 1))]);   // SHA-1 hash, no issuerSerial
var av = b.sequence([b.sequence([essCertId])]);                     // SigningCertificate { certs }
var sc = pki.schema.smime.parseSigningCertificate(av);
sc.certs[0].hashAlgorithm.name;    // "sha1" (implied)

References

pki.schema.smime.parseSigningCertificateV2

since 0.1.22 experimental
pki.schema.smime.parseSigningCertificateV2(der) -> { certs, policies }

Decode an ESS v2 SigningCertificateV2 attribute value (RFC 5035 sec. 5.4.1). Identical shape to v1 but each certs entry carries a real hashAlgorithm: decoded when present, or the RFC 5035 sec. 4 default id-sha256 (with defaulted: true) when omitted. An explicit hashAlgorithm byte-equal to that default is a non-canonical DER encoding and is rejected smime/non-canonical-default (X.690 sec. 11.5). Throws a typed smime/* error on malformed input.

Example

var b = pki.asn1.build;
var essCertId = b.sequence([b.octetString(Buffer.alloc(32, 2))]);   // hashAlgorithm defaulted
var av = b.sequence([b.sequence([essCertId])]);
var sc = pki.schema.smime.parseSigningCertificateV2(av);
sc.certs[0].hashAlgorithm.defaulted;   // true (SHA-256 default)

References

pki.schema.smime.parseSmimeCapabilities

since 0.1.22 experimental
pki.schema.smime.parseSmimeCapabilities(der) -> { capabilities }

Decode an SMIMECapabilities attribute value (RFC 8551 sec. 2.5.2) into { capabilities } -- an ORDERED list (preference order, never sorted), each { capabilityID, name, parameters } with parameters the raw ANY DEFINED BY capabilityID bytes (or null). Throws a typed smime/* error on malformed input.

Example

var b = pki.asn1.build;
var cap = b.sequence([b.oid(pki.oid.byName("aes256-CBC"))]);
var caps = pki.schema.smime.parseSmimeCapabilities(b.sequence([cap]));
caps.capabilities[0].name;    // "aes256-CBC"

References

pki.schema.smime.decodeAttribute

since 0.1.22 experimental
pki.schema.smime.decodeAttribute(attr) -> { kind, ... }

OID-dispatch convenience over the three value decoders for a CMS-shaped { type, values } attribute (the shape cms.parse surfaces on signerInfos[i].signedAttrs). Enforces the single-AttributeValue rule (RFC 8551 sec. 2.5.2 / sec. 2.5) -- a values length other than 1 is rejected smime/multi-valued-attribute -- then routes on attr.type: signingCertificate / signingCertificateV2 / smimeCapabilities decode to { kind, ...result }; any other type is recognize-and-deferred smime/unsupported-attribute (its type, registry name, and raw values carried on the error so a caller keeps the bytes).

Example

var b = pki.asn1.build;
var essCertId = b.sequence([b.octetString(Buffer.alloc(32, 2))]);   // ESSCertIDv2, hashAlgorithm defaulted
var av = b.sequence([b.sequence([essCertId])]);                     // SigningCertificateV2 { certs: [ ESSCertIDv2 ] }
var got = pki.schema.smime.decodeAttribute({ type: pki.oid.byName("signingCertificateV2"), values: [av] });
got.kind;    // "signingCertificateV2"

References