这将生成一个短的8位哈希值 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)
...
生成Java中X509Certificate的主题哈希...
以下是来自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];
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];
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
将 X509_NAME
编码为标准表示形式,使用RFC 2459(和其他地方)进行编码。例如,在证书主题和颁发者名称中使用。
您可以使用类似 openssl x509 -in <cert> -text -noout
的命令查看 OpenSSL 用于名称字符串的内容。它将类似于 C=US, ST=California, L=Mountain View, O=Google Inc, CN=www.google.com
(取自 Google 证书)。
在 Java 中生成 X509Certificate 的 Subject Hash...
从大局上来看,您正在生成主题的可分辨名称字符串的哈希值,并返回一个无符号长整数。无符号长整数实际上是一个被截断的哈希值。
X509_subject_name_hash
使用 SHA-1,而 X509_subject_name_hash_old
使用 MD5。
(评论)...他们如何使用 sha1 哈希来生成这个短哈希值
OpenSSL 提供了截断哈希的十六进制编码。整个哈希值在 md
中。 md
将是 16 字节(MD5)或 20 字节(SHA-1)。
截断发生在选择字节 [0,3]
和对 md[0]
、md[1]
、md[2]
和 md[3]
进行位操作时。
8 个数字来自于将 4 个字节的十六进制编码。
byte []sha1Bytes0_3 = Arrays.copyOfRange( sha1.digest(), 0, 4); String hexString = getHex(sha1Bytes0_3);
,但是得到的哈希值与openssl计算出的不同。 - Aamir Rizwan