2013-07-30 40 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