我正在尝试从头开始实现X.509证书生成器(我知道现有的,但我需要另一个)。我无法理解的是如何计算证书的SHA-1(或任何其他)指纹。
RFC5280表示签名函数的输入是DER编码的tbsCertificate字段。不幸的是,我计算的哈希值与OpenSSL产生的哈希值不同。这是一个循序渐进的例子。
openssl x509 -fingerprint
sha1sum
实用程序现在,我在第2步和第3步得到的哈希值不同。有人可以给我一个提示我可能做错了吗?
答案 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();
}