【问题标题】:Generating MD5 Hash生成 MD5 哈希
【发布时间】:2013-07-30 12:16:48
【问题描述】:

我有一个发送给我的密码,该密码使用基于数字 ID 的 MD5 散列的 AES 加密

从请求中,我可以使用其他属性获取数据库中的 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;
    }

基于 id 1 的 md5Value 长度为 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
    }

【问题讨论】:

    标签: java security aes md5


    【解决方案1】:

    问题在于字符串是十六进制的。我建议您使用 apache commons-code 包。那里有一个用于哈希的实用程序类。

    http://commons.apache.org/proper/commons-codec/apidocs/org/apache/commons/codec/digest/DigestUtils.html

    那么就可以使用下面的代码了:

    String md5 = DigestUtils.md5Hex(id);
    // or
    byte[] md5 = DigestUtils.md5(id);
    

    【讨论】:

    • 不知道这个库,使用它并且它的伎俩。欢呼伙计们
    【解决方案2】:

    您得到的字节数组是一个 md5 哈希,但具有十六进制值。

    您不能只将数组转换为字符串。您必须使用采用这些六进制值并为您提供正确字符串的算法对其进行转换。

    您可以在下面看到获取 32 位 MD5Hash-String 的算法,也许这会有所帮助:

    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 "";
        }
    }
    

    【讨论】:

      【解决方案3】:

      这个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

      【讨论】:

        猜你喜欢
        • 2017-05-24
        • 1970-01-01
        • 2011-07-26
        • 2011-08-17
        • 2015-08-14
        • 1970-01-01
        • 2013-09-08
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多