O novo algoritmo de hash openssl do assunto é diferente

Eu estou correndo em um problema ao gerenciar certificados openssl do Java Framework.

openssl x509 -subject_hash ...

saída difere para aquele que o framework Java retorna ao chamarX509_NAME_hash(), ver abaixo.

A razão para isso é que o openssl mudou a maneira como calcula o SHA1. Agora, em vez de basear o hash na representação ASN.1 DER do sujeito, como faz para o MD5, ele primeiro calcula a representação CANÔNICA e, em seguida, com base nisso, calcula o ASN.1 DER e depois usa isso como entrada para o algoritmo 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);
    }
}

Eu estava olhandox_name.c ex509_cmp.c da biblioteca openssl para tentar consertá-lo na subcamada Java. Mas eu não tive sucesso.

Eu entendo que tenho que modificarX509_NAME_hash método emx509_cmp.c. Mas não tenho certeza se essa mudança deve ser logo antes ou logo apósi2d_X509_NAME(x,NULL); Este método está calculando a representação CANÔNICA do nome do sujeito, certo? então, eu precisaria calcular o ASN1 DER com base nessa saída, certo? mas eu não posso fazer isso.

Eu ficaria grato se alguém puder me guiar ou através de alguma luz sobre isso para resolver este problema.

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

A funçãox509_name_canon aparentemente executa a re-codificação. Isso está emcrypto/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.
 * 
 */

questionAnswers(1)

yourAnswerToTheQuestion