如何在NodeJS中提取ASN.1格式的证书主题属性值?
问题描述
可以通过以下OpenSSL命令直接在命令行打印ASN.1格式的证书主题:
openssl x509 -subject -noout -nameopt rfc2253 -nameopt dump_all -nameopt oid -nameopt sep_multiline -in mycertificate.cer
对应的证书内容:
-----BEGIN CERTIFICATE----- MIIG6jCCBdKgAwIBAgIUMp1HU0W7iInXwAKycQieXr3Nl24wDQYJKoZIhvcNAQEL BQAwcTELMAkGA1UEBhMCQlIxHDAaBgNVBAoTE09wZW4gQmFua2luZyBCcmFzaWwx FTATBgNVBAsTDE9wZW4gQmFua2luZzEtMCsGA1UEAxMkT3BlbiBCYW5raW5nIFNB TkRCT1ggSXNzdWluZyBDQSAtIEcxMB4XDTIyMDkyOTEyNDMwMFoXDTIzMTAyOTEy NDMwMFowggEPMQswCQYDVQQGEwJCUjELMAkGA1UECBMCUkoxDzANBgNVBAcTBkxP TkRPTjEcMBoGA1UEChMTT3BlbiBCYW5raW5nIEJyYXNpbDEMMAoGA1UEAxMDdHBw MRcwFQYDVQQFEw40MzE0MjY2NjAwMDE5NzEdMBsGA1UEDxMUUHJpdmF0ZSBPcmdh bml6YXRpb24xEzARBgsrBgEEAYI3PAIBAxMCVUsxMzAxBgNVBGETKk9GQkJSLTc0 ZTkyOWQ5LTMzYjYtNGQ4NS04YmE3LWMxNDZjODY3YTgxNzE0MDIGCgmSJomT8ixk AQETJDcyMThlMWFmLTE5NWYtNDJiNS1hNDRiLThjNzgyODQ3MGY1YTCCASIwDQYJ KoZIhvcNAQEBBQADggEPADCCAQoCggEBANRjfdZJaqwfRB3IOL0OPpNaH6jqU97T iNiOWDYN8sd/ZVFqPMgAPBiIczLSfgYon9dj2p8emHGFr/IIwFP1uQyASwcGotGS 6yLLvtAqTWUqlrKEQRL/70AHYOrGYFHxG0s9228Xw1fn70Dm2FibC9t/Y2+HheKL t0yqOtPTRMn4jRS2bOJ9u23YBG+k6a2t5iO05eIOYEFkGaOuJKxJlnLqyB7kM57c 9y38JLBDFiEKETNoyubhwsPk+3rAyAwonin0OiejLvH5jzwWMMWZJD3JtWCbKl3/ NTaxKdnsd7ZoURghYNJObALBS6hjcKCM0tS5CiehYmFNAyu9cPNbuZUCAwEAAaOC AtgwggLUMAwGA1UdEwEB/wQCMAAwHQYDVR0OBBYEFIrCpV3lc3CZadaUV70hKRXe B3k5MB8GA1UdIwQYMBaAFIZ/WK0X9YK2TrQFs/uwzhFD30y+MEwGCCsGAQUFBwEB BEAwPjA8BggrBgEFBQcwAYYwaHR0cDovL29jc3Auc2FuZGJveC5wa2kub3BlbmJh bmtpbmdicmFzaWwub3JnLmJyMEsGA1UdHwREMEIwQKA+oDyGOmh0dHA6Ly9jcmwu c2FuZGJveC5wa2kub3BlbmJhbmtpbmdicmFzaWwub3JnLmJyL2lzc3Vlci5jcmww GAYDVR0RBBEwD4INdHBwLmxvY2FsaG9zdDAOBgNVHQ8BAf8EBAMCBaAwEwYDVR0l BAwwCgYIKwYBBQUHAwIwggGoBgNVHSAEggGfMIIBmzCCAZcGCisGAQQBg7ovZAEw ggGHMIIBNgYIKwYBBQUHAgIwggEoDIIBJFRoaXMgQ2VydGlmaWNhdGUgaXMgc29s ZWx5IGZvciB1c2Ugd2l0aCBSYWlkaWFtIFNlcnZpY2VzIExpbWl0ZWQgYW5kIG90 aGVyIHBhcnRpY2lwYXRpbmcgb3JnYW5pc2F0aW9ucyB1c2luZyBSYWlkaWFtIFNl cnZpY2VzIExpbWl0ZWRzIFRydXN0IEZyYW1ld29yayBTZXJ2aWNlcy4gSXRzIHJl Y2VpcHQsIHBvc3Nlc3Npb24gb3IgdXNlIGNvbnN0aXR1dGVzIGFjY2VwdGFuY2Ug b2YgdGhlIFJhaWRpYW0gU2VydmljZXMgTHRkIENlcnRpY2ljYXRlIFBvbGljeSBh bmQgcmVsYXRlZCBkb2N1bWVudHMgdGhlcmVpbi4wSwYIKwYBBQUHAgEWP2h0dHA6 Ly9yZXBvc2l0b3J5LnNhbmRib3gucGtpLm9wZW5iYW5raW5nYnJhc2lsLm9yZy5i ci9wb2xpY2llczANBgkqhkiG9w0BAQsFAAOCAQEAMbqpPqhVeuUs6tPUCk6XdYGl Ofh6OpMLD1X58cGAWLx4DjEYva9dUecQ2FebyYoizyChawKrexNUI4pKkoPWPrWd TnlEKma9cjPUMuWVa2ZrMz/gzl1tSD8sSY8ZM7/72JT8GhbgCxBz0+qlITyD+myk 4ekJUHMm2/7/bwR4T73HctJ7Y8AorjdSRUNF6CSh/R1NUhWoycg7vJ2tH+Hj/mUk kzO4I08v/5P5kfRMkofSSH6vRh1zJfYq2/uvpZpFj7/LMar8o5MYRuPFxKifRsr/ vL8HmergQjPtpAnUF8YJpg63AxjKSgfhM9KisaUN6i2/jrhCvz3pAIUzLXBr7w== -----END CERTIFICATE-----
执行命令后的输出:
subject= 0.9.2342.19200300.100.1.1=#132437323138653161662D313935662D343262352D613434622D386337383238343730663561 2.5.4.97=#132A4F464242522D37346539323964392D333362362D346438352D386261372D633134366338363761383137 1.3.6.1.4.1.311.60.2.1.3=#1302554B 2.5.4.15=#131450726976617465204F7267616E697A6174696F6E 2.5.4.5=#130E3433313432363636303030313937 2.5.4.3=#1303747070 2.5.4.10=#13134F70656E2042616E6B696E672042726173696C 2.5.4.7=#13064C4F4E444F4E 2.5.4.8=#1302524A 2.5.4.6=#13024252
我尝试用Node.js的crypto模块的X509Certificate、asn1js、pkijs等工具实现类似功能,但都没成功,请问有没有可行的实现方法?
解决方案
有两种可行的实现方式,一种是通过ASN.1解析库纯JS实现,另一种是直接调用OpenSSL命令行工具复用其逻辑:
方法一:使用pkijs + asn1js解析ASN.1结构
1. 安装依赖
npm install pkijs asn1js
2. 实现代码
const pkijs = require("pkijs"); const asn1js = require("asn1js"); const fs = require("fs"); // 读取证书文件并转换为DER格式 const certPem = fs.readFileSync("./mycertificate.cer", "utf8"); const certDer = Buffer.from( certPem.replace(/-----BEGIN CERTIFICATE-----|-----END CERTIFICATE-----/g, "").trim(), "base64" ); // 解析证书结构 const asn1 = asn1js.fromBER(certDer); const cert = new pkijs.Certificate({ schema: asn1.result }); // 输出符合格式的主题信息 console.log("subject="); cert.subject.typesAndValues.forEach(attr => { const oid = attr.type.toString(); // 获取属性值的BER编码十六进制字符串 const valueHex = attr.value.toBER(false).toString("hex"); console.log(`${oid}=#${valueHex}`); });
说明
这段代码会解析证书的ASN.1结构,遍历主题的每个属性,输出OID和对应属性值的BER十六进制编码,格式与你提供的OpenSSL输出完全一致。
方法二:直接调用OpenSSL命令行
实现代码
const { execSync } = require("child_process"); const fs = require("fs"); const certPath = "./mycertificate.cer"; try { const output = execSync( `openssl x509 -subject -noout -nameopt rfc2253 -nameopt dump_all -nameopt oid -nameopt sep_multiline -in ${certPath}`, { encoding: "utf8" } ); console.log(output); } catch (err) { console.error("执行失败:", err.message); }
说明
通过Node.js的child_process模块执行OpenSSL命令,直接获取命令输出,无需处理复杂的ASN.1解析逻辑,适合对输出格式要求严格的场景。
内容的提问来源于stack exchange,提问作者Ranieri Mazili
相关产品推荐
相关产品推荐

