2013-07-30 157 views
0

我有被髮送到我這是使用AES基於數字ID生成MD5哈希

從請求中的MD5哈希加密的密碼,我可以在我與其他屬性數據庫中獲取的ID保持 因此,在服務器端,我需要獲取id,根據該id獲取MD5哈希,並使用AES算法和生成的MD5哈希清除密碼。

我使用以下代碼來獲取MD5哈希

try { 
     byte[] bytesOfMessage = id.getBytes("UTF-8"); 
     log.error "bytesOfMessage length: " + bytesOfMessage.length 
     MessageDigest md = MessageDigest.getInstance("MD5"); 
     byte[] thedigest = md.digest(bytesOfMessage); 

     md5Value = new String(thedigest); 
     log.error "md5Value length: " + md5Value.length() 
     log.error "md5Value bytes length: " + md5Value.getBytes().length 
    } catch (UnsupportedEncodingException e) { 
     log.error "[getMD5EncryptionKey]UnsupportedEncodingException: " + e; 
    } catch (NoSuchAlgorithmException e) { 
     log.error "[getMD5EncryptionKey]NoSuchAlgorithmException: " + e; 
    } 

的md5Value長度是基於1的ID 16,但是當我從這個md5value的字節數,有34個字節

當我去使用這個MD5哈希和javax.crypto.Cipher中的庫來解密密碼,我得到以下信息

java.security.InvalidKeyException:無效的AES密鑰長度:34個字節

任何想法我在這裏做錯了嗎?

我用它來解密消息的代碼如下

try { 
     byte [] encryptionKeyBytes = md5EncryptionKey.getBytes("UTF-8"); 
     Key key = new SecretKeySpec(encryptionKeyBytes, "AES"); 
     Cipher c = Cipher.getInstance("AES"); 
     c.init(Cipher.DECRYPT_MODE, key); 
     byte[] decodedValue = new Base64().decode(encryptedData); 
     byte[] decValue = c.doFinal(decodedValue); 
     String decryptedValue = new String(decValue); 
     return decryptedValue; 
    } catch (InvalidKeyException e) { 
     log.error "[getDecryptedValue] InvalidKeyException: " + e 
    } catch (IllegalBlockSizeException e) { 
     log.error "[getDecryptedValue] InvalidKeyException: " + e 
    } catch (BadPaddingException e) { 
     log.error "[getDecryptedValue] InvalidKeyException: " + e 
    } catch (NoSuchAlgorithmException e) { 
     log.error "[getDecryptedValue] InvalidKeyException: " + e 
    } catch (NoSuchPaddingException e) { 
     log.error "[getDecryptedValue] InvalidKeyException: " + e 
    } catch (Exception e) { 
     log.error "[getDecryptedValue] InvalidKeyException: " + e 
    } 

回答

1

字節數組,你得到的是一個MD5哈希值,但與十六進制值。

你不能只把你的數組轉換成字符串。你必須將它轉換爲一個採用這些hexa值的算法,並給你適當的字符串。

下面你可以看到一個算法,以獲得32位MD5Hash字符串,也許這會有所幫助:

public String createHashString(String s) 
{ 

    try { 
     MessageDigest md = MessageDigest.getInstance("MD5"); 
     byte[] bytesOfMessage = s.getBytes("UTF-8"); 
     byte[] thedigest = md.digest(bytesOfMessage); 


     String hexString = ""; 
     for(byte bi : thedigest) 
     { 
      String hex = Integer.toHexString(0xFF & bi); 
      if (hex.length() == 1) { 

       hexString += "0"; 
      } 
      hexString += (hex); 
     } 

     return hexString; 

    } 
    catch (Exception e) { 
     return ""; 
    } 
} 
1

md5Value = new String(thedigest)是你的問題。 thedigest是二進制的,並且String類不能找出它的編碼(導致它沒有),這會導致二進制值在您嘗試將其從字符串中取出時發生錯位。這就是爲什麼md5Value.getBytes().length是34個字節。直接從thedigest創建SecretKeySpec

Key key = new SecretKeySpec(thedigest, "AES"); 

AES密鑰需要是MD5散列的實際16字節二進制值。

請注意,new String(someBinaryByteArray).getBytes()有時返回您放入的相同字節,但它都依賴於輸入。您的輸入ID值說明了這一點。又如:

String id = "test"; 
byte[] bytesOfMessage = id.getBytes("UTF-8"); 
System.out.println("bytesOfMessage length: " + bytesOfMessage.length); 
MessageDigest md = MessageDigest.getInstance("MD5"); 
byte[] thedigest = md.digest(bytesOfMessage); 
System.out.println("thedigest Hex: " + Hex.encodeHexString(thedigest)); 
String md5Value = new String(thedigest); 
System.out.println("md5Value length: " + md5Value.length()); 
System.out.println("md5Value bytes length: " + md5Value.getBytes().length); 
System.out.println("md5Value Hex: " + Hex.encodeHexString(md5Value.getBytes())); 

Output: 
bytesOfMessage length: 4 
thedigest Hex: 098f6bcd4621d373cade4e832627b4f6 
md5Value length: 16 
md5Value bytes length: 16 
md5Value Hex: 093f6bcd4621d373cade4e832627b4f6 

098f6bcd4621d373cade4e832627b4f6 = 093f6bcd4621d373cade4e832627b4f6