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

时间:2011-01-26 11:03:26

标签: c encryption openssl x509

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

RFC5280表示签名函数的输入是DER编码的tbsCertificate字段。不幸的是,我计算的哈希值与OpenSSL产生的哈希值不同。这是一个循序渐进的例子。

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

    现在,我在第2步和第3步得到的哈希值不同。有人可以给我一个提示我可能做错了吗?

2 个答案:

答案 0 :(得分:19)

好吧,事实证明,OpenSSL计算的指纹只是整个证书的哈希值(在DER二进制编码中,不是 ASCII PEM一个!) ),不仅仅是我认为的TBS部分。

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

答案 1 :(得分:2)

指纹类似于.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();


    }