2012-11-30 5 views
5

Thứ gì đó ở phía sau đầu tôi đang nói với tôi rằng tôi đang thiếu điều gì đó hiển nhiên ở đây.Thuật toán MessageDigest MD5 không trả lại những gì tôi mong đợi

Tôi đang tích hợp dự án java hiện có với api của bên thứ ba sử dụng băm md5 của khóa api để xác thực. Nó không làm việc cho tôi, và trong quá trình gỡ lỗi, tôi nhận ra rằng các băm tôi tạo ra không khớp với các ví dụ mà chúng đã cung cấp. Tôi đã tìm thấy một số trang web tạo ra băm MD5 từ chuỗi để kiểm tra các ví dụ của họ, và theo như tôi có thể nói tôi sai và họ đúng.

ví dụ: theo this website, chuỗi "hello" tạo ra một mã băm "5d41402abc4b2a76b9719d911017c592". (FWIW Tôi không biết gì về trang web này ngoại trừ việc nó có vẻ băm chính xác những ví dụ mà tôi có). Khi tôi chạy nó thông qua mã của tôi tôi nhận được:

XUFAKrxLKna5cZ2REBfFkg ==

Dưới đây là phương pháp đơn giản, tôi đang sử dụng để tạo ra md5 hash/chuỗi .:

private String md5(String md5Me) throws Exception { 
    MessageDigest md = MessageDigest.getInstance("MD5"); 
    md.reset(); 
    md.update(md5Me.getBytes("UTF-8")); 

    return Base64.encodeBase64String(md.digest()); 
} 

tôi đã sử dụng rất phương pháp tương tự để xác thực thành công một API khác bằng thuật toán SHA1 tuần trước. Tôi tự hỏi nếu vấn đề có liên quan đến org.apache.commons.net.util.Base64.encodeBase64String ... Bất kỳ trợ giúp nào được đánh giá rất cao, nếu chỉ một số thử nghiệm để xem liệu byteArray có đúng hay không nhưng chuỗi được chuyển đổi sai .

+1

md.digest() phải chứa byte bạn đang tìm kiếm, bạn mã hóa chúng hơn nữa bằng thuật toán Base64 và nhận kết quả khác nhau – hoaz

+0

Tôi cần chuyển đổi các byte đó thành Chuỗi cho yêu cầu http, có cách nào tốt hơn để làm điều đó không ? – eric

+1

new String (byte [] bytes) – Andy

Trả lời

8

ví dụ, theo trang web này, chuỗi "hello" tạo ra một hash của "5d41402abc4b2a76b9719d911017c592". (FWIW Tôi không biết gì về trang web này ngoại trừ việc nó có vẻ băm chính xác những ví dụ mà tôi có). Khi tôi chạy nó thông qua mã của tôi tôi nhận được:

XUFAKrxLKna5cZ2REBfFkg ==

Cả hai đều là cách đúng đắn về đại diện cho cùng một băm mười sáu byte. 5d41402abc4b2a76b9719d911017c592 thể hiện từng byte của băm dưới dạng hai chữ số thập lục phân, trong khi XUFAKrxLKna5cZ2REBfFkg== sử dụng Base-64 để biểu thị mỗi ba byte của băm dưới dạng bốn ký tự.

Để tạo hexadecimal-phiên bản API của bên thứ ba này được mong đợi, bạn có thể thay đổi điều này:

Base64.encodeBase64String(md.digest()); 

này:

String.format("%032x", new BigInteger(1, md.digest())); 

(chủ yếu lấy từ this StackOverflow answer).

Tuy nhiên, bạn có thể muốn xem xét sử dụng thư viện bên ngoài cho việc này. Perception, trong một bình luận ở trên, đề cập đến Apache Commons DigestUtils. Nếu bạn sử dụng, bạn sẽ muốn the md5hex method.

+0

Đánh dấu điều này là chính xác vì nó giải quyết được vấn đề của tôi, giải thích những gì đang xảy ra và tham khảo đề xuất của Perception để sử dụng DigestUtils (cũng hoạt động). Cảm ơn! – eric

+0

@eric: Bạn được chào đón! – ruakh

2

Thuật toán băm md5 là một phần của API java lõi nên không cần bất kỳ thư viện bên ngoài nào. Đây là phương pháp tôi sử dụng để mã hóa mật khẩu với MD5.

import java.security.MessageDigest; 

/** 
* Use to encrypt passwords using MD5 algorithm 
* @param password should be a plain text password. 
* @return a hex String that results from encrypting the given password. 
*/ 
public static String encryptPassword(String password) { 
    try { 
     MessageDigest md = MessageDigest.getInstance("MD5"); 
     md.update(password.getBytes()); 

     byte byteData[] = md.digest(); 

     StringBuffer hexString = new StringBuffer(); 
     for (int i=0;i<byteData.length;i++) { 
      String hex=Integer.toHexString(0xff & byteData[i]); 
      if(hex.length()==1) hexString.append('0'); 
      hexString.append(hex); 
     } 
     return hexString.toString(); 
    } 
    catch(java.security.NoSuchAlgorithmException missing) { 
     return "Error."; 
    } 
}