我有一个申请,可能需要密码才能进行身份验证 此应用程序不处理任何敏感数据,因为这个"密码"是由主持人选择并告诉"客户"通过另一个渠道(WhatsApp或其他)。 因此,当客户端想要进行身份验证时,主机会生成一个随机字符串,并将其发送给客户端 然后,客户端使用用户输入的密码加密此随机字符串 加密的随机字符串是主机发回的 主机使用由相同密码生成的密钥对此加密的String进行解密 如果未加密和原始字符串匹配,则用户已登录 这是我到目前为止所提出的:
String base64;
char[] password = "password".toCharArray();
String randomString = new BigInteger(130, new SecureRandom()).toString(32);
try {
//Encrypt Client Side
SecretKey key = new SecretKeySpec(SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512").generateSecret(new PBEKeySpec(password)).getEncoded(), "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, key);
base64 = Base64.getEncoder().encodeToString(cipher.doFinal(randomString.getBytes(StandardCharsets.UTF_8)));
} catch (GeneralSecurityException e) {
throw new IllegalStateException(e);
}
try {
//Decrypt Server Side
SecretKey key = new SecretKeySpec(SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512").generateSecret(new PBEKeySpec(password)).getEncoded(), "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, key);
//Check if both strings match
System.out.println(Arrays.equals(cipher.doFinal(Base64.getDecoder().decode(base64)), randomString.getBytes(StandardCharsets.UTF_8)));
} catch (GeneralSecurityException e) {
throw new IllegalStateException(e);
}
不幸的是,此代码抛出异常:java.security.spec.InvalidKeySpecException: Salt not found
我应该使用不同的算法,还是应该通过散列密码本身或者完全不同的方法来生成盐?
我想避免将随机字符串与生成的盐一起发送
答案 0 :(得分:1)
您应该为PBEKeySpec
提供为AES密钥生成足够位所需的内容。你需要两面都用同样的盐,所以你可以这样做:
byte[] salt = new byte[8];
System.arraycopy(randomString.getBytes("UTF-8"), 0, salt, 0, 8);
现在将PBEKeySpec
替换为new PBEKeySpec(password, salt, 10, 128)
,一切正常。