在 Java 中生成 X509Certificate 的主题哈希 [英] Generate Subject Hash of X509Certificate in Java

查看:35
本文介绍了在 Java 中生成 X509Certificate 的主题哈希的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在尝试使用 Java 安全 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("主题" + cert.getSubjectDN());System.out.println("颁发者" + cert.getIssuerDN());sha1.update(cert.getSubjectDN().getName().getBytes());String hexString = bytesToHex(sha1.digest());System.out.println(" sha1 " + hexString);System.out.println();

解决方案

这会生成一个短的 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_MD5unsigned long X509_subject_name_hash_old(X509 *x){返回 (X509_NAME_hash_old(x->cert_info->subject));}#万一

最后:

unsigned long X509_NAME_hash(X509_NAME *x){无符号长ret = 0;无符号字符 md[SHA_DIGEST_LENGTH];/* 确保 X509_NAME 结构包含有效的缓存编码 */i2d_X509_NAME(x, NULL);如果 (!EVP_Digest(x->canon_enc, x->canon_enclen, md, NULL, EVP_sha1(),空值))返回0;ret = (((unsigned long)md[0]) | ((unsigned long)md[1] <<8L) |((unsigned long)md[2] <<16L) |((unsigned long)md[3] <<24L)) &0xffffffffL;返回 (ret);}#ifndef OPENSSL_NO_MD5unsigned long X509_NAME_hash_old(X509_NAME *x){EVP_MD_CTX md_ctx;无符号长ret = 0;无符号字符 md[16];/* 确保 X509_NAME 结构包含有效的缓存编码 */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);如果 (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);返回 (ret);}#万一

<小时>

i2d_X509_NAME 编码 X509_NAME 使用 RFC 2459(和其他地方)转换为标准表示.例如,它用于证书主题和颁发者名称.

您可以使用诸如 openssl x509 -in <cert> 之类的命令查看 OpenSSL 用于名称字符串的内容.-text -noout.它看起来类似于 C=US, ST=California, L=Mountain View, O=Google Inc, CN=www.google.com(取自 Google 证书).

<小时><块引用>

在 Java 中生成 X509Certificate 的主题哈希...

从总体上看,您正在生成主题的专有名称字符串的散列并返回一个 unsigned long.unsigned long 实际上是一个截断的散列.

X509_subject_name_hash 使用 SHA-1,X509_subject_name_hash_old 使用 MD5.

<小时><块引用>

(comment) ... 他们如何使用 sha1 哈希来生成短哈希

OpenSSL 提供截断散列的十六进制编码.整个散列在 md 中.md 将是 16 字节 (MD5) 或 20 字节 (SHA-1).

截断发生在选择字节 [0,3] 和对 md[0]md[1] 的位操作>、md[2]md[3].

8 位数字来自 4 个字节的十六进制编码.

I'm currently trying to generate the subject hash by using the Java Security API and BouncyCastle.

Here's what I do, when I use the Openssl Library:

openssl x509 -in  /Users/Sn0wfreezeDev/Downloads/Test.pem -hash

This generates a short 8 digit hash 1817886a

This is my Java code

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

There are two forms of this from 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...

Here is the source for them from 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

And finally:

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 encodes a X509_NAME into a standard representation using RFC 2459 (and elsewhere). Its used, for example, in certificate subject and issuer names.

You can see what OpenSSL uses for the name string with commands like openssl x509 -in <cert> -text -noout. It will look similar to C=US, ST=California, L=Mountain View, O=Google Inc, CN=www.google.com (taken from a Google certificate).


Generate Subject Hash of X509Certificate in Java...

In the big picture, you are generating a hash of the Subject's Distinguished Name string and returning an unsigned long. The unsigned long is effectively a truncated hash.

X509_subject_name_hash uses SHA-1, and X509_subject_name_hash_old uses MD5.


(comment) ... how they can use a sha1 hash to generate that short hash

OpenSSL provides a hex encoding of a truncated hash. The whole hash is in md. md will be 16 bytes (MD5) or 20 bytes (SHA-1).

The truncation occurs with the selection of bytes [0,3] and the bit operations on md[0], md[1], md[2] and md[3].

The 8 digits comes from hex encoding the 4 bytes.

这篇关于在 Java 中生成 X509Certificate 的主题哈希的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆