Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 新的主题散列openssl算法有所不同_Java_Algorithm_Openssl_Sha1_X509 - Fatal编程技术网

Java 新的主题散列openssl算法有所不同

Java 新的主题散列openssl算法有所不同,java,algorithm,openssl,sha1,x509,Java,Algorithm,Openssl,Sha1,X509,我在从Java框架管理openssl证书时遇到了一个问题 openssl x509 -subject_hash ... 输出与Java framework调用X509\u NAME\u hash()时返回的输出不同,请参见下文 原因是openssl改变了计算SHA1的方式。现在,它不再像MD5那样在主题的ASN.1阶表示中基于散列,而是首先计算规范表示,然后在此基础上计算ASN.1阶,然后将其用作SHA1算法的输入 NativeCrypto.java: // --- X509_NAME ---

我在从Java框架管理openssl证书时遇到了一个问题

openssl x509 -subject_hash ...
输出与Java framework调用
X509\u NAME\u hash()
时返回的输出不同,请参见下文

原因是openssl改变了计算SHA1的方式。现在,它不再像MD5那样在主题的ASN.1阶表示中基于散列,而是首先计算规范表示,然后在此基础上计算ASN.1阶,然后将其用作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);
    }
}
    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);
    }
我正在查看openssl库中的
x_name.c
x509_cmp.c
,试图在Java底层修复它。但我没有成功

我知道我必须修改
X509\u cmp.c
中的
X509\u NAME\u hash
方法。但不确定该更改是在
i2d\u X509\u NAME(x,NULL)之前还是之后
这个方法是计算主题名称的规范表示,对吗?然后,我需要根据输出计算ASN1 DER,对吗?但我就是做不到

如果有人能指导我或通过一些光来解决这个问题,我将不胜感激

x509\u cmp.c

// --- 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);
    }
}
    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);
    }

您离它不远,如果您想要与OpenSSL new SubjectHash相同的结果,那么必须删除DN的前导序列。因此,你必须这样做:

// --- 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[] princ = principal.getEncoded();
        final ASN1Sequence obj = (ASN1Sequence) ASN1Object.fromByteArray( princ );

        // Remove the leading sequence ...
        final DERSet enc = (DERSet) obj.getObjectAt(0);
        final byte[] toHash = enc.getDEREncoded();

        MessageDigest md = MessageDigest.getInstance(algorithm);
        byte[] digest = md.digest(toHash);
        return Memory.peekInt(digest, 0, ByteOrder.LITTLE_ENDIAN);

    } catch (NoSuchAlgorithmException e) {
        throw new AssertionError(e);
    } catch (IOException e) {
        throw new AssertionError(e);
    }
}

这样的结果与OpenSSL新主题散列相同。

另请参见。虽然是Java,但它详细说明了主题哈希的OpenSSL处理。我不知道这是如何工作的。获得第一个集合,但序列包含多文件集合。从
princ[]
您需要跳过标记和长度的前(三)个字节吗?