You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 05:26:11