2013-02-08 3 views
2

코드의 이러한 (PHP 및 Java) 코드 스 니펫이 동일한 입력에 대해 동일한 SHA512를 반환하지 않는 이유를 알아낼 수 있습니까?Java SHA512 다이제스트 출력이 PHP 스크립트와 다릅니다

public String processSHA512(String pw, String salt, int rounds) 
{ 
    try { 
     md = MessageDigest.getInstance("SHA-512"); 
    } catch (NoSuchAlgorithmException e) { 
     e.printStackTrace(); 
     throw new RuntimeException("No Such Algorithm"); 
    } 

    String result = hashPw(pw, salt, rounds); 
    System.out.println(result); 
    return result; 
} 

private static String hashPw(String pw, String salt, int rounds) { 
    byte[] bSalt; 
    byte[] bPw; 

    String appendedSalt = new StringBuilder().append('{').append(salt).append('}').toString(); 

    try { 
     bSalt = appendedSalt.getBytes("ISO-8859-1"); 
     bPw = pw.getBytes("ISO-8859-1"); 
    } catch (UnsupportedEncodingException e) { 
     throw new RuntimeException("Unsupported Encoding", e); 
    } 

    byte[] digest = run(bPw, bSalt); 
    Log.d(LCAT, "first hash: " + Base64.encodeBytes(digest)); 
    for (int i = 1; i < rounds; i++) { 
     digest = run(digest, bSalt); 
    } 

    return Base64.encodeBytes(digest); 
} 

private static byte[] run(byte[] input, byte[] salt) { 
    md.update(input); 
    return md.digest(salt); 
} 

base64 인코딩의 도서관이있다 :

$password = 'whateverpassword'; 
$salt = 'ieerskzcjy20ec8wkgsk4cc8kuwgs8g'; 
$salted = $password.'{'.$salt.'}'; 
$digest = hash('sha512', $salted, true); 
echo "digest: ".base64_encode($digest); 
for ($i = 1; $i < 5000; $i++) { 
    $digest = hash('sha512', $digest.$salted, true); 
} 
$encoded_pass = base64_encode($digest); 
echo $encoded_pass; 

은 안드로이드 응용 프로그램의 코드입니다 base64lib

이 자바 코드는 실제로 내가 다른 질문을 주위에 발견 된 일부 수정 된 코드 스택 오버플로. Android 코드가 정상적으로 실행되고 있지만 PHP 스크립트의 결과와 일치하지 않습니다. 첫 번째 해시와 일치하지 않습니다.

주 1 : 원시 이진 출력을

주 2를 반환 hash('sha512',$input, $raw_output) PHP에 : 자바에 나는 캐릭터 세트 (UTF-8, ASCII)를 변경하려고하지만 그것도 작동하지 않았다.

참고 3 : 서버의 코드를 변경할 수 없으므로 내 안드로이드 코드를 변경하는 방법에 대한 답변을 보내 주시면 감사하겠습니다.

+0

안드로이드와 PHP에서 이것 좀보세요 : http://www.coderblog.de/producing-the-same-sha-512-hash-in-java-and-php/#comment-614 ... 도움이되었습니다. 나 :) – Buksy

답변

2

첫 번째 해시는 서버와 Java에서 동일해야합니다. 그런 다음 루프에서 다이제스트에 추가되는 내용은 PHP 코드에서 password{salt}이지만 Java 코드에서는 {salt}뿐입니다.

+0

예, 당신 말이 맞아요. 귀하의 조언으로 코드를 변경했지만 동일한 출력을 생성하지는 못했습니다. 그러나 첫 번째 해시는 동일해야합니다. – Joscandreu

+0

@ Joscandreu 첫 번째 해시가 이미 다르거 나 동일합니까? – Henry

+0

첫 번째 해시가 다릅니다. 내 생각 엔 문자열의 바이너리 해석으로 무언가를해야하지만 charset을 변경해도 자바 출력에는 영향을 미치지 않는다. PHP에서 ISO-8859-1을 java에 강제로 설치했기 때문에 설치시 php의 기본 문자셋이 표시됩니다. – Joscandreu

0

게으른 단어의 경우 한 단어가 천 개 단어보다 좋습니다. 나는 마침내 무슨 일이 일어 났는지 이해했다. 메서드 업데이트는 다이제스트에 바이트를 추가하므로 $ password. {$ salt}를 추가하면 mda.update (암호 바이트) 및 mda.digest ("{$ salt}"바이트를 수행하는 것과 동일합니다. .. 나는 그것이 작동하지 않는 이유 미친 발견을 거라고하고이 답변의 모든 때문에

고마워를 을이 자바 서버에서 작동하는 예입니다 SHA512에 문제가있는 사람들을위한

public static String hashPassword(String password, String salt) throws Exception { 
     String result = password; 
     String appendedSalt = new StringBuilder().append('{').append(salt).append('}').toString(); 
     String appendedSalt2 = new StringBuilder().append(password).append('{').append(salt).append('}').toString(); 

     if(password != null) { 
      //Security.addProvider(new BouncyCastleProvider()); 

      MessageDigest mda = MessageDigest.getInstance("SHA-512"); 
      byte[] pwdBytes = password.getBytes("UTF-8"); 
      byte[] saltBytes = appendedSalt.getBytes("UTF-8"); 
      byte[] saltBytes2 = appendedSalt2.getBytes("UTF-8"); 
      byte[] digesta = encode(mda, pwdBytes, saltBytes); 

      //result = new String(digesta); 
      System.out.println("first hash: " + new String(Base64.encode(digesta),"UTF-8")); 
       for (int i = 1; i < ROUNDS; i++) { 

        digesta = encode(mda, digesta, saltBytes2); 
       } 
       System.out.println("last hash: " + new String(Base64.encode(digesta),"UTF-8")); 

       result = new String(Base64.encode(digesta)); 
     } 
     return result; 
    } 

private static byte[] encode(MessageDigest mda, byte[] pwdBytes, 
      byte[] saltBytes) { 
     mda.update(pwdBytes); 
     byte [] digesta = mda.digest(saltBytes); 
     return digesta; 
    } 
관련 문제