I have been using the following two methods to encrypt and decrypt sensitive info.
public static String encryptSensitiveInfo(String strToEncrypt,
String saltToEncrypt) throws Exception {
String encryptedString = "";
byte[] encryptedValue;
Key key = new SecretKeySpec(saltToEncrypt.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, key);
encryptedValue = cipher.doFinal(strToEncrypt.getBytes());
encryptedString = new String(Base64.encodeBase64(encryptedValue));
encryptedValue = null;
return encryptedString;
}
public static String decryptSensitiveInfo(String strToDecrypt,
String saltToDecrypt) throws Exception {
String decryptedString = "";
byte[] decryptedValue;
Key key = new SecretKeySpec(saltToDecrypt.getBytes(), "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, key);
decryptedValue = cipher.doFinal(Base64.decodeBase64(strToDecrypt
.getBytes()));
decryptedString = new String(decryptedValue);
decryptedValue = null;
return decryptedString;
}
At the time of decryption I get "pad block corrupted" execption. Any help to resolve this issue would be very much appreciated. Thanks in advance.
You're correctly performing base 64 on the ciphertext because the ciphertext consists of random looking bytes. However, you forget to do the same with your key (which, inexplicably, is called saltToDecrypt in your code). If the keys do not match or if the ciphertext has become corrupted then you will almost certainly run into a BadPaddingException.
If the amount of ciphertext has changed an IllegalBlockSizeException is more likely and if the key isn't of the right size for AES, an InvalidKeyException.
Related
I am thinking about a way I can "try to protect" my application data.
Initially I was doing the following:
I have an encryption key that I use to encrypt and decrypt the data received, as well as what will be stored, I used firebase for the backend.
Basically something like this:
private String encriptar(String datos, String password) throws Exception {
SecretKeySpec secretKey = generateKey(password);
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
byte[] datosEncriptadosBytes = cipher.doFinal(datos.getBytes());
String datosEncriptadosString = Base64.encodeToString(datosEncriptadosBytes, Base64.DEFAULT);
return datosEncriptadosString;
}
private String desencriptar(String datos, String password) throws Exception {
SecretKeySpec secretKey = generateKey(password);
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
byte[] datosDescoficados = Base64.decode(datos, Base64.DEFAULT);
byte[] datosDesencriptadosByte = cipher.doFinal(datosDescoficados);
String datosDesencriptadosString = new String(datosDesencriptadosByte);
return datosDesencriptadosString;
}
private SecretKeySpec generateKey(String password) throws Exception {
MessageDigest sha = MessageDigest.getInstance("SHA-256");
byte[] key = password.getBytes("UTF-8");
key = sha.digest(key);
SecretKeySpec secretKey = new SecretKeySpec(key, "AES");
return secretKey;
}
Well, you can see that in all three methods the password value is required for all methods, encryption, decryption and to generate the key.
I had planned to save this password as "Remote confing" in firebase and get it when I use it, but there are many calls to the server. The other option is to store it locally, but if I do it this way, the password would be plain text in a sharedpreferences, for example.
I am somewhat confused with how to approach this.
I am a rookie on the subject (as you may have seen) and would appreciate knowing if my approach is correct in keeping the key and what you would advise me.
Thank you very much in advance.
Firebase takes care of the encryption for you. The data you send in the network does not go through in plain text. To secure your database, consider adding Security Rules.
See https://firebase.google.com/docs/rules
I have done encryption in android with a static password i.e. "encrypt". The encryption works fine and encrypts the data. But when i try to decrypt the encrypted text it does not show. The code to decrypt is as follow.
public String decrypt(String msg, String inputPassword) throws Exception{
SecretKeySpec key= generateKey(inputPassword);
Cipher c = Cipher.getInstance(AES);
c.init(Cipher.DECRYPT_MODE, key);
byte[] decodedValue= Base64.decode(msg, Base64.DEFAULT);
/*If this line is present the encrypted message is not seen*/
byte[] decValue = c.doFinal(Base64.decode(decodedValue,
Base64.DEFAULT));
String decryptedValue = new String(decodedValue);
String decryptedValue = new String(decValue, StandardCharsets.UTF_8);
return decryptedValue;
}
When the code (below the comment) is enabled. The message is not displayed. But when the line is commented. This is shown in the message box
After the code is commented.
This is the encrypt and key generate methods.
public String encrypt(String message, String inputPassword) throws Exception{
SecretKeySpec key = generateKey(inputPassword);
Cipher c = Cipher.getInstance(AES);
c.init(c.ENCRYPT_MODE, key);
byte[] encVal = c.doFinal(message.getBytes());
String encryptedValue = Base64.encodeToString(encVal, Base64.DEFAULT);
return encryptedValue;
}
//For generating key for encryption
public SecretKeySpec generateKey(String inputPassword) throws Exception{
final MessageDigest digest = MessageDigest.getInstance("SHA-256");
byte[] bytes = inputPassword.getBytes("UTF-8");
digest.update(bytes, 0, bytes.length);
byte[] key = digest.digest();
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
return secretKeySpec;
}
The log is follow
enter image description here
Also the API level is not maintained... I don't know where to setup this as well.
enter image description here
Could you try changing this
String decryptedValue = new String(decodedValue)
to this
String decryptedValue = new String(decodedValue, StandardCharsets.UTF_8)
And for your error, try changing to this
c.doFinal(Base64.decode(decodedValue, Base64.DEFAULT))
I'm trying to decrypt a server response using AES (256/ECB) but getting a wrong result. When I try the same inputs with this online tool I get the right result but running my code is giving a wrong result. Here's my decryption code
//input is a Hex encoded String of the response
public String decryptString(String input){
SecretKeySpec keySpec = new SecretKeySpec(Hex.decodeHex(key),"AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE,keySpec);
byte[] output = cipher.doFinal(Hex.decodeHex(input));
String outputString = Base64.encodeBase64String(output);
return outputString;
}
The parameters I entered into the online tool are :
key = 57e17ae84ceb2938c1f464e902f004919ea08fa7de5e358d1df028fde98d456d
input = 1c6f645bed9019332e94b69bd0152015b41dfce6c7f83046a59e1f80bce302a1ea59ccd15adbd7fcd5e7579cdaea1178fa9540ff0afa74cfe85c4e3244f9255f6dc3808b76088203bf28af25191d9d79487a2f7fb3a53bf7ee50d735d748dd16fbc3f19f9ebcf33a44d95bb221ef47fb577450d207ce6c5b762dc70142c9b7c1d815137ce24bf34fd0f5d2e0ab618c9087ef62327657f1f6c31f164109a4d190973c998e02971e6438dfc1af8dffc28cad0aa9a91a62f57d15200934cd18935b93d7327f7f8a41498ac416d90316a963cc736ce5d4fcde8401ec2f83714c4b202ddb69ce5fde1b61d69caadc2c7a162d7e88f2c5c671832f0bc4f14c98a4e2b9c4c84666a60530623f17c2f960b60c4a7242e10752cb863d41153c451dfc7d5cc4e2e9a8f8c0641764c8fca05f7db2b6
Just wanted to share the answer in case anyone stumbles into the same problem.
The result was actually the right result, the missing part was encoding the resulting byte array as a string using UTF-8 charset. The function becomes
public String decryptString(String input){
SecretKeySpec keySpec = new SecretKeySpec(Hex.decodeHex(key),"AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.DECRYPT_MODE,keySpec);
byte[] output = cipher.doFinal(Hex.decodeHex(input));
String outputString = new String(output,"UTF-8");
return outputString;
}
i already wandered in many stackoverflows post but still cant figured out whats wrong with my code.
public class KripAsim {
String hasil;
public String encrypt(String text) {
try {
String PUBLIC_KEY="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvCNqSslgCndo8vfNrkXFDLXmst024Oi8D7LEiJFjYBva4kBKKISe8rKp58kCLLHjv90RN+Dy2KWcf0eFkKaqc3zILBI99JhV1z8TFOzmt5dfgW6fD1ucBfsK6pWxK84DddyOqKldwHlReqjuDHT2jLue51vpXaCa12WV5bMnGsfy3vZKnp699YCguqRpTR1MijZ9pz8WqldrR0a/DCaq5YxZ7lvjwuWIodQy3S3XRHAaeaUrFHFFLumzXAGuP447oRYR0p+1qsy8+wOtrsGm8m8bMg+C1XGMblkODtOFHz3wtrRZ5OwzgEm7J7odmSX8mSYBZYLcnUVqIFRsQkZLiwIDAQAB";
byte [] decoded = Base64.decode(PUBLIC_KEY,Base64.NO_WRAP);
KeyFactory keyFac = KeyFactory.getInstance("RSA");
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decoded);
PublicKey pubkey = keyFac.generatePublic(keySpec);
Cipher rsa;
rsa = Cipher.getInstance("RSA");
rsa.init(Cipher.ENCRYPT_MODE, pubkey);
hasil = Base64.encodeToString(rsa.doFinal(text.getBytes("UTF-8")),Base64.NO_WRAP);
return hasil;
} catch (Exception e) {
e.printStackTrace();
}
return hasil;
}
}
it returns null. please help. thanks in advance
The line PublicKey pubkey = keyFac.generatePublic(keySpec); throws an InvalidKeySpecException because you have incorrectly supplied a PKCS8EncodedKeySpec when you should have supplied an X509EncodedKeySpec.
You should also completely specify the transformation string in the Cipher.getInstance() method. The following fragment taken from your code illustrates this:
byte[] decoded = Base64.decode(PUBLIC_KEY, Base64.DEFAULT);
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(decoded);
PublicKey pubkey = KeyFactory.getInstance("RSA").generatePublic(keySpec);
Cipher rsa = Cipher.getInstance("RSA/ECB/OAEPwithSHA-256andMGF1Padding");
rsa.init(Cipher.ENCRYPT_MODE, pubkey);
String hasil = Base64.encodeToString(rsa.doFinal(text.getBytes("UTF-8")),
Base64.NO_WRAP);
return hasil;
Finally, you should avoid encrypting data directly with RSA. The correct method is to use a hybrid encryption scheme in which the data is encrypted with a block cipher, say AES in GCM mode, using a randomly generated AES key, and then this key is encrypted using RSA. There are many examples of this around for reference.
I just want AES/CBC 128 bit encryption decryption in openSSl c and Android with identical result.
I have to send encrypted data using pre defined 16 bytes key from android to c via bluetooth.
So is there any common mechanism which i can use in both to produce identical result of encryption and decryption.
Any help would be appreciate.
Thank you.
I found a solution which work perfectly for Android.
I am going to post the answer if it would help anyone.
static String IV = "AAAAAAAAAAAAAAAA";
static String encryptionKey = "0123456789ABCDEF";
public static String decrypt(byte[] cipherText, String encryptionKey) throws Exception{
Cipher cipher = Cipher.getInstance("AES/CBC/ZeroBytePadding"/*, "SunJCE"*/);
SecretKeySpec key = new SecretKeySpec(encryptionKey.getBytes("UTF-8"), "AES");
cipher.init(Cipher.DECRYPT_MODE, key,new IvParameterSpec(IV.getBytes("UTF-8")));
return new String(cipher.doFinal(cipherText),"UTF-8");
}
public static byte[] encrypt(String plainText, String encryptionKey) throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/ZeroBytePadding"/*, "SunJCE"*/);
SecretKeySpec key = new SecretKeySpec(encryptionKey.getBytes("UTF-8"), "AES");
cipher.init(Cipher.ENCRYPT_MODE, key,new IvParameterSpec(IV.getBytes("UTF-8")));
return cipher.doFinal(plainText.getBytes("UTF-8"));
}
//To Encrypt
byte[] cipher = encrypt(plaintext, encryptionKey);
System.out.print("cipher: ");
//To Decrypt
String decrypted = decrypt(cipher, encryptionKey);
System.out.println("decrypt: " + decrypted);