2011-09-30 50 views
10

我有一个包含用户名和密码的SQL表。密码使用MessageDigest的摘要()方法进行编码。如果我使用MessageDigest的digest()方法对密码进行编码(比如说“abcdef12”),然后将其转换为十六进制值,则String与使用PHP的SHA1方法执行相同操作时不同。我希望这些值是完全一样的。用来编码密码Java的MessageDigest SHA1算法返回的结果不是SHA1的函数php

代码:

public static String convertStringToHex(String str) { 

    char[] chars = str.toCharArray(); 

    StringBuffer hex = new StringBuffer(); 
    for (int i = 0; i < chars.length; i++) { 
     hex.append(Integer.toHexString((int) chars[i])); 
    } 

    return hex.toString(); 
} 

密码:abcdef12

这里的

MessageDigest md = MessageDigest.getInstance("SHA-1"); 
byte[] passbyte; 
passbyte = "abcdef12".getBytes("UTF-8"); 
passbyte = md.digest(passbyte); 

字符串为十六进制的转换就是采用这种方法来完成由许多SHA1-Hash在线生成器和PHP SHA1()返回的密码 - 功能:d253e3b d69ce1e7ce6074345fd5faa1a3c2e89ef

这里的密码通过消息摘要作为编码:d253e3bd69ce1e7ce674345fd5faa1a3c2e2030ef

我是不是忘了什么东西?

伊戈尔。

编辑:我发现有人有类似的问题:C# SHA-1 vs. PHP SHA-1...Different Results?。解决方案是更改编码..但我不能更改服务器端的编码,因为该SQL表中的密码不是由我的应用程序创建的。 我使用JavaScript SHA1类(更精确地说:Google Web Toolkit类)使用客户端SHA1编码。它的工作原理,并预期编码字符串,但显然使用ASCII字符..

回答

3

它与编码无关。输出将完全不同。

对于初学者,您的功能convertStringToHex()不输出前导零,也就是07只变成7

其余的(更改892030)也可能与该功能有关。尝试在passbyte = md.digest(passbyte);之后查看passbyte的值。

+0

谢谢!你的答案解决了我的问题。我无法正确地将字节数组转换为十六进制字符串!我使用@stivlo的方法,它效果很好!我打算将这个回答标记为正确的,但在这种情况下,我希望我可以将两个回答都标记为正确回答!谢谢你们俩! – Igor

5

我有同样的摘要作为PHP与我的Java SHA-1散列函数:

public static String computeSha1OfString(final String message) 
    throws UnsupportedOperationException, NullPointerException { 
     try { 
       return computeSha1OfByteArray(message.getBytes(("UTF-8"))); 
     } catch (UnsupportedEncodingException ex) { 
       throw new UnsupportedOperationException(ex); 
     } 
} 

private static String computeSha1OfByteArray(final byte[] message) 
    throws UnsupportedOperationException { 
     try { 
      MessageDigest md = MessageDigest.getInstance("SHA-1"); 
      md.update(message); 
      byte[] res = md.digest(); 
      return toHexString(res); 
     } catch (NoSuchAlgorithmException ex) { 
      throw new UnsupportedOperationException(ex); 
     } 
} 

我已经添加到我的单元测试:

String sha1Hash = StringHelper.computeSha1OfString("abcdef12"); 
assertEquals("d253e3bd69ce1e7ce6074345fd5faa1a3c2e89ef", sha1Hash); 

该类的完整源代码是on github

+0

事实上 - 你的代码产生正确的SHA1(或者更确切地说:与php的SHA1相同)。但是,我正在编写一个必须登录到现有数据库的应用程序。该数据库不是由我自己创建的(也不是密码加密)。但**它使用MessageDigest,就像我的示例**中所写,因此在该String上运行Base64.decode会返回不同的结果(在我的示例中指定的结果),而不是您的正确结果,我也使用JavaScript SHA1-类。有什么方法可以比较它们吗?我不知道MessageDigest如何返回其他结果。 – Igor

2

试试这个 - 这是为我工作:

MessageDigest md = MessageDigest.getInstance(algorithm); 
md.update(original.getBytes()); 
byte[] digest = md.digest(); 
StringBuffer sb = new StringBuffer(); 
for (byte b : digest) { 
    sb.append(Integer.toString((b & 0xff) + 0x100, 16).substring(1)); 
} 
return sb.toString(); 

问候, Konki

2

或者试试这个:

MessageDigest md = MessageDigest.getInstance("SHA-1"); 
md.update(clearPassword.getBytes("UTF-8")); 
return new BigInteger(1 ,md.digest()).toString(16)); 

干杯罗伊