如何在Java中实现Scrypt?

3

我一直在努力尝试在我的Web应用程序中使用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,因为有更多的文档可以参考,但我希望有人能帮助我将Scrypt实现。


Scrypt 对于服务器端的 Web 应用程序来说将会占用大量内存。Bcrypt 可能是更好的选择。 - TheGreatContini
2
为什么要创建另一个Scrypt类?你只需要import org.bouncycastle.crypto.generators.SCrypt,然后使用generate方法:SCrypt.generate(parameters...)。确保在它们的网站上下载bouncycastle jars(或者如果你正在使用maven,则包含在你的pom.xml中)。 - user7605325
2个回答

2

链接已经失效。 - Ricardo A.

0
Scrypt哈希算法在基于Java的应用程序中广泛使用(因为MD5和其他JDK提供的算法被认为容易被破解)。
JDK没有为Scrypt提供SPI,因此您需要使用BouncyCastle提供程序来支持Scrypt。您可以在项目中使用以下依赖项:
org.bouncycastle:bcprov-jdk18on:1.76

你可以根据你的Java版本使用适当的版本。

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

  • cpuCost(整数):定义CPU成本,必须大于1且小于等于65536
  • memoryCost(整数):定义内存成本,必须大于1
  • parallelization(整数):定义并行化,必须大于1且小于Integer.MAX_VALUE / (128 * memoryCost * 8)
  • keyLength(整数):密钥长度必须大于1
  • salt(整数):盐长度必须大于1

现在你可以按照给定的盐大小生成盐的字节数组:

SecureRandom random = new SecureRandom();

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


一旦你生成了盐,你可以使用下面的代码来对给定的内容进行编码。
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);


希望能对你有所帮助!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接