gpt4 book ai didi

java - 如何在 php 中获得与 spring 安全框架中的encodePassword 相同的值?

转载 作者:行者123 更新时间:2023-12-02 05:45:19 25 4
gpt4 key购买 nike

我需要从 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的结果值。我该怎么办?

最佳答案

这是我解决这个问题所经历的过程;我在这里完整地写下它是为了帮助您了解整个过程,而不仅仅是这个解决方案。

来源ShaPasswordEncoder (为简洁起见,删除了注释):

public class ShaPasswordEncoder extends MessageDigestPasswordEncoder {
public ShaPasswordEncoder() {
this(1);
}

public ShaPasswordEncoder(int strength) {
super("SHA-" + strength);
}
}

对我来说看起来像是一个非常薄的包装类。调用 new ShaPasswordEncoder(256) 实际上与调用 new MessageDigestPasswordEncoder("SHA-256") 相同,所以让我们看一下 that 的源代码:

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。它的工作原理正如你所期望的那样。从编号行:

  1. 对密码加盐
    • 这使用了看似无辜的 mergePasswordAndSalt 方法,我们接下来会看看
  2. 对加盐密码进行哈希处理
    • 请注意此处的 UTF-8 编码 - 这并不总是默认编码
  3. 重复散列输出以进行额外的迭代
    • 请注意,messageDigest.digest 方法的输入和输出都是原始字节数组,而不是十六进制编码的字符串
  4. 返回最终输出的十六进制编码字符串

正如所 promise 的,这是 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 */
}
}

再次从编号部分来看:

  1. 检查密码是否为空
  2. 检查是否存在 {} 字符;由于下一点,这些是不允许的
  3. password{salt} 的形式输出加盐密码

在这里,我们了解了为什么您尝试在 PHP 中重现该算法失败了。

根据这些信息,看看您是否可以构建一个具有相同行为方式的 PHP 函数。今晚晚些时候,当我有权访问测试环境时,我将在完整的 PHP 解决方案中进行编辑。

关于java - 如何在 php 中获得与 spring 安全框架中的encodePassword 相同的值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56100628/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com