如何获取 PEM 证书的主题哈希值

问题描述 投票:0回答:1

我有一个 Node 项目(用 TypeScript 编写),我想添加一个函数来获取 PEM 证书的主题哈希值,我需要它以与 OpenSSL 相同的方式计算哈希值,但不使用 OpenSSL(b/c 我的代码需要在可能未安装 OpenSSL 的各种平台上运行)。

所以假设我有一个名为

my-cert.pem
的文件。当我运行
openssl x509 -inform PEM -subject_hash_old -in my-cert.pem | head -1
时,它输出
2889162b

然后我尝试了以下在 TypeScript 中计算哈希值的方法,看看是否可以获得相同的值:

import crypto from 'node:crypto';
import forge from 'node-forge';

public static getSubjectHashFromPEM1(pemCertificate: string): string {
    const cert = new crypto.X509Certificate(pemCertificate);
    const subject = cert.subject.replaceAll('\n', ', ');
    const hash = crypto.createHash('sha1').update(subject).digest('hex').slice(0, 8);
    return hash;
}

public static getSubjectHashFromPEM2(pemCertificate: string): string {
    const cert = forge.pki.certificateFromPem(pemCertificate);
    const subject = cert.subject;
    const subjectString = subject.attributes.map(attr => `${attr.shortName ?? ''}=${attr.value as string}`).join(', ');
    const hash = crypto.createHash('sha1').update(subjectString).digest('hex').slice(0, 8);
    return hash;
}

但是这两个方法都返回

d89c7493
,这与 OpenSSL 返回的
2889162b
不同。

我在这里做错了什么?

openssl ssl-certificate x509certificate
1个回答
0
投票

我设法让它工作如下:

private static getSubjectHashOld(cert: forge.pki.Certificate): string {
    // 1. Extract the subject name in ASN.1 format
    const subjectAsn1 = forge.pki.distinguishedNameToAsn1(cert.subject);

    // 2. Convert the subject to DER-encoded form
    const derSubject = forge.asn1.toDer(subjectAsn1).getBytes();

    // 3. Create an MD5 hash of the DER-encoded subject
    const md = forge.md.md5.create();
    md.update(derSubject, 'raw');
    const md5Hash = md.digest().getBytes();

    // 4. The first four bytes of the MD5 hash are the subject hash in little-endian format
    const hashBuffer = forge.util.createBuffer(md5Hash.slice(0, 4), 'raw');
    const hashArray = Array.from(hashBuffer.bytes()).reverse();

    // 5. Convert the little-endian hash to a hexadecimal string
    const subjectHash = hashArray.map(byte => ('00' + byte.charCodeAt(0).toString(16)).slice(-2)).join('');

    return subjectHash;
}
© www.soinside.com 2019 - 2024. All rights reserved.