C 如何计算X.509证书';s SHA-1指纹?

C 如何计算X.509证书';s SHA-1指纹?,c,encryption,openssl,x509,C,Encryption,Openssl,X509,我正在尝试从头实现一个X.509证书生成器(我知道现有的,但我还需要另一个)。我无法理解的是如何计算证书的SHA-1(或任何其他)指纹 表示签名函数的输入是DER编码的tbsCertificate字段。不幸的是,我计算的哈希与OpenSSL生成的哈希不同。这里有一个逐步的例子 使用OpenSSL的x509工具生成证书(以二进制DER形式,而不是ASCII PEM) 使用opensslx509-fingerprint 使用dd(或其他任何内容)提取TBS字段,并将其存储在单独的文件中;使用sha1

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

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

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

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

    好的,所以结果证明,OpenSSL计算的指纹只是整个证书(在其DER二进制编码中,不是ASCII PEM!)上的散列,而不仅仅是我认为的TBS部分


    对于任何关心计算证书摘要的人来说,这是以不同的方式完成的:哈希仅在DER编码(同样,不是PEM字符串)TBS部分上计算,包括其ASN.1头(ID 0x30==ASN1_序列| ASN1_构造和长度字段)。请注意,证书的ASN.1标头未被考虑。

    指纹类似于.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();
    
    
        }
    
    公共字符串generateFingerPrint(X509Certificate cert)抛出CertificateCodingException,NoSuchAlgorithmException{
    MessageDigest=MessageDigest.getInstance(“SHA-1”);
    字节[]散列=digest.digest(cert.getEncoded[]);
    最终字符分隔符=':';
    //计算指纹中的字符数
    //('#of bytes'*2)字符+('#of bytes'-1)用于分隔符的字符
    final int len=hash.length*2+hash.length-1;
    //通常,SHA-1算法产生20个字节,即len应为59
    StringBuilder指纹=新StringBuilder(len);
    for(int i=0;i
    当您计算tbsCertificate的SHA-1哈希时,是否按照?嗯。。。RFC2313(PKCS#1)仅指定RSA加密。据我所知,在SHA-1计算阶段不需要填充?@Roman D:因为它一点也不明显,你应该写下来作为答案并接受它。@Abhineet,你如何获得证书的指纹?我不知道是什么。您可以计算证书的SHA-1,看看它是否与指纹相同。@Abhineet,我现在没有可用的Windows PC来查看。可能显示的指纹是公钥的散列,如中所述?您可以在回答(或问题)中添加如何使用dd提取TBS部分以供将来参考:)哦。。。那是很久以前的事了,所以我不记得细节了。我想我从证书的hextump中手动提取了TBS偏移量和长度,然后将这些值用作dd的参数,这并不复杂there@RomanD您的答案在第一段中是“对整个证书进行哈希运算”,在第二段中是“仅TBS部分”。这是个错误吗?那么,证书的TBS部分是什么?我在谷歌搜索中找不到任何有用的东西。@chitti不,这不是一个错误,我甚至用斜体字强调这个想法。:)第一段是关于指纹,第二段是关于摘要。您可以阅读RFC5280中的TBSCertificate字段(参见4.1.1、4.1.1.1、4.1.2)。基本上,它是证书的必填字段之一(另外两个是signatureAlgorithm和signatureValue)。@FilipePina您可以使用OpenSSL函数i2d_X509_CINF获取X509的TBS部分。