【问题标题】:android md5 encryption does not match mysql or php?android md5加密不匹配mysql或php?
【发布时间】:2012-02-10 19:33:39
【问题描述】:

** 问题已解决。我的输入在从 EditText 到运行该函数的 Java 的过程中被更改。这也很明显。我真的觉得很笨。浪费大家的时间真的很抱歉……

我正在尝试让 android 使用 MD5 加密字符串,但发现它与 MySQL 和 PHP 中使用的 md5 函数的结果不匹配。

例如:

PHP/MYSQL: 字符串:password 哈希:5f4dcc3b5aa765d61d8327deb882cf99

安卓: 字符串:password 哈希:bc4a7f3b32b2a85688a53c49df19cd95

我已经搜索并查看了 stackoverflow 上遇到相同问题的人,但我仍然没有找到答案。 我使用了很多方法并尝试更改字符代码,但仍然无法匹配。

这是我目前保存在项目中的函数(这不起作用):

public static String md5(String input){
        String result = input;
        if(input != null) {
            MessageDigest md;
            try {
                md = MessageDigest.getInstance("MD5");
            md.update(input.getBytes());
            BigInteger hash = new BigInteger(1, md.digest());
            result = hash.toString(16);
            if ((result.length() % 2) != 0) {
                result = "0" + result;
            } 
            }catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
                return null;
            }
        }
        return result;
    }

任何帮助将不胜感激。

【问题讨论】:

  • 嗯...当我在标准 Sun JVM (1.6) 中运行您的代码时,我得到了正确的输出。我认为它与input.getBytes() 没有任何关系,因为Android 上的默认字符集应该是UTF-8。它可能与MessageDigest 有关。尽管如此,我会尝试使用getBytes("UTF-8") 来明确。
  • 在将字符串转换为字节数组时,是否尝试使用相同的字符串编码?
  • Snippet 看起来不错,因为依赖于平台默认编码(尽管 Android 已经使用 UTF-8)。您确定输入中没有空格吗?对于另一个 sn-p,另请参阅:stackoverflow.com/questions/5494447/…
  • 看来我的输入确实在从 EditText 抓取到 Java 的过程中发生了变化......我觉得真的很愚蠢。
  • 这是否用于密码散列?普通的 md5/sha1/sha2 对于密码哈希来说是个坏主意。

标签: java android security md5


【解决方案1】:

两件事...首先,我会避免使用BigInteger。您想将字节数组转换为十六进制表示形式 - 因此请使用专为实现此目的而设计的代码,例如 Apache Common Codec。当您想专注于 MD5 输出是什么时,它会阻止您追逐转换问题。编辑:好的,听起来代码不是问题,获取输入是 - 但我仍然会在这里进行更改。它应该以更易读的代码结束,更清楚地表达你想要实现的目标。

其次,这段代码:

md.update(input.getBytes());

... 正在使用平台默认编码。这几乎从来都不是一个好主意。明确指定编码,即使您知道平台默认编码是什么。在这种情况下它是无害的,但无论如何你都应该修复代码,以防你不得不处理非 ASCII 文本。

【讨论】:

  • 示例输入仅包含 ASCII 兼容字符,因此未指定字符编码不是 OP 的具体问题的原因。此外,您并没有真正解释为什么 BigInteger 是一个坏主意,我对此很好奇。
  • @BalusC:虽然在这种特殊情况下它只有 ASCII 字符,但使用默认编码是一个等待发生的错误,所以我更不用说它了。我怀疑问题出在BigInteger 这里 - 我不知道它为什么会失败(它适用于桌面 Java)但从根本上说它似乎不是一种明智的做法与大整数无关的东西——它是关于字节的十六进制表示。
  • 嗯,答案暗示这是 OP 的具体问题的两个可能原因之一(因此在这种特殊情况下是不正确的)。好的,因此您完全猜测BigInteger 是可能的原因。我仍然想知道它失败的技术原因,因为它应该可以正常工作,即使它滥用了BigInteger 类。
  • @BalusC:看到评论后,看起来这是一个完全不同的问题 - 但我仍然会进行这两项更改:) 已编辑以反映这一点。
  • 我的原始函数确实将字节数组转换为十六进制,但在它不起作用之后,我开始尝试我能找到的任何东西。原来我的输入被改变了。我觉得现在发布这个真的很糟糕......
【解决方案2】:

问题很可能是由于字符编码造成的。我知道您说过您尝试了不同的字符代码,但您发布的代码没有。

检查这个问题的答案: How can I generate an MD5 hash?

MessageDigest 类可以为您提供 MD5 的实例 摘要。

在使用字符串和加密类时,请务必 始终指定您希望字节表示的编码。如果 您只需使用 string.getBytes() 它将使用平台默认值。 (不是 所有平台都使用相同的默认值)

byte[] bytesOfMessage = yourString.getBytes("UTF-8");

【讨论】:

  • 虽然您完全正确,但对于仅包含 ASCII 字符的单词并不重要。它几乎在每个字符编码中都产生相同的字节(除了像 EBCDIC 那样与 ASCII 竞争的古代编码)。根据所使用的字符编码,只有超出 ASCII 范围的字符可能会给出不同的字节。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-01-09
  • 2011-05-24
相关资源
最近更新 更多