Scrpyt
如前所述,Scrypt密码哈希的安全性要高于Bcrypt,Scrypt内部还使用了PBKDF2算法,具体算法就不深入研究了,其实从Scrypt的入参就可以看出其安全性,具体入参列表如下:
- Passphrase:待哈希密码
- Salt:盐,推荐不小于16字节
- N:CPU/内存消耗指数,一般取值为2的若干次方,例如16384
- p:并行计算参数,理论上取值范围为1-255,参数值越大越依赖于并发计算
- r:表块大小,理论取值范围为1-255,同样越大越依赖内存与带宽
- dkLen: 表最终生成的结果长度。
以JAVA代码为例,使用如下Scrypt库
<dependency>
<groupId>com.lambdaworks</groupId>
<artifactId>scrypt</artifactId>
<version>1.4.0</version>
</dependency>
示例代码如下:
String pwd = "123456";
byte[] salt = new byte[16];
SecureRandom.getInstance("SHA1PRNG").nextBytes(salt);
long time = new Date().getTime();
System.out.println(toHexString(SCrypt.scrypt(pwd.getBytes("UTF-8"), salt, 16384, 8, 1, 32)));
System.out.println(String.valueOf(new Date().getTime() - time));
其中SCrypt.scrpyt方法的参数与上所描述的顺序一致,N、p、r参数均能影响实际计算耗时,为此后续需要根据各自的实际需求来调整参数,同时尽量保证计算时间不高于300ms。
Argon2
Argon2的入参和Scrypt差不多,但是个人感觉更加量化一些,主要包括如下:
- password:密码
- salt:盐
- parallelism:并发线程数量
- memorySizeKB:占用内存大小(单位KB)
- iterations:迭代次数
看来基本与Scrypt一致,不过参数更加量化一些,不像Scrypt感觉那么抽象。使用起来也较为简单,现成的库如下:
<dependency>
<groupId>de.mkammerer</groupId>
<artifactId>argon2-jvm</artifactId>
<version>2.4</version>
</dependency>
示例代码如下:
Argon2 argon2 = Argon2Factory.create();
String pwd = "123456";
long time = new Date().getTime();
String hash = argon2.hash(2, 65536, 1, pwd, StandardCharsets.UTF_8);
System.out.println(hash);
System.out.println(String.valueOf(new Date().getTime() - time));
和Scrypt一致,影响计算时间的参数有多个,具体参数的选择还是需要根据实际的需求去调整,遗憾的是Argon2暂未找到相应的Javascript实现。