【问题标题】:Java SHA not woking. Hash value dosen't equal String. Is there an issue with my encoding?Java SHA 不工作。哈希值不等于字符串。我的编码有问题吗?
【发布时间】:2018-12-21 16:43:50
【问题描述】:

基本上我有这个

   if (args.length != 1) {
        System.err.println("Usage: java MyMd5 <message>");
        System.exit(1);
    }
    try {
        // get message
        byte[] message = args[0].getBytes("UTF8");
        // create message digest object for MD5
        MessageDigest messageDigest = MessageDigest.getInstance("SHA");
        // System.out.println("Provider: " +
        messageDigest.getProvider().getInfo();
        // create message digest
        messageDigest.update(message);
        byte[] md = messageDigest.digest();
        // print result
        System.out.println("Message Digest Algorithm: MD5");
        System.out.println("Message: " + new String(message));
        System.out.println("Message Digest: \"" + new String(md, "UTF8") + "\"");
        String HashPassword=new String(md, "UTF8");
        System.out.println(HashPassword);
        System.out.println(HashPassword.equals("???8p???W?B:??N?~"));

但不知何故,当我尝试比较它时返回 false。我的编码有问题吗?谢谢!

    Message Digest Algorithm: MD5 
    Message: pass123
    Message Digest: "???8p???W?B:??N?~"
    ???8p???W?B:??N?~
    false

【问题讨论】:

  • 主要问题是您在字节数组和字符串之间进行转换,在多个地方假装字节数组包含 UTF-8 编码文本,而实际上它根本不是编码文本。
  • ? 表示不可打印的字符,因此 ? 不一定等于 ? - 在字节级别进行比较
  • "Java MD5 not woking.":您注意到这不太可能吗? Java 中的 MD5 已经存在很多年了。

标签: java hash java-security


【解决方案1】:

问题在于不必要的编码,使用 md5 我们必须以正确的方式对字符串进行编码,而不是使用 UTF8 编码

public static void main(String[] args) throws Exception {
    String pass = "pass123";
    byte[] message = pass.getBytes();
    MessageDigest messageDigest = MessageDigest.getInstance("SHA");
    messageDigest.update(message);
    byte[] md = messageDigest.digest();
    StringBuffer sb = new StringBuffer();
    for (int i = 0; i < md.length; i++) {
        sb.append(Integer.toString((md[i] & 0xff) + 0x100, 16).substring(1));
    }
    System.out.println("encoded pass:" + sb.toString());
    System.out.println(sb.toString().equals("aafdc23870ecbcd3d557b6423a8982134e17927e"));
}

【讨论】:

    【解决方案2】:

    如果我正确理解了您的问题,您希望将新生成的哈希字符串与现有哈希字符串(存储在数据库或其他地方)进行比较。可以使用上面提供的代码,例如,如果您将生成的值(而不是从控制台复制)存储到数据库,您将获得true,然后将其与新生成的值进行比较。

    但是当您生成哈希时,它包含符号(字符),在任何字符串编码中都没有正确的表示。因此,没有人不会将散列存储为纯字符串。通常它们存储在hex string 表示或Base64 表示中。

    使用下面提供的hex strings 实现:

    public static void main(String[] args) throws Exception { // args = ["Hello world"]
    if (args.length != 1) {
        System.err.println("Usage: java MyMd5 <message>");
        System.exit(1);
    }
    // get message
    byte[] message = args[0].getBytes("UTF8"); //You may have problems with encoding here. In Windows, for example, with symbols that are out of English alphabet range  
    // create message digest object for MD5
    MessageDigest messageDigest = MessageDigest.getInstance("SHA");
    // System.out.println("Provider: " +
    messageDigest.getProvider().getInfo();
    // create message digest
    messageDigest.update(message);
    byte[] md = messageDigest.digest();
    System.out.println("Digest: " + byteArrayToHexString(md));
    System.out.println("Is equals? " + byteArrayToHexString(md).equals("7b502c3a1f48c8609ae212cdfb639dee39673f5e"));
    }
    
    private static String byteArrayToHexString(byte[] array) {
        StringBuilder result = new StringBuilder(array.length);
        IntStream.range(0, array.length)
            .forEach(i -> result.append(Integer.toString( (array[i] & 0xff) + 0x100, 16).substring(1)));
        return result.toString();
    }
    

    此外,在提供的示例中提到您使用的是MD5,但实际上它是SHAMessageDigest messageDigest = MessageDigest.getInstance("SHA");

    【讨论】:

      猜你喜欢
      • 2015-05-29
      • 1970-01-01
      • 2014-08-19
      • 2018-04-24
      • 2012-02-26
      • 2018-07-16
      • 2011-03-07
      • 2012-05-14
      • 1970-01-01
      相关资源
      最近更新 更多