我需要从php获得与使用Spring Security ShaPasswordEncoder对象的encodePassword方法获得的结果相同的值。我没有权限修改相应的Java代码,所以php本身就可以解决这个问题。Java代码:ShaPasswordEncoder shaPasswordEncoder = new ShaPasswordEncoder(256);shaPasswordEncoder.setIterations(1000);String password = "123456789";String salt = "123456";String hash2 = shaPasswordEncoder.encodePassword(password, salt);System.out.println(hash2);我尝试了以下方法:$password = "123456789"; $salt = "123456";$hash = hash_pbkdf2('sha256', $password, $salt, 1000);echo 'hash_pbkdf2 result : '.$hash.'<br>';$out = $salt.$password;for ($i = 0; $i < 1000; $i++) $out = hash('sha256', $out);echo 'hash result : '.$out.'<br>';Java结果:9379d5a5fdd899cdf588b075988b9e94d2b3fe5cb44e593dd4a241f4757c8eecphp结果:hash_pbkdf2 result : 2794f28c44aa958663637ebeed391b533854fb2f4b7b7d09f521de8c1fe5c6bbhash result : b0782b680af7a13aeffc61006d2799d69ddc0465c33f376b40d946dd232f62ed我想让php的结果值等于Java的结果值。我该怎么办?
1 回答
汪汪一只猫
TA贡献1898条经验 获得超8个赞
这是我经历过这个过程的过程; 我在这里完整地写出来帮助你学习这个过程,而不仅仅是这个解决方案。
从ShaPasswordEncoder
(为简洁起见删除注释)的来源:
public class ShaPasswordEncoder extends MessageDigestPasswordEncoder { public ShaPasswordEncoder() { this(1); } public ShaPasswordEncoder(int strength) { super("SHA-" + strength); }}
对我来说,看起来像一个非常薄的包装类。呼叫new ShaPasswordEncoder(256)
是有效地与调用new MessageDigestPasswordEncoder("SHA-256")
,所以让我们来看看源说:
public class MessageDigestPasswordEncoder extends BaseDigestPasswordEncoder { private final String algorithm; private int iterations = 1; [...] public String encodePassword(String rawPass, Object salt) { String saltedPass = mergePasswordAndSalt(rawPass, salt, false); /* 1 */ MessageDigest messageDigest = getMessageDigest(); byte[] digest = messageDigest.digest(Utf8.encode(saltedPass)); /* 2 */ // "stretch" the encoded value if configured to do so for (int i = 1; i < this.iterations; i++) { /* 3 */ digest = messageDigest.digest(digest); } if (getEncodeHashAsBase64()) { return Utf8.decode(Base64.encode(digest)); } else { return new String(Hex.encode(digest)); /* 4 */ } } [...]}
啊,现在我们到了某个地方。那里有一些额外的方法,但我们现在才真正关心encodePassword
。它的工作原理与你期望的一样。从编号行:
加密密码
这使用了看起来很无辜的
mergePasswordAndSalt
方法,我们接下来会看一下哈希盐渍密码
请注意这里的UTF-8编码 - 这并不总是默认编码
重复散列输出以进行其他迭代
请注意,
messageDigest.digest
方法的输入和输出都是原始字节数组,而不是十六进制编码的字符串返回最终输出的十六进制编码字符串
正如所承诺的,这是mergePasswordAndSalt
方法的来源:
protected String mergePasswordAndSalt(String password, Object salt, boolean strict) { if (password == null) { /* 1 */ password = ""; } if (strict && (salt != null)) { /* 2 */ if ((salt.toString().lastIndexOf("{") != -1) || (salt.toString().lastIndexOf("}") != -1)) { throw new IllegalArgumentException("Cannot use { or } in salt.toString()"); } } if ((salt == null) || "".equals(salt)) { return password; } else { return password + "{" + salt.toString() + "}"; /* 3 */ }}
再次从编号部分:
检查空密码
检查是否存在
{
和}
字符; 由于下一点,这些是不允许的在表单中输出salted密码
password{salt}
在这里,我们看到为什么您尝试在PHP中复制此算法失败。
从这些信息中,看看是否可以构建一个行为相同的PHP函数。我将在今晚晚些时候编辑一个完整的PHP解决方案,当时我可以访问一个环境来测试它。
添加回答
举报
0/150
提交
取消