【发布时间】:2013-10-14 18:06:00
【问题描述】:
我在从 Java 框架管理 openssl 证书时遇到了问题。
openssl x509 -subject_hash ...
输出与 Java 框架在调用 X509_NAME_hash() 时返回的不同,见下文。
原因是 openssl 改变了它计算 SHA1 的方式。现在,它不像 MD5 那样基于主题的 ASN.1 DER 表示中的散列,而是首先计算 CANONICAL 表示,然后在此基础上计算 ASN.1 DER,然后将其用作SHA1 算法的输入。
NativeCrypto.java:
// --- X509_NAME -----------------------------------------------------------
public static int X509_NAME_hash(X500Principal principal) {
return X509_NAME_hash(principal, "SHA1");
}
private static int X509_NAME_hash(X500Principal principal, String algorithm) {
try {
byte[] digest = MessageDigest.getInstance(algorithm).digest(principal.getEncoded());
return Memory.peekInt(digest, 0, ByteOrder.LITTLE_ENDIAN);
} catch (NoSuchAlgorithmException e) {
throw new AssertionError(e);
}
}
我正在从 openssl 库中查看 x_name.c 和 x509_cmp.c 以尝试在 Java 底层中修复它。但我没有成功。
我知道我必须修改x509_cmp.c 中的X509_NAME_hash 方法。但不确定该更改应该在i2d_X509_NAME(x,NULL); 之前还是之后
此方法正在计算主题名称的 CANONICAL 表示,对吗?那么,我需要根据该输出计算 ASN1 DER,对吗?但我就是做不到。
如果有人能指导我或通过一些线索来解决这个问题,我将不胜感激。
x509_cmp.c:
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);
}
函数x509_name_canon 显然执行了重新编码。这是crypto/asn1/x_name.c:
/* This function generates the canonical encoding of the Name structure.
* In it all strings are converted to UTF8, leading, trailing and
* multiple spaces collapsed, converted to lower case and the leading
* SEQUENCE header removed.
*
*/
【问题讨论】:
-
另见Generate Subject Hash of X509Certificate in Java。虽然它是 Java,但它详细说明了主题哈希的 OpenSSL 处理。
标签: java algorithm openssl sha1 x509