如何用Java实现Scrypt?

问题描述 投票:0回答:2

我真的一直在努力尝试让 Bouncy Castle Scrypt 在我的网络应用程序中进行密码加密。我对 Java 编程和安全性相当陌生。

我尝试查看 Bouncy Castle 的 Scrypt 类文档。然而,我很难弄清楚它是如何工作的。它似乎并没有真正提供有关如何创建类或类似内容的太多信息。

我在 Stack Exchange 和 Google 上进行了搜索,看看是否有任何地方可以给我一个很好的例子,告诉我应该如何创建这个类。我找到了这个问题和答案,并且我在没有创建类的情况下尝试了它,但这似乎也不起作用。

最重要的是,我的导入似乎也不起作用。

这是我拥有的所有代码:

import org.bouncycastle.crypto.generators;

public class SCrypt extends java.lang.Object {

    public Scrypt(){}

    public static byte[] generate(byte[] P,byte[] S,int N,int r,int p,int dkLen) {

    }
}

我想使用 Scrypt,因为它似乎是加密密码最安全的方法,但它似乎不太可能实现。我非常接近使用 PBKDF2,因为有更多关于它的文档,但我希望有人可以帮助我实现这一目标。

java bouncycastle pbkdf2 scrypt
2个回答
2
投票

感谢雨果的反馈! 经过一番努力和搜索,我找到了这个网站:http://www.itcsolutions.eu/2011/08/22/how-to-use-bouncy-castle-cryptographic-api-in-netbeans-or-eclipse- for-java-jse-项目/

这帮助我逐步了解了在我的计算机上安装和运行 Bouncy Castle 所需的内容。 我希望这会对其他人有所帮助,因为我花了很长时间才找到将其分解为外行术语的东西。 :)


0
投票

Scrypt 哈希算法广泛用于基于 Java 的应用程序(因为 MD5 和其他 JDK 附带的算法被认为很容易破解)。

JDK不为Scrypt提供SPI,因此您需要为Scrypt使用BouncyCastle提供程序。您可以在项目中使用以下依赖项:

org.bouncycastle:bcprov-jdk18on:1.76

您可以根据您的Java版本使用合适的版本。

现在,您需要决定或生成以下参数来定义 Scrypt 哈希的复杂性:

  • cpuCost
    (int): 定义cpu成本,必须大于1且小于 大于等于 65536
  • memoryCost
    (int): 定义内存消耗,必须更大 超过 1
  • parallelization
    (int):定义并行化,必须是 大于 1 且小于
    Integer.MAX_VALUE / (128 * memoryCost * 8)
  • keyLength
    (int):密钥长度必须大于1
  • salt
    (int):盐长度必须大于 1

现在您可以在给定盐大小的字节数组中生成盐,如下所示:

SecureRandom random = new SecureRandom();

public byte[] generateKey(int keyLength) {
   byte[] bytes = new byte[keyLength];
   this.random.nextBytes(bytes);
   return bytes;
}

生成 Salt 后,您可以使用下面的代码对给定的进行编码

var cpuCost = 65536;
var memoryCost = 8;
var parallelization = 1;
var keyLength = 32;
var saltLength = 16;
var rawPassword = "abcdef"; //String to be hashed

var salt = generateKey(saltLength);

byte[] derived = SCrypt.generate(Utf8.encode(rawPassword), salt, cpuCost, memoryCost, parallelization, keyLength);
String params = Long.toString( ((int) (Math.log(cpuCost) / Math.log(2)) << 16L) | memoryCost << 8 | parallelization, 16);
StringBuilder sb = new StringBuilder((salt.length + derived.length) * 2);
sb.append("$").append(params).append('$');
sb.append(encodePart(salt)).append('$');
sb.append(encodePart(derived));
val encodedValue =  sb.toString();

Scrypt 也在 Spring Security 中用于密码编码,因此如果您已经在使用 Spring,那么您可以简单地使用

SCryptPasswordEncoder
进行编码和匹配。 这个类提供了针对 Spring 使用进行优化的静态工厂方法,例如:

SCryptPasswordEncoder scryptEncoder = SCryptPasswordEncoder.defaultsForSpringSecurity_v5_8();

String hashedValue = scryptEncoder.encode("abcdef");

//To match the encoded string with raw value
boolean isSame = scryptEncoder.matches("abcdef", hashedValue);

希望对您有帮助!

© www.soinside.com 2019 - 2024. All rights reserved.