当前位置: 首页 > 知识库问答 >
问题:

创建与symfony2使用java(SHA-512)时相同的哈希

宇文弘懿
2023-03-14

我在这里有一个旧的基于Symfony2的应用程序,我正在用Java开发Dropwizard替代它。我将所有用户记录从旧数据库迁移到新的数据模型中。我还为密码添加了新字段,并导入了旧密码和盐字段。

现在我想做一个众所周知的程序。让用户登录,对新密码字段进行尝试。如果失败,尝试迁移的密码,如果它们工作,用新算法编码明文密码,并将新哈希存储在新密码字段中。因此,用户将密码哈希从旧过程移植到新过程。

听起来简单而正常,一切照旧,但这个Symfony和PHP让我抓狂。

我坚持的地方是用java创建相同的哈希,就像Symfony一样。旧的应用程序使用MessageDigestPasswordEncoder与sha512,Base64编码和5000次迭代,所有默认值;)

重要的方法是:

MessageDigestPasswordEncoder:

public function encodePassword($raw, $salt) {
  if ($this->isPasswordTooLong($raw)) {
    throw new BadCredentialsException('Invalid password.');
  }

  if (!in_array($this->algorithm, hash_algos(), true)) {
    throw new \LogicException(sprintf('The algorithm "%s" is not supported.', $this->algorithm));
  }

  $salted = $this->mergePasswordAndSalt($raw, $salt);
  $digest = hash($this->algorithm, $salted, true);

  // "stretch" hash
  for ($i = 1; $i < $this->iterations; ++$i) {
    $digest = hash($this->algorithm, $digest.$salted, true);
  }

  return $this->encodeHashAsBase64 ? base64_encode($digest) : bin2hex($digest);
}

和BasePasswordEncoder:

protected function mergePasswordAndSalt($password, $salt) {
  if (empty($salt)) {
    return $password;
  }

  if (false !== strrpos($salt, '{') || false !== strrpos($salt, '}')) {
    throw new \InvalidArgumentException('Cannot use { or } in salt.');
  }

  return $password.'{'.$salt.'}';
}

这似乎是直截了当的,但我坚持下去了。当我读到这篇文章时,它确实:

  1. 合并盐和清除文本密码到:"密码{盐}"
  2. 用SHA-512散列这个字符串,并将一个二进制字符串返回到digest变量
  3. 迭代5k次,并使用与合并明文密码连接的摘要将其重新散列为摘要
  4. 将摘要编码到Base64

下面是我在Java中的尝试:

import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.slf4j.Logger;
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;

public void legacyEncryption(String salt, String clearPassword) throws UnsupportedEncodingException, NoSuchAlgorithmException {
  // Get digester instance for algorithm "SHA-512" using BounceCastle
  MessageDigest digester = MessageDigest.getInstance("SHA-512", new BouncyCastleProvider());

  // Create salted password string
  String mergedPasswordAndSalt = clearPassword + "{" + salt + "}";

  // First time hash the input string by using UTF-8 encoded bytes.
  byte[] hash = digester.digest(mergedPasswordAndSalt.getBytes("UTF-8"));

  // Loop 5k times
  for (int i = 0; i < 5000; i++) {
    // Concatenate the hash bytes with the clearPassword bytes and rehash
    hash = digester.digest(ArrayUtils.addAll(hash, mergedPasswordAndSalt.getBytes("UTF-8")));
  }

  // Log the resulting hash as base64 String
  logger.info("Legace password digest: salt=" + salt + " hash=" + Base64.getEncoder().encodeToString(hash));
}

有人看到问题了吗?我认为区别在于:PHP:binary.binary和JAVA: addAll(byte[], byte[])的结果

提前感谢

共有1个答案

何浩荡
2023-03-14

php端的实现通过执行第一轮哈希,然后循环4999次,正确地进行了5k次迭代。

$digest = hash($this->algorithm, $salted, true);

for ($i = 1; $i < $this->iterations; ++$i) {
  $digest = hash($this->algorithm, $digest.$salted, true);
}

在java实现中,for循环从0开始,导致5k1次迭代。

通过在java中也在1处启动for循环,得到的密码哈希值就等于。

byte[] hash = digester.digest(mergedPasswordAndSalt.getBytes("UTF-8"));

for (int i = 0; i < 5000; i++) {
  hash = digester.digest(ArrayUtils.addAll(hash, mergedPasswordAndSalt.getBytes("UTF-8")));
}
 类似资料:
  • 问题内容: 我一直在研究一些有关Java字符串加密技术的信息,但不幸的是,我还没有找到如何在Java中使用SHA-512对String进行哈希处理的很好的教程。我读了一些有关MD5和Base64的博客,但是它们并不像我想要的那样安全(实际上,Base64不是一种加密技术),所以我更喜欢SHA-512。 问题答案: 您可以将其用于SHA-512

  • 我一直在使用PHP为Dovecot创建一个可用的盐渍SHA-512哈希。当创建一个非salt十六进制格式的哈希时,一切都很好。向哈希中添加一个盐,我无法再使用“doveadm pw”验证哈希。 这是我的代码: var\u dumps()的输出如下: 现在,当我尝试根据doveadm验证哈希时,只有第一个哈希(十六进制格式的非salt)有效。第二个错误是关于字符串长度的错误(输入长度无效(128而不

  • 作为练习,我用C编写了自己的SHA-512哈希函数实现。我知道它是有效的,因为我从abc 在Base64中。就像在测试现场一样。 我有两个问题: > 如何加密我的密码?如果我有: 我应该创建字符串以输入盐通过="ssssssssmy密钥密码"吗?或者可能以相反的方式?我试图在谷歌上到处寻找答案——我找不到真正合适的东西。 在base64中,我应该使用什么编码来获得像/etc/shadow文件中那样

  • 我想找到一个解决方案或方法,使我能够添加盐和控制迭代次数。本机Rfc2898DeriveBytes基于HMACSHA1。理想情况下,使用SHA-256或SHA-512将使系统经得起未来的考验。 这是迄今为止我发现的最好的例子:http://jmedved.com/2012/04/pbkdf2-with-sha-256-and-others/但是当我用SHA-256运行它时,它实际上比用SHA-51

  • 我对密码学是个新手,但是学习。我从网上的研究中收集了许多不同的建议,并制作了自己的类,用于处理哈希、salt、键拉伸以及关联数据的比较/转换。 在研究了内置的。NET密码学库,我发现我拥有的仍然只有SHA-1。但我得出的结论是,这并不坏,因为我使用了哈希过程的多次迭代。对吗? 但如果我想从更健壮的SHA-512开始,我如何在下面的代码中实现它呢?提前谢谢。 注意:我已经参考了很多来自https:/

  • 想要改进此问题?更新问题,以便它仅通过编辑这篇文章来关注一个问题。 我们需要读取文件内容并将其转换为SHA256,然后将其转换为Base64。 任何指针或示例代码都足够了,因为我是这个加密机制的新手。 提前谢谢。