你能用PHP获得相同的Java SHA-1吗?

我发现自己需要将网站平台从Java更改为PHP,但我想保留所有用户的密码……

在将散列值作为网站密码写入之前,我有这段代码做密码散列:

MessageDigest md = null; md = MessageDigest.getInstance("SHA"); md.update(plaintext.getBytes("UTF-8")); byte raw[] = md.digest(); hash = new Base64().encodeToString(raw).replaceAll("\n", "").replaceAll("\r", ""); 

我认为Java代码对密码进行了SHA-1散列,但在此之前,它是字节编码为UTF-8,之后是Base64编码。

我想让一个PHP代码做同样的事情,即为与Java相同的密码返回相同的哈希值,只是看起来我做的SHA-1哈希的PHP代码不会返回相同的SHA (-1,而不是Base64编码,我认为?)与哈希的Java Base64解码值相比时的值……这可能与我在PHP中的密码首先不是UTF-8字节编码这一事实有关(我怎么能用PHP做到这一点?

PS

另一个奇怪的事情……我在Java中的密码长度都是28个字符(通常类似于这个rnwn4zTNgH30l4pP8V05lRVGmF4= )……但这些密码哈希值的Base64().decode(hash)值是10个字符长(例如[B@14e1f2b )。

我认为Base64为每3个章程做了额外的1个字符(28或27,不包括padding = charter,比那些10个字符大三分之一)所以我在做某些解码调用错误可能???

最重要的是,PHP中的SHA-1密码散列值是40个字符长(在UTF-8 mysql数据库中),如dd94709528bb1c83d08f3088d4043f4742891f4f

[B@14e1f2b绝对不是哈希。 这是从byte[]String的隐式转换的结果。

看起来你做这样的事情:

 String decodedHash = Base64().decode(hash); // Produces [B@14e1f2b 

但是,哈希的正确表示是字节数组:

 byte[] decodedHash = Base64().decode(hash); 

我通常使用Java来计算与PHP sha1()函数完全相同的SHA-1哈希,如下所示。 关键是toHexString用于以可打印的方式显示原始字节。 如果您使用PHP函数并希望获得与复杂过程相同的结果,则需要在PHP中使用参数$ raw_output to true来获取原始字节并应用Base64。 完整的源代码 。

 /** * Compute a SHA-1 hash of a String argument * * @param arg the UTF-8 String to encode * @return the sha1 hash as a string. */ public static String computeSha1OfString(String arg) { try { return computeSha1OfByteArray(arg.getBytes(("UTF-8"))); } catch (UnsupportedEncodingException ex) { throw new UnsupportedOperationException(ex); } } private static String computeSha1OfByteArray(byte[] arg) { try { MessageDigest md = MessageDigest.getInstance("SHA-1"); md.update(arg); byte[] res = md.digest(); return toHexString(res); } catch (NoSuchAlgorithmException ex) { throw new UnsupportedOperationException(ex); } } private static String toHexString(byte[] v) { StringBuilder sb = new StringBuilder(v.length * 2); for (int i = 0; i < v.length; i++) { int b = v[i] & 0xFF; sb.append(HEX_DIGITS.charAt(b >>> 4)).append(HEX_DIGITS.charAt(b & 0xF)); } return sb.toString(); } 

PHP的sha1 ()默认将输出的每个字节编码为hex,但您可以通过传递true作为第二个参数来获取原始输出:

 $digest = sha1($password, true); // This returns the same string of bytes as md.digest() 

然后将摘要传递给base64_encode ,您就完成了:

 base64_encode(sha1($password, true)); 

这将返回与java代码完全相同的SHA-1哈希值。