仅基于密码生成AES密钥

时间:2017-07-14 13:14:58

标签: java security encryption encryption-symmetric

我有一个申请,可能需要密码才能进行身份验证 此应用程序不处理任何敏感数据,因为这个"密码"是由主持人选择并告诉"客户"通过另一个渠道(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
我应该使用不同的算法,还是应该通过散列密码本身或者完全不同的方法来生成盐? 我想避免将随机字符串与生成的盐一起发送

1 个答案:

答案 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),一切正常。