你能用PHP得到同样的JavaSHA-1吗?
我发现自己需要将网站平台从Java更改为PHP,但我想保留所有用户的密码 在将哈希值作为密码写入网站之前,我让此代码进行密码哈希:你能用PHP得到同样的JavaSHA-1吗?,java,php,hash,passwords,sha,Java,Php,Hash,Passwords,Sha,我发现自己需要将网站平台从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
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编码的?)值与哈希值的JavaBase64解码值相比……这可能与我在PHP中的密码不是首先进行UTF-8字节编码(我在PHP中如何做到这一点)有关吗
p.s.
另一件奇怪的事…我在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
绝对不是散列。它是从字节[]
到字符串的隐式转换的结果
看起来你是这样做的:
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
/**
*计算字符串参数的SHA-1哈希
*
*@param arg要编码的UTF-8字符串
*@以字符串形式返回sha1哈希。
*/
公共静态字符串计算HA1OFSTRING(字符串参数){
试一试{
返回计算ha1ofbytearray(arg.getBytes((“UTF-8”);
}捕获(不支持DencodingException ex){
抛出新的不支持操作异常(ex);
}
}
私有静态字符串计算ha1ofbytearray(字节[]arg){
试一试{
MessageDigest md=MessageDigest.getInstance(“SHA-1”);
md.update(arg);
字节[]res=md.digest();
返回到hextstring(res);
}捕获(nosuchalgorithmex异常){
抛出新的不支持操作异常(ex);
}
}
私有静态字符串到十六进制字符串(字节[]v){
StringBuilder sb=新StringBuilder(v.length*2);
对于(int i=0;i>>4)).追加(十六进制数字.charAt(b&0xF));
}
使某人返回字符串();
}
PHP()默认情况下将输出的每个字节编码为十六进制,但您可以通过将true
作为第二个参数传递来获得原始输出:
$digest = sha1($password, true); // This returns the same string of bytes as md.digest()
然后将摘要传递给,您就完成了:
base64_encode(sha1($password, true));
这将返回与java代码完全相同的SHA-1哈希值。您需要正确格式化代码。在每行前面放置四个空格或一个制表符。@Alberteddu:这可以通过选择代码并单击“{}”图标来完成。[B@14e1f2b
不是Base64()的值。解码(哈希)
,它是数组的常规字符串表示形式,形式为[
+ArrayType+@
+hashCode。您要做的是遍历数组,而不仅仅是简单地编写System.out.println(array\u var);
PHP中的sha1函数返回一个十六进制数的字符串,而Java代码返回一个base64编码的字符串。非常感谢大家指出我的错误。但是,正确的字节[]到字符串转换会返回我在PHP中得到的40个字符吗?我为格式错误道歉(我也是一个非常讨厌的人)@Nubie:如果PHP生成一个十六进制值,您可以尝试将结果数组转换为十六进制字符串,并检查它们是否匹配。@axtavt有点挑剔,在[B@13e1f2b
后面的部分实际上是一个散列,但显然不是Nubie想要的部分。它是toString()的输出方法,其主体是:getClass().getName()+“@”+Integer.toHexString(hashCode());
base64_encode(sha1($password, true));