我在尝试解码某些加密文本时遇到了一些麻烦。 由于c.doFInal处的BadPaddingException,CheckpswdBasedKey始终返回false 我正在使用AES,基本上是加密:
public static String generatePswdBasedKey(String password){
String finalKey = null;
SecretKey sk = null;
KeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt, IT, KEY_LENGTH);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
byte[] keyBytes = keyFactory.generateSecret(keySpec).getEncoded();
sk = new SecretKeySpec(keyBytes, "AES");
Cipher cipher = Cipher.getInstance(Cifrador.AES_MODE);//AES_MODE = AES/CBC/PKCS5Padding
IvParameterSpec ivParams = new IvParameterSpec(iv);//IV already initialized
cipher.init(Cipher.ENCRYPT_MODE, sk, ivParams);
byte pwdbytes[] = password.getBytes();//I also tried using Base64 to decode... without success
byte cc[] = cipher.doFinal(pwdbytes);
finalKey = Base64.encodeToString(cc, false); //.encodeToString(byte[] sArr, boolean lineSep)
return finalKey;
现在解密模式:
//This method compares a password received from keyboard with the decrypted password (decrypting output from generatePswdBasedKey(String password))
public static boolean checkPswdBasedKey(String password, String passwordInput){
byte bufferBytes[] = Base64.decode(password);
SecretKey sk = new SecretKeySpec(bufferBytes, 0, bufferBytes.length, "AES"); //Also tried new SecretKeySPec(bufferBytes, "AES");...
Cipher c = Cipher.getInstance(Cifrador.AES_MODE);//AES_MODE = AES/CBC/PKCS5Padding
IvParameterSpec ivParams = new IvParameterSpec(iv);//IV already initialized
c.init(Cipher.DECRYPT_MODE, sk, ivParams);
byte result[] = c.doFinal(bufferBytes);
String resultStr = Base64.encodeToString(result, false); //.encodeToString(byte[] sArr, boolean lineSep)
if(passwordInput.equalsIgnoreCase(resultStr)){
return true;
}
return false;
}
我比较了来自iv @checkPswdBasedKey和iv @generatePswdBasedKey的字节,它们都是一样的。同样的秘密密钥@checkPswdBasedKey(我得到那些字节:sk.getEncoded())和密钥@generatePswdBasedKey ......它们都是相同的。 所以基本上当我解密我知道我使用相同的密钥,相同的IV和相同的消息...和适当的长度(16字节密钥,16字节消息,16字节iv,使用AES 128)任何想法?
答案 0 :(得分:0)
正如 Joachim Isaksson 所评论的那样,如果要实施密码检查,则应使用密码的安全哈希表示,这是不可逆的。这样,即使哈希+密钥被泄露,也无法通过解密获得密码。
无论如何,在generatePswdBasedKey
中使用PBKDF2WithHmacSHA1
算法生成SecretKey
,然后使用该密钥加密密码。现在,您有两种方法可以验证checkPswdBasedKey
中的密码。你要么:
generatePswdBasedKey
相同的方式加密密码,并比较它们提供相同的加密字符串或者你
我假设您在使用以下命令启动密码进行解密时尝试后续方法:
c.init(Cipher.DECRYPT_MODE,sk,ivParams);
Hovewer,对于这种工作方法,您需要以同样的方式实例化SecretKey
就像你在generatePswdBasedKey
中所做的那样 - 目前你最终得到了两个不同的键。
在generatePswdBasedKey:
SecretKey sk = null;
KeySpec keySpec = new PBEKeySpec(password.toCharArray(), salt, IT, KEY_LENGTH);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
byte[] keyBytes = keyFactory.generateSecret(keySpec).getEncoded();
sk = new SecretKeySpec(keyBytes, "AES");
在checkPswdBasedKey:
byte bufferBytes[] = Base64.decode(password);
SecretKey sk = new SecretKeySpec(bufferBytes, 0, bufferBytes.length, "AES");
修复后,您还需要查看比较逻辑。在比较之前,您不应对结果执行 Base64 编码 - 并且比较应区分大小写。 不要使用:
byte result[] = c.doFinal(bufferBytes);
String resultStr = Base64.encodeToString(result, false);
if (passwordInput.equalsIgnoreCase(resultStr)) {
return true;
}
但改为使用:
byte result[] = c.doFinal(bufferBytes);
String resultStr = new String(result);
if (passwordInput.equals(resultStr)) {
return true;
}