I try to encrypt some text (here it is named code) and decrypt it again. For this i use a 4 digit Pin which is salted.
After this the text is encrypted, also again some Base64 decoding, so i can safely output the String again.
As i understand i have to base64.decode it and then again decrypt it.
But i don't get my encrypted text correctly decrypted back. Just some different text. ( something like this[B@3ceB...)
It is just a small project nothing serious. Also it is my second android app, so some good examples would be great.
String pinstr = new String();
pinstr = "5555";
try {
EncryptDecrypt encryptor = new EncryptDecrypt(pinstr);
//encryptor.encrypt(code);
String encrypted = new String();
encrypted = encryptor.encrypt(code);
String decrypted = new String();
decrypted = encryptor.decrypt(encrypted);
Toast.makeText(MainActivity.this, decrypted, Toast.LENGTH_SHORT).show();
} catch (InvalidKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (BadPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
public class EncryptDecrypt {
private SecretKeySpec skeySpec;
private Cipher cipher, cipher2;
EncryptDecrypt(String password) throws NoSuchAlgorithmException,
UnsupportedEncodingException, NoSuchPaddingException,
IllegalBlockSizeException, BadPaddingException, InvalidKeyException {
MessageDigest sha = MessageDigest.getInstance("SHA-1");
byte[] key = Arrays.copyOf(sha.digest(("ThisisMySalt1234" + password).getBytes("UTF-8")),
16);
skeySpec = new SecretKeySpec(key, "AES");
cipher = Cipher.getInstance("AES");
cipher2 = Cipher.getInstance("AES");
}
String encrypt(String clear) throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException, NoSuchPaddingException {
String encrypted = new String();
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encryptedBytes = null;
encryptedBytes = cipher.doFinal(clear.getBytes());
encrypted = Base64.encodeToString(encryptedBytes, Base64.DEFAULT);
return encrypted;
}
// fehlerhaft
String decrypt(String encryptedBase64) throws InvalidKeyException, IllegalBlockSizeException, BadPaddingException {
String decrypted = new String();
cipher2.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] decodedBytes = null;
decodedBytes = Base64.decode(encryptedBase64, Base64.DEFAULT);
decrypted = cipher2.doFinal(decodedBytes).toString();
return decrypted;
}
}
The output type of
Cipher#doFinal(byte[])
isbyte[]
, but Arrays don't have a default way in which their contents are printed. By callingbyte[].toString()
on an array, you're simply printing its type and hash code. (More on this here)What you want is
which tells the
String
constructor that the given byte array contains characters that are encoded in UTF-8.When you do that, then you also need to get the byte array out of the string in a specific encoding:
If you omit the encoding, then the system default is used which might make your plaintexts unrecoverable when you send the ciphertexts across systems which have different system encoding defaults.
Btw, you don't need both
Cipher
instances. Only one suffices since you're initiating it always during encryption and decryption.Other security problems:
Cipher.getInstance("AES")
toCipher.getInstance("AES/CBC/PKCS5Padding")
.Never use ECB mode which is the default when you use
"AES"
cipher string. It is not semantically secure. Use at least CBC mode with a random IV:The IV is not supposed to be secret, so you can simply prepend it to the ciphertext and splice it off before decryption.
Authenticate your ciphertext so that you're not vulnerable to a padding oracle attack and can always check your ciphertexts for integrity. This can be easily done with an encrypt-then-MAC scheme with a strong MAC algorithm like HMAC-SHA256. You can also use an authenticated mode of encryption like GCM or EAX.