0

I'm having some trouble here while trying to decode some encrypted text. CheckpswdBasedKey is always returning false, because of the BadPaddingException at c.doFInal I'm using AES, basicaly the encryption:

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;

Now decrypt mode:

//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;
}

I compared bytes from iv @checkPswdBasedKey and iv @generatePswdBasedKey and they are all the same. Same happens to the secretkey @checkPswdBasedKey (i get those bytes with: sk.getEncoded() ) and secretkey @generatePswdBasedKey... they are all equal. So basically when i decrypt i know i'm using the same key, same IV and same message... and an appropiate length (16 bytes key, 16 bytes msg, 16 bytes iv, using AES 128) Any idea?

Viccari
  • 9,029
  • 4
  • 43
  • 77
Aero
  • 3
  • 1
  • A bit off topic, but any particular reason not to use a secure hash instead for the password? – Joachim Isaksson Apr 28 '13 at 14:59
  • Set the decrypt side to no padding and see what you get. All sorts of errors are possible, and knowing what is on the end of your plaintext can eliminate some of them. – rossum Apr 28 '13 at 18:43
  • @rossum Ok i did it, thx u, now there is no exception at all, however the decryption output doenst match the passwordInput – Aero Apr 28 '13 at 18:59
  • @Viccari because i was told to use password based encryption :)) – Aero Apr 28 '13 at 19:00
  • Are you sure you wanted to answer me, and not @JoachimIsaksson ? – Viccari Apr 28 '13 at 19:38
  • Using "no padding" means no exception. That lets you look at the output to help diagnose what's wrong. First look at the last few bytes to try and match to a padding scheme. – rossum Apr 28 '13 at 22:45

1 Answers1

0

As Joachim Isaksson commented, if you want to implement a password check, you ought to use a secure hash representation of the password, that is not reversible. This way, the password can't be obtained by decryption even if the hash + key is compromised.

Anyway, in your generatePswdBasedKey you use the PBKDF2WithHmacSHA1 algorithm to generate a SecretKey, and then use that key to encrypt the password. Now you have two options to verify the password in checkPswdBasedKey. Either you:

  • encrypt the password the same way as in generatePswdBasedKey and compare that they give the same encrypted string

or you

  • decrypt the encrypted version and compare the result with the password in clear.

I presume that you try the later approach as you init your cipher for decrypt with:

c.init(Cipher.DECRYPT_MODE, sk, ivParams);

Hovewer, for that approach to work you need to instantiate your SecretKey the same way as you did in generatePswdBasedKey - currently you end up with two different keys.

In 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");

In checkPswdBasedKey:

byte bufferBytes[] = Base64.decode(password);
SecretKey sk = new SecretKeySpec(bufferBytes, 0, bufferBytes.length, "AES");

When that is fixed, you also need to look at your compare logic. You should not do a Base64 encoding of your result before the compare - and the compare ought to be case sensitive. Don't use:

byte result[] = c.doFinal(bufferBytes);
String resultStr = Base64.encodeToString(result, false);
if (passwordInput.equalsIgnoreCase(resultStr)) {
    return true;
}

But instead use:

byte result[] = c.doFinal(bufferBytes);
String resultStr = new String(result);
if (passwordInput.equals(resultStr)) {
    return true;
}
Ebbe M. Pedersen
  • 7,250
  • 3
  • 27
  • 47