如何计算X.509证书的SHA-1指纹?

发布于 2024-10-14 08:22:27 字数 562 浏览 1 评论 0原文

我正在尝试从头开始实现 X.509 证书生成器(我知道现有的证书生成器,但我还需要另一个)。我无法理解的是如何计算证书的 SHA-1(或任何其他)指纹。

RFC5280 表示签名函数的输入是DER 编码的 tbsCertificate 字段。不幸的是,我计算的哈希值与 OpenSSL 生成的哈希值不同。这是一个分步示例。

  1. 使用 OpenSSL 的 x509 工具生成证书(采用二进制 DER 形式,不是 ASCII PEM)
  2. 使用 openssl x509 -fingerprint 计算其 SHA-1 哈希
  3. 使用 < 提取 TBS 字段code>dd (或其他任何内容)并将其存储在单独的文件中;使用 sha1sum 实用程序计算其哈希值

现在,我在步骤 2 和步骤 3 中获得的哈希值不同。有人可以给我提示我可能做错了什么吗?

I'm trying to implement an X.509 certificate generator from scratch (I know about the existing ones, but I need yet another one). What I cannot understand is how to calculate the SHA-1 (or any other) fingerprint of the certificate.

The RFC5280 says that the input to the signature function is the DER-encoded tbsCertificate field. Unfortunately, the hash that I calculate differs from the one produced by OpenSSL. Here's a step-by-step example.

  1. Generate a certificate using OpenSSL's x509 tool (in a binary DER form, not the ASCII PEM)
  2. Calculate its SHA-1 hash using openssl x509 -fingerprint
  3. Extract the TBS field using dd (or anything else) and store it in a separate file; calculate its hash using the sha1sum utility

Now, the hashes I get at steps 2 and 3 are different. Can someone please give me a hint what I may be doing wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

帝王念 2024-10-21 08:22:27

好吧,事实证明,OpenSSL 计算出的指纹只是整个证书的哈希值(采用 DER 二进制编码,不是 ASCII PEM 编码!),而不是正如我所想,只有TBS部分。

对于任何关心计算证书摘要的人来说,它是以不同的方式完成的:哈希值是通过 DER 编码(同样,不是 PEM 字符串)TBS 部分计算的,包括其 ASN.1 标头(ID 0x30 == ASN1_SEQUENCE | ASN1_CONSTRUCTED 和长度字段)。请注意,不考虑证书的 ASN.1 标头。

Ok, so it turned out that the fingerprint calculated by OpenSSL is simply a hash over the whole certificate (in its DER binary encoding, not the ASCII PEM one!), not only the TBS part, as I thought.

For anyone who cares about calculating certificate's digest, it is done in a different way: the hash is calculated over the DER-encoded (again, not the PEM string) TBS part only, including its ASN.1 header (the ID 0x30 == ASN1_SEQUENCE | ASN1_CONSTRUCTED and the length field). Please note that the certificate's ASN.1 header is not taken into account.

一笑百媚生 2024-10-21 08:22:27

指纹类似于 .net 中的术语“指纹”。下面的代码片段应该可以帮助您计算指纹:

    public String generateFingerPrint(X509Certificate cert) throws CertificateEncodingException,NoSuchAlgorithmException {

MessageDigest digest = MessageDigest.getInstance("SHA-1");
byte[] hash = digest.digest(cert.getEncoded[]);

final char delimiter = ':';
// Calculate the number of characters in our fingerprint
      // ('# of bytes' * 2) chars + ('# of bytes' - 1) chars for delimiters
      final int len = hash.length * 2 + hash.length - 1;
      // Typically SHA-1 algorithm produces 20 bytes, i.e. len should be 59
      StringBuilder fingerprint = new StringBuilder(len);

      for (int i = 0; i < hash.length; i++) {
         // Step 1: unsigned byte
         hash[i] &= 0xff;

         // Steps 2 & 3: byte to hex in two chars
         // Lower cased 'x' at '%02x' enforces lower cased char for hex value!
         fingerprint.append(String.format("%02x", hash[i]));

         // Step 4: put delimiter
         if (i < hash.length - 1) {
            fingerprint.append(delimiter);
         }
      }

      return fingerprint.toString();


    }

The finger print is similar to term "Thumbprint" in .net. Below code snippet should help you to compute finger print :

    public String generateFingerPrint(X509Certificate cert) throws CertificateEncodingException,NoSuchAlgorithmException {

MessageDigest digest = MessageDigest.getInstance("SHA-1");
byte[] hash = digest.digest(cert.getEncoded[]);

final char delimiter = ':';
// Calculate the number of characters in our fingerprint
      // ('# of bytes' * 2) chars + ('# of bytes' - 1) chars for delimiters
      final int len = hash.length * 2 + hash.length - 1;
      // Typically SHA-1 algorithm produces 20 bytes, i.e. len should be 59
      StringBuilder fingerprint = new StringBuilder(len);

      for (int i = 0; i < hash.length; i++) {
         // Step 1: unsigned byte
         hash[i] &= 0xff;

         // Steps 2 & 3: byte to hex in two chars
         // Lower cased 'x' at '%02x' enforces lower cased char for hex value!
         fingerprint.append(String.format("%02x", hash[i]));

         // Step 4: put delimiter
         if (i < hash.length - 1) {
            fingerprint.append(delimiter);
         }
      }

      return fingerprint.toString();


    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文