java - diferencia - El nuevo algoritmo hash openssl de sujeto difiere
sha1 vs sha512 (1)
No está muy lejos de eso, si quiere el mismo resultado que OpenSSL new SubjectHash, debe eliminar la secuencia principal del DN. Por lo tanto, tienes que hacer algo como esto:
// --- 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);
}
}
Y con esto, el resultado es el mismo que OpenSSL new Subject_hash.
Me encuentro con un problema cuando administro certificados de openssl desde Java Framework.
openssl x509 -subject_hash ...
la salida difiere de la que devuelve Java framework al llamar a X509_NAME_hash()
, ver abajo.
La razón de esto es que openssl cambió la forma en que calcula el SHA1. Ahora, en lugar de basar el hash en la representación ASN.1 DER del sujeto, como lo hace para MD5, primero calcula la representación CANONICAL y luego, basándose en eso, calcula el DER ASN.1 y luego lo usa como el entrada para el 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);
}
}
Estaba buscando en x_name.c
y x509_cmp.c
de la biblioteca de openssl para tratar de arreglarlo en la x509_cmp.c
de Java. Pero no tuve éxito.
Entiendo que tengo que modificar el método x509_cmp.c
en x509_cmp.c
. Pero no estoy seguro si ese cambio debería ser correcto antes o después de i2d_X509_NAME(x,NULL);
Este método está calculando la representación CANÓNICA del nombre del sujeto, ¿verdad? entonces, necesitaría calcular el DER de ASN1 basado en esa salida, ¿verdad? pero simplemente no puedo hacerlo.
Estaría agradecido si alguien me puede guiar o con algo de luz sobre esto 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);
}
La función x509_name_canon
aparentemente realiza la recodificación. Esto está en 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.
*
*/