我目前正在尝试使用Java Security API和BouncyCastle生成主题哈希.
当我使用Openssl库时,我就是这样做的:
openssl x509 -in /Users/Sn0wfreezeDev/Downloads/Test.pem -hash
这会生成一个短的8位数哈希值1817886a
这是我的Java代码
X509Certificate cert = CertManager.getCertificate(number, c);
MessageDigest sha1 = MessageDigest.getInstance("SHA1");
System.out.println(" Subject " + cert.getSubjectDN());
System.out.println(" Issuer " + cert.getIssuerDN());
sha1.update(cert.getSubjectDN().getName().getBytes());
String hexString = bytesToHex(sha1.digest());
System.out.println(" sha1 " + hexString);
System.out.println();
解决方法:
This generates a short 8 digit hash 1817886a
OpenSSL有两种形式:
$cd openssl-1.0.2-src
$grep -R X509_subject_name_hash *
...
crypto/x509/x509.h:unsigned long X509_subject_name_hash(X509 *x);
crypto/x509/x509.h:unsigned long X509_subject_name_hash_old(X509 *x);
crypto/x509/x509_cmp.c:unsigned long X509_subject_name_hash(X509 *x)
crypto/x509/x509_cmp.c:unsigned long X509_subject_name_hash_old(X509 *x)
...
Generate Subject Hash of X509Certificate in Java…
以下是来自crypto / x509 / x509_cmp.c的来源:
unsigned long X509_subject_name_hash(X509 *x)
{
return (X509_NAME_hash(x->cert_info->subject));
}
#ifndef OPENSSL_NO_MD5
unsigned long X509_subject_name_hash_old(X509 *x)
{
return (X509_NAME_hash_old(x->cert_info->subject));
}
#endif
最后:
unsigned long X509_NAME_hash(X509_NAME *x)
{
unsigned long ret = 0;
unsigned char md[SHA_DIGEST_LENGTH];
/* Make sure X509_NAME structure contains valid cached encoding */
i2d_X509_NAME(x, NULL);
if (!EVP_Digest(x->canon_enc, x->canon_enclen, md, NULL, EVP_sha1(),
NULL))
return 0;
ret = (((unsigned long)md[0]) | ((unsigned long)md[1] << 8L) |
((unsigned long)md[2] << 16L) | ((unsigned long)md[3] << 24L)
) & 0xffffffffL;
return (ret);
}
#ifndef OPENSSL_NO_MD5
unsigned long X509_NAME_hash_old(X509_NAME *x)
{
EVP_MD_CTX md_ctx;
unsigned long ret = 0;
unsigned char md[16];
/* Make sure X509_NAME structure contains valid cached encoding */
i2d_X509_NAME(x, NULL);
EVP_MD_CTX_init(&md_ctx);
EVP_MD_CTX_set_flags(&md_ctx, EVP_MD_CTX_FLAG_NON_FIPS_ALLOW);
if (EVP_DigestInit_ex(&md_ctx, EVP_md5(), NULL)
&& EVP_DigestUpdate(&md_ctx, x->bytes->data, x->bytes->length)
&& EVP_DigestFinal_ex(&md_ctx, md, NULL))
ret = (((unsigned long)md[0]) | ((unsigned long)md[1] << 8L) |
((unsigned long)md[2] << 16L) | ((unsigned long)md[3] << 24L)
) & 0xffffffffL;
EVP_MD_CTX_cleanup(&md_ctx);
return (ret);
}
#endif
i2d_X509_NAME
使用RFC 2459(和其他地方)将X509_NAME编码为标准表示.例如,它用于证书主题和发行人名称.
您可以使用openssl x509 -in< cert>等命令查看OpenSSL用于名称字符串的内容. -text -noout.它看起来类似于C = US,ST = California,L = Mountain View,O = Google Inc,CN = www.google.com(取自Google证书).
Generate Subject Hash of X509Certificate in Java…
在大图中,您将生成Subject的Distinguished Name字符串的哈希并返回unsigned long. unsigned long实际上是一个截断的哈希.
X509_subject_name_hash使用SHA-1,X509_subject_name_hash_old使用MD5.
(comment) … how they can use a sha1 hash to generate that short hash
OpenSSL提供截断哈希的十六进制编码.整个哈希是md. md将是16字节(MD5)或20字节(SHA-1).
通过选择字节[0,3]和md [0],md [1],md [2]和md [3]上的位操作进行截断.
8位数来自16位字节的十六进制编码.