2013-10-08 3 views
3

Java Framework에서 openssl 인증서를 관리 할 때 문제가 발생합니다.새 주제 해시 openssl 알고리즘이 다릅니다.

openssl x509 -subject_hash ... 

출력은 X509_NAME_hash()을 호출 할 때 Java 프레임 워크가 반환하는 것과 다릅니다 (아래 참조).

이유는 openssl이 SHA1을 계산하는 방식을 변경했기 때문입니다. 이제 MD5에서와 마찬가지로 제목의 ASN.1 DER 표현에 해시를 사용하는 대신 CANONICAL 표현을 계산 한 다음이를 기반으로 ASN.1 DER을 계산 한 다음이를 사용하여 SHA1 알고리즘에 대한 입력.

NativeCrypto.java : 나는 자바에서 레이어에 그것을 해결하기 위해 시도하려면 openssl 라이브러리에서 x_name.cx509_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); 
    } 
} 

. 그러나 나는 성공하지 못했습니다.

X509_NAME_hash 메서드를 x509_cmp.c에서 수정해야한다는 것을 알고 있습니다. 그러나 그 변경이 바로 이전인지 직전인지 확실하지 않은 경우 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에 : 당신이 DN의 주요 순서를 제거해야합니다 OpenSSL을 새로운 SubjectHash과 같은 결과를 원하는 경우

/* 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. 
* 
*/ 
+0

[Java에서 X509Certificate의 제목 해시 생성] (http://stackoverflow.com/a/30265791/608639)을 참조하십시오. 그것의 자바, 그것은 주제 해시의 OpenSSL 처리를 상세하게 설명한다. – jww

답변

2

당신은 아주 멀리에서 수 없습니다. 그러므로 다음과 같이해야합니다 :

// --- 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 new Subject_hash와 같습니다.