如何在php中获得与spring弹性框架中的encodePassword相同的值?

我需要从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结果:


9379d5a5fdd899cdf588b075988b9e94d2b3fe5cb44e593dd4a241f4757c8eec

php结果:


hash_pbkdf2 result : 2794f28c44aa958663637ebeed391b533854fb2f4b7b7d09f521de8c1fe5c6bb

hash result : b0782b680af7a13aeffc61006d2799d69ddc0465c33f376b40d946dd232f62ed

我想让php的结果值等于Java的结果值。我该怎么办?


波斯汪
浏览 732回答 1
1回答

汪汪一只猫

这是我经历过这个过程的过程;&nbsp;我在这里完整地写出来帮助你学习这个过程,而不仅仅是这个解决方案。从ShaPasswordEncoder(为简洁起见删除注释)的来源:public&nbsp;class&nbsp;ShaPasswordEncoder&nbsp;extends&nbsp;MessageDigestPasswordEncoder&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;ShaPasswordEncoder()&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;this(1); &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;ShaPasswordEncoder(int&nbsp;strength)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;super("SHA-"&nbsp;+&nbsp;strength); &nbsp;&nbsp;&nbsp;&nbsp;}}对我来说,看起来像一个非常薄的包装类。呼叫new ShaPasswordEncoder(256)是有效地与调用new MessageDigestPasswordEncoder("SHA-256"),所以让我们来看看源说:public&nbsp;class&nbsp;MessageDigestPasswordEncoder&nbsp;extends&nbsp;BaseDigestPasswordEncoder&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;final&nbsp;String&nbsp;algorithm; &nbsp;&nbsp;&nbsp;&nbsp;private&nbsp;int&nbsp;iterations&nbsp;=&nbsp;1; &nbsp;&nbsp;&nbsp;&nbsp;[...] &nbsp;&nbsp;&nbsp;&nbsp;public&nbsp;String&nbsp;encodePassword(String&nbsp;rawPass,&nbsp;Object&nbsp;salt)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;String&nbsp;saltedPass&nbsp;=&nbsp;mergePasswordAndSalt(rawPass,&nbsp;salt,&nbsp;false);&nbsp;&nbsp;&nbsp;/*&nbsp;1&nbsp;*/ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;MessageDigest&nbsp;messageDigest&nbsp;=&nbsp;getMessageDigest(); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;byte[]&nbsp;digest&nbsp;=&nbsp;messageDigest.digest(Utf8.encode(saltedPass));&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;2&nbsp;*/ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//&nbsp;"stretch"&nbsp;the&nbsp;encoded&nbsp;value&nbsp;if&nbsp;configured&nbsp;to&nbsp;do&nbsp;so &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;for&nbsp;(int&nbsp;i&nbsp;=&nbsp;1;&nbsp;i&nbsp;<&nbsp;this.iterations;&nbsp;i++)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;3&nbsp;*/ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;digest&nbsp;=&nbsp;messageDigest.digest(digest); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(getEncodeHashAsBase64())&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;Utf8.decode(Base64.encode(digest)); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;else&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;new&nbsp;String(Hex.encode(digest));&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;4&nbsp;*/ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;[...]}啊,现在我们到了某个地方。那里有一些额外的方法,但我们现在才真正关心encodePassword。它的工作原理与你期望的一样。从编号行:加密密码这使用了看起来很无辜的mergePasswordAndSalt方法,我们接下来会看一下哈希盐渍密码请注意这里的UTF-8编码 - 这并不总是默认编码重复散列输出以进行其他迭代请注意,messageDigest.digest方法的输入和输出都是原始字节数组,而不是十六进制编码的字符串返回最终输出的十六进制编码字符串正如所承诺的,这是mergePasswordAndSalt方法的来源:protected&nbsp;String&nbsp;mergePasswordAndSalt(String&nbsp;password,&nbsp;Object&nbsp;salt,&nbsp;boolean&nbsp;strict)&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(password&nbsp;==&nbsp;null)&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;1&nbsp;*/ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;password&nbsp;=&nbsp;""; &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;(strict&nbsp;&&&nbsp;(salt&nbsp;!=&nbsp;null))&nbsp;{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;2&nbsp;*/ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;((salt.toString().lastIndexOf("{")&nbsp;!=&nbsp;-1) &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;||&nbsp;(salt.toString().lastIndexOf("}")&nbsp;!=&nbsp;-1))&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;throw&nbsp;new&nbsp;IllegalArgumentException("Cannot&nbsp;use&nbsp;{&nbsp;or&nbsp;}&nbsp;in&nbsp;salt.toString()"); &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;} &nbsp;&nbsp;&nbsp;&nbsp;if&nbsp;((salt&nbsp;==&nbsp;null)&nbsp;||&nbsp;"".equals(salt))&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;password; &nbsp;&nbsp;&nbsp;&nbsp;}&nbsp;else&nbsp;{ &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return&nbsp;password&nbsp;+&nbsp;"{"&nbsp;+&nbsp;salt.toString()&nbsp;+&nbsp;"}";&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*&nbsp;3&nbsp;*/ &nbsp;&nbsp;&nbsp;&nbsp;}}再次从编号部分:检查空密码检查是否存在{和}字符;&nbsp;由于下一点,这些是不允许的在表单中输出salted密码&nbsp;password{salt}在这里,我们看到为什么您尝试在PHP中复制此算法失败。从这些信息中,看看是否可以构建一个行为相同的PHP函数。我将在今晚晚些时候编辑一个完整的PHP解决方案,当时我可以访问一个环境来测试它。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Java