如何在Node.js(TypeScript)中生成与OpenSSL一致的PEM证书Subject Hash
问题分析与解决方案
你的代码存在两个核心错误:
- 错误1:使用格式化后的Subject字符串计算哈希
OpenSSL的subject_hash_old是基于Subject字段的原始ASN.1 DER二进制编码计算SHA1哈希,而非你代码中用的格式化文本(逗号分隔的字符串)。不同工具对Subject的格式化规则不同,导致字符串内容和OpenSSL的计算源完全不一致。 - 错误2:未处理字节序反转
OpenSSL会将SHA1哈希的前4个字节反转后再转为十六进制输出,你直接取前8个字符(对应前4字节)但未反转字节顺序,结果自然和OpenSSL不符。
正确实现(Node.js原生crypto模块)
这个实现完全匹配OpenSSLsubject_hash_old的计算逻辑,无需依赖OpenSSL:
import crypto from 'node:crypto'; export function getSubjectHashOld(pemCertificate: string): string { const cert = new crypto.X509Certificate(pemCertificate); // 获取Subject字段的原始ASN.1 DER二进制编码 const subjectDer = cert.rawSubject; // 计算SHA1哈希 const sha1Hash = crypto.createHash('sha1').update(subjectDer).digest(); // 取前4个字节并反转字节顺序,再转为小写十六进制 const reversedBytes = sha1Hash.subarray(0, 4).reverse(); return reversedBytes.toString('hex'); }
正确实现(node-forge版本)
如果需要依赖forge库,可使用以下代码:
import forge from 'node-forge'; import crypto from 'node:crypto'; export function getSubjectHashOldForge(pemCertificate: string): string { const cert = forge.pki.certificateFromPem(pemCertificate); // 将Subject转为ASN.1 DER二进制编码 const subjectAsn1 = forge.pki.certificateToAsn1(cert).tbsCertificate.subject; const subjectDer = forge.asn1.toDer(subjectAsn1).getBytes(); // 计算SHA1哈希 const sha1Hash = crypto.createHash('sha1').update(Buffer.from(subjectDer, 'binary')).digest(); // 反转前4字节并转十六进制 const reversedBytes = sha1Hash.subarray(0, 4).reverse(); return reversedBytes.toString('hex'); }
调用上述函数后,返回结果会和openssl x509 -inform PEM -subject_hash_old -in my-cert.pem | head -1的输出完全一致(即2889162b)。
内容的提问来源于stack exchange,提问作者Meisam Seyed Aliroteh
相关产品推荐
相关产品推荐

