Skip to content

X.509 证书解析 ​

sm-crypto-wasm/x509 提供只读的国密证书解析与单证书验签:

  • 解析 DER / PEM / base64 / hex 证书;
  • 读取版本、序列号、签发者/主体、有效期、公钥、扩展;
  • 用签发者公钥验证单张证书的签名;
  • 计算 SM3 / SHA-256 指纹。

不提供证书链路径校验、策略校验、名称约束、CRL / OCSP / AIA 拉取。 需要链校验时,请按 issuer / authorityKeyIdentifier 自己逐级调用 verifySignature()。

解析 ​

ts
import { parseCertificate, parseCertificates } from 'sm-crypto-wasm/x509';

const cert = parseCertificate(pem);

cert.version;              // 1 | 2 | 3
cert.serialNumber;         // bigint
cert.serialNumberHex;      // '1003'
cert.issuer.toString();    // 'C=CN,O=Example,CN=Example CA'
cert.subject.commonName;   // 'server.example.test'
cert.validity.notBefore;   // Date(精度到秒)
cert.publicKeyAlgorithm;   // 'SM2' | 'RSA' | 'UNKNOWN'
cert.supported;            // 本库能否使用该公钥
cert.subjectPublicKey;     // 裸公钥;SM2 为 65 字节 04 || X || Y

// PEM bundle 或连续 DER
const chain = parseCertificates(bundle);

扩展 ​

常用扩展解析为便捷字段;未知扩展保留 OID + critical + 原始值:

ts
cert.basicConstraints;      // { ca: true, pathLen: 2 }
cert.keyUsage;              // { digitalSignature, keyCertSign, ... }
cert.subjectAltNames;       // [{ type: 'dns' | 'ip' | 'email' | 'uri', value }]
cert.extendedKeyUsage;      // ['1.3.6.1.5.5.7.3.1']
cert.subjectKeyIdentifier;  // Uint8Array
cert.authorityKeyIdentifier;// { keyIdentifier?, authorityCertSerialNumber? }

cert.getExtension('1.2.3.4'); // Extension | undefined

有效期与验签 ​

ts
cert.checkValidity();                 // 当前是否在有效期内
cert.checkValidity(new Date('2030-01-01T00:00:00Z'));

const ok = cert.verifySignature(caCertificate);

verifySignature() 接受三种签发者输入:

  • 本库解析的 Certificate;
  • DER / PEM 证书字节;
  • 裸公钥(64 或 65 字节)。

SM2 用户标识:

  • GM/T 证书使用默认标识 1234567812345678;
  • OpenSSL 的 X.509 路径默认使用空标识;
  • 省略 userID 时先按默认标识验证,失败后按空标识重试:
ts
cert.verifySignature(ca, { userID: new Uint8Array(0) }); // 显式指定

签发 ​

ts
import { sm2, sm3 } from 'sm-crypto-wasm';
import { createSelfSignedCertificate, issueCertificate, parseDistinguishedName } from 'sm-crypto-wasm/x509';

await sm2.ensureLoaded();
await sm3.ensureLoaded();                 // 默认 SKI 使用 SM3

const caKeys = await sm2.generateKeyPair();
const ca = createSelfSignedCertificate({
  subject: parseDistinguishedName('C=CN,O=Example,CN=Example CA'),
  privateKey: caKeys.privateKeyPem,
  notAfter: new Date('2035-01-01T00:00:00Z'),
  basicConstraints: { ca: true, pathLen: 1 },
  keyUsage: ['keyCertSign', 'cRLSign'],
});

const leafKeys = await sm2.generateKeyPair();
const leaf = issueCertificate({
  subject: { commonName: 'server.example.test' },
  subjectPublicKey: leafKeys.publicKeyPem, // CA 签发时必填
  notAfter: new Date('2030-01-01T00:00:00Z'),
  basicConstraints: { ca: false },
  keyUsage: ['digitalSignature', 'keyEncipherment'],
  extendedKeyUsage: ['1.3.6.1.5.5.7.3.1'],
  subjectAltNames: [{ type: 'dns', value: 'server.example.test' }],
  signer: { privateKey: caKeys.privateKeyPem, certificate: ca.certificate },
});

约束:

  • 版本固定 v3;
  • ca=false 不能带 keyCertSign;pathLen 仅 CA 可用;
  • 非 CA 证书(basicConstraints.ca !== true)不能作为签发者;
  • 序列号必须为正整数,默认生成 16 字节随机数(最高位清零);
  • SAN 的 DNS/email/URI 必须为 ASCII,IP 必须是合法 IPv4/IPv6。

SM2 用户标识:

  • 默认空标识(与 OpenSSL 的 X.509 路径一致,openssl verify 可直接验证);
  • GM/T 默认标识:userID: DEFAULT_SM2_USER_ID。
ts
import { DEFAULT_SM2_USER_ID } from 'sm-crypto-wasm/x509';

createSelfSignedCertificate({ ..., userID: DEFAULT_SM2_USER_ID });

SKI:

  • 默认 SM3(公钥) 前 20 字节;
  • subjectKeyIdentifier: { hash: 'sha1' } 兼容 OpenSSL 的 hash 算法;
  • AKI 自签时等于 SKI,CA 签发时取签发者证书的 SKI。

本模块不生成密钥、不管理私钥。

指纹 ​

ts
cert.fingerprint();          // SM3(32 字节 hex)
cert.fingerprint('sha256');  // SHA-256(内置纯 JS 实现)

SM3 指纹需要先预热 SM3 wasm:

ts
import { sm3 } from 'sm-crypto-wasm';
await sm3.ensureLoaded();

错误处理 ​

证书结构、截断、尾部多余字节等问题统一抛 CertificateError:

ts
import { CertificateError } from 'sm-crypto-wasm/x509';

try {
  parseCertificate(input);
} catch (e) {
  if (e instanceof CertificateError) { /* 非证书 / 结构非法 */ }
}

未知扩展、未知算法、未知 Name 属性和 RSA 证书不会抛错:

  • 未知内容保留原始值;
  • RSA 证书正常解析字段,但 supported === false,verifySignature() 返回 false。

范围 ​

能力状态
DER / PEM / base64 / hex 解析✅
KeyUsage / BasicConstraints / SAN / SKI / AKI / EKU✅
单证书 SM2 验签(GM/T + OpenSSL 用户标识)✅
SM3 / SHA-256 指纹✅
证书链路径校验❌
CRL / OCSP / AIA❌

以 Apache-2.0 许可发布