我正在尝试使用sha 256加密来存储用户密码。我有以下方法来加密密码:
public static String hashPassword(String password) {
MessageDigest mdEnc = null;
try {
mdEnc = MessageDigest.getInstance("SHA-256");
} catch (NoSuchAlgorithmException e) {
return null;
}
mdEnc.update(password.getBytes(), 0, password.length());
return new BigInteger(1, mdEnc.digest()).toString(16);
}
我在安全域中声明了以下内容,但每次尝试登录时,都表示凭据不正确。当我不使用加密,并删除hashAlgorithm和hashEncoding属性,并将密码存储在clear中时,身份验证工作正常。任何人都可以看到我的加密方法有任何问题吗?
<module-option name="hashAlgorithm" value="SHA-256"/>
<module-option name="hashEncoding" value="base64"/>
我试着效仿一个简单加密方法的例子:
import org.jboss.security.auth.spi.Util;
public class PasswordGenerator {
public static void main(String[] args) {
for (String arg : args) {
System.out.println(new PasswordGenerator().generate(arg));
}
}
private String generate(String password) {
return Util.createPasswordHash("SHA-256", "BASE64", null, null,password);
}
}
问题在于它说包含Util类的jar在JBoss安装的模块目录中,但它一定是一个较旧的例子,因为我没有看到它。
答案 0 :(得分:1)
您的问题是使用BigInteger
创建十六进制编码;可以使用字节数组中的大端编码创建BigInteger
。但是,如果字节数组以一个或多个00
值字节开头,则可以剥离这些字节。使用Guava,Apache Codec或Bouncy Castle来代替创建十六进制字符串。
也就是说,您应该使用基于密码的密钥派生函数(PBKDF),例如PBKDF2(存在于标准Java API中),bcrypt或scrypt来存储密码“哈希”。这些输出字节也是如此,因此如果需要文本,您仍需要对其进行编码。
另请注意,String.getBytes()
使用平台编码,您只应使用该编码与标准进行通信。相反,您应该为String.getBytes()
方法提供字符编码,例如使用String.getBytes(StandardCharsets.UTF_8)
。