Android String Encryption/Decryption - java

I want to encrypt and decrypt a String from an EditText using AndroidKeyStore. My problem is that at the decrypt process is get a BadPaddingException.
Key generator code:
KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
KeyGenParameterSpec keyGenParameterSpec = new KeyGenParameterSpec.Builder(ALIAS, KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT).
setBlockModes(KeyProperties.BLOCK_MODE_GCM).setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE).build();
keyGenerator.init(keyGenParameterSpec);
keyGenerator.generateKey();
Encryption code:
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
KeyStore.SecretKeyEntry secretKeyEntry = (KeyStore.SecretKeyEntry) keyStore.getEntry(ALIAS, null);
SecretKey secretKey = secretKeyEntry.getSecretKey();
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
cipherIV = cipher.getIV();
plainText.setText(new String(cipher.doFinal(plainText.getText().toString().getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8));
Decryption code:
KeyStore keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
final KeyStore.SecretKeyEntry secretKeyEntry = (KeyStore.SecretKeyEntry) keyStore.getEntry(ALIAS, null);
final SecretKey secretKey = secretKeyEntry.getSecretKey();
final Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
final GCMParameterSpec spec = new GCMParameterSpec(128, cipherIV);
cipher.init(Cipher.DECRYPT_MODE, secretKey, spec);
byte[] decrypted = cipher.doFinal(plainText.getText().toString().getBytes(StandardCharsets.UTF_8));
plainText.setText(new String(decrypted, StandardCharsets.UTF_8));

This line is in error:
plainText.setText(new String(cipher.doFinal(plainText.getText().toString().getBytes(StandardCharsets.UTF_8)), StandardCharsets.UTF_8));
If we break it apart, we have something like
byte [] cipherBytes = cipher.doFinal(plainText.getText().toString().getBytes(StandardCharsets.UTF_8));
plainText.setText(new String(cipherBytes, StandardCharsets.UTF_8);
The problem is that cipherBytes is a sequence of arbitrary bytes rather than the characters of a string. The String constructor will silently replace invalid characters with something else, a process which corrupts the data.
If you want to display the cipher bytes or otherwise send it to a character oriented channel you must encode it. Typically encodings are base64 or hex. To decrypt the String you must then decode it to bytes first and then decrypt it.
Example:
byte [] cipherBytes = cipher.doFinal(plainText.getText().toString().getBytes(StandardCharsets.UTF_8));
plainText.setText(Base64.encodeToString(cipherBytes, Base64.DEFAULT));
And on decrypt:
byte[] cipherBytes = Base64.decode(plainText.getText().toString(), Base64.DEFAULT);
byte[] decrypted = cipher.doFinal(cipherBytes);

byte[] decrypted = cipher.doFinal(plainText.getText().toString().getBytes(StandardCharsets.UTF_8));
This line may not work well because of the call of getBytes(StandardCharsets.UTF_8). If your EditText is hex representation, try to convert it to string and then invoke getBytes(). E.g.
public static byte[] convertHexStringToByteArray(String hexString) {
int l = hexString.length();
byte[] data = new byte[l/2];
for (int i = 0; i < l; i += 2) {
data[i/2] = (byte)((Character.digit(hexString.charAt(i), 16) << 4) + Character.digit(hexString.charAt(i+1), 16));
}
return data;
}

Related

encryption code of java applied in PHP resulting in wrong decryption string

I am using one encryption/decryption method used in java and applying it in php . I have almost reached to the end but there is one mistake which I found that my decrypted string is not what i was expecting ,
This is my java code
private static final String ALGORITHM = "AES/CBC/PKCS5Padding";
public static String encrypt(String message, String key) throws GeneralSecurityException, UnsupportedEncodingException {
if (message == null || key == null) {
throw new IllegalArgumentException("text to be encrypted and key should not be null");
}
Cipher cipher = Cipher.getInstance(ALGORITHM);
byte[] messageArr = message.getBytes();
byte[] keyparam = key.getBytes();
SecretKeySpec keySpec = new SecretKeySpec(keyparam, "AES");
byte[] ivParams = new byte[16];
byte[] encoded = new byte[messageArr.length + 16];
System.arraycopy(ivParams, 0, encoded, 0, 16);
System.arraycopy(messageArr, 0, encoded, 16, messageArr.length);
cipher.init(Cipher.ENCRYPT_MODE, keySpec, new IvParameterSpec(ivParams));
byte[] encryptedBytes = cipher.doFinal(encoded);
encryptedBytes = Base64.getEncoder().encode(encryptedBytes);
return new String(encryptedBytes);
}
public static String decrypt(String encryptedStr, String key) throws GeneralSecurityException, UnsupportedEncodingException {
if (encryptedStr == null || key == null) {
throw new IllegalArgumentException("text to be decrypted and key should not be null");
}
Cipher cipher = Cipher.getInstance(ALGORITHM);
byte[] keyparam = key.getBytes();
SecretKeySpec keySpec = new SecretKeySpec(keyparam, "AES");
byte[] encoded = encryptedStr.getBytes();
encoded = Base64.getDecoder().decode(encoded);
byte[] decodedEncrypted = new byte[encoded.length - 16];
System.arraycopy(encoded, 16, decodedEncrypted, 0, encoded.length - 16);
byte[] ivParams = new byte[16];
System.arraycopy(encoded, 0, ivParams, 0, ivParams.length);
cipher.init(Cipher.DECRYPT_MODE, keySpec, new IvParameterSpec(ivParams));
byte[] decryptedBytes = cipher.doFinal(decodedEncrypted);
return new String(decryptedBytes);
}
now i have done this in php like this
$encKey = 'encryptionKey';
$cipher = "aes-256-cbc";
$data = 'some data';
$encryption_key = openssl_random_pseudo_bytes(32);
$iv_size = openssl_cipher_iv_length($cipher);
$iv = openssl_random_pseudo_bytes($iv_size);
$ciphertext_raw = openssl_encrypt(json_encode($data), 'aes-256-cbc', $encKey, $options = OPENSSL_RAW_DATA, $iv);
//$ciphertext_raw = openssl_encrypt(json_encode($data), $cipher, $encKey, $options=OPENSSL_RAW_DATA, $iv);
$encrypted_data = base64_encode($iv . $ciphertext_raw);
print_r($encrypted_data);
now the problem is when i encrypt one string in php and decrypt it in java code it add some escape sequence but when i encrypt that same string in java and decrypt it in java it is proper and accurate and i am not sure why this is happening ... may be i am doing some thing wrong
as I have to do this encryption in php using java code i am not sure that is this process going in right way or there is some error .
this is the string which i am encrypting
String str = "vendor_id=INT_GTW&format=json&msg_code=KBEX99&data={\"header\":{\"msg_code\":\"KBEX99\",\"source\":\"INSTANTPAY\",\"channel\":\"CONBNK\",\"txn_ref_number\":\"INSTANTPAY_CONBNK_00001\",\"txn_datetime\":\"1498118309808\",\"ip\":\"1\",\"device_id\":\"XYWZPQR123\",\"api_version\":\"1.0.0\"},\"detail\":{\"entity\":\"INSTANTPAY\",\"intent\":\"REG\",\"user_identifier\":\"INSTANTPAY28423928\",\"crn\":\"105683710\",\"p1\":\"105683710\",\"p2\":\"\",\"p3\":\"INSTANTPAY\",\"p4\":\"\",\"p5\":\"\",\"p6\":\"\",\"p7\":\"\",\"p8\":\"\",\"p9\":\"\",\"p10\":\"\",\"p11\":\"\",\"p12\":\"\",\"p13\":\"\",\"p14\":\"\",\"p15\":\"\",\"p16\":\"\",\"p17\":\"\",\"p18\":\"\",\"p19\":\"\",\"p20\":\"\"}}";
and this is decrypted string
vendor_id=INT_GTW&format=json&msg_code=KBEX99&data={"header":{"msg_code":"KBEX99","source":"INSTANTPAY","channel":"CONBNK","txn_ref_number":"INSTANTPAY_CONBNK_00001","txn_datetime":"1498118309808","ip":"1","device_id":"XYWZPQR123","api_version":"1.0.0"},"detail":{"entity":"INSTANTPAY","intent":"REG","user_identifier":"INSTANTPAY28423928","crn":"105683710","p1":"105683710","p2":"","p3":"INSTANTPAY","p4":"","p5":"","p6":"","p7":"","p8":"","p9":"","p10":"","p11":"","p12":"","p13":"","p14":"","p15":"","p16":"","p17":"","p18":"","p19":"","p20":""}}
but when i am doing it in php and decrypting
"vendor_id=INT_GTW&format=json&msg_code=KBEX99&data={\"header\":{\"msg_code\":\"KBEX99\",\"source\":\"INSTANTPAY\",\"channel\":\"CONBNK\",\"txn_ref_number\":\"INSTANTPAY_CONBNK_00001\",\"txn_datetime\":\"1498118309808\",\"ip\":\"1\",\"device_id\":\"XYWZPQR123\",\"api_version\":\"1.0.0\"},\"detail\":{\"entity\":\"INSTANTPAY\",\"intent\":\"REG\",\"user_identifier\":\"INSTANTPAY28423928\",\"crn\":\"105683710\",\"p1\":\"105683710\",\"p2\":\"\",\"p3\":\"INSTANTPAY\",\"p4\":\"\",\"p5\":\"\",\"p6\":\"\",\"p7\":\"\",\"p8\":\"\",\"p9\":\"\",\"p10\":\"\",\"p11\":\"\",\"p12\":\"\",\"p13\":\"\",\"p14\":\"\",\"p15\":\"\",\"p16\":\"\",\"p17\":\"\",\"p18\":\"\",\"p19\":\"\",\"p20\":\"\"}}"
i am getting this
So any encryption decryption expert please help me in this ...
Thank you !!

Why AES decryption giving empty result?

Encryption done in java using AES and wanted to decrypt in Python, but the result is empty in python (no errors).
See the code before marking as duplicate. I want to detect problem in my code.
java encryption code:
public static String encrypt(String plainText) throws Exception {
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(128);
SecretKey secretKey = keyGenerator.generateKey();
String keyStr = Base64.encodeToString(secretKey.getEncoded(), Base64.NO_WRAP);
byte[] initVector = new byte[16];
(new Random()).nextBytes(initVector);
IvParameterSpec iv = new IvParameterSpec(initVector);
SecretKeySpec skeySpec = new SecretKeySpec(secretKey.getEncoded(), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
byte[] plainTextByte = plainText.getBytes();
byte[] encryptedByte = cipher.doFinal(plainTextByte);
byte[] messagebytes = new byte[initVector.length + encryptedByte.length];
System.arraycopy(initVector, 0, messagebytes, 0, 16);
System.arraycopy(encryptedByte, 0, messagebytes, 16, encryptedByte.length);
return Base64.encodeToString(messagebytes, Base64.NO_WRAP);
}
Python code
def decrypt(key, message):
"""
Input encrypted bytes, return decrypted bytes, using iv and key
"""
byte_array = message.encode("UTF-8")
iv = byte_array[0:16] # extract the 16-byte initialization vector
messagebytes = byte_array[16:] # encrypted message is the bit after the iv
cipher = AES.new(key.encode("UTF-8"), AES.MODE_CBC, iv)
decrypted_padded = cipher.decrypt(messagebytes)
decrypted = unpad(decrypted_padded)
return decrypted.decode("UTF-8");
I see that the Java is explicitly encoding the string as Base 64 at return Base64.encodeToString(messagebytes, Base64.NO_WRAP);
But i see that you are again encoding in python byte_array = message.encode("UTF-8") where in you will have to decode the encrypted message
# Standard Base64 Decoding
decodedBytes = base64.b64decode(encodedStr)
decodedStr = str(decodedBytes, "utf-8")
And only then Decrypt the decoded message.

Encrypt payload using a key and iv by AES/GCM/NoPadding algorithm in node js and decrypt in java

I have encrypt the file using node.js and decrypt in JAVA. Decryption is done in JAVA using "AES/GCM/Nopadding" algorithm and it is third party app hence I cannot see the JAVA code.
I am encrypting the payload in node.js using "aes-128-gcm" algorithm.
for this, I am try mimicking a working java encryption code
I have tried with crypto and node-forge.
iam getting the output but am getting an error "Bad encryption - payload is not encrypted properly" when submitting payload.
pleas help me to find what I did wrong in this code.
working code in java
public void encrypt(#NonNull final byte[] payload, #NonNull final byte[] key) throws GeneralSecurityException
{
SecretKeySpec codingKey = new SecretKeySpec(key, AES);
Cipher cipher = AEC_GCM_THREAD_CIPHER.get();
byte[] iv = new byte[cipher.getBlockSize()];
RANDOM.nextBytes(iv);
cipher.init(Cipher.ENCRYPT_MODE, codingKey, new IvParameterSpec(iv));
final byte[] encryptedPayload = cipher.doFinal(payload);
byte[] encryptMerchantKey = encryptMerchantKey(key);
String payloadFinal = encodeToUrlString(encryptedPayload); // final payload
String ivFinal = encodeToUrlString(iv); // final iv
String keyFinal = encodeToUrlString(encryptMerchantKey); // final key
System.out.println("Payload");
System.out.println(payloadFinal);
System.out.println("iv");
System.out.println(ivFinal);
System.out.println("key");
System.out.println(keyFinal);
}
code iam tried in node js
function encrypt(payload) {
let key = forge.random.getBytesSync(16);
let iv = forge.random.getBytesSync(16);
let cipher = forge.cipher.createCipher("AES-GCM", key);
cipher.start({ iv: iv});
cipher.update(forge.util.createBuffer(payload));
cipher.finish();
let encrypted = forge.util.encode64(cipher.output.getBytes());
let tag = forge.util.encode64(cipher.mode.tag.getBytes());
let iv64 = forge.util.encode64(iv);
let encryptedPayload = encrypted+tag;
//RSA Encryption
encryptedkey = RSAencrypt(forge.util.encode64(key));
return {
"payload" : base64url.fromBase64(encryptedPayload) ,
"iv" : base64url.fromBase64(iv64).length,
"key" : base64url.fromBase64(encryptedkey)
};
}
Rsa description is working fine abling to decrypt the key.
some problem with aes encryption. as see the code, I added auth tag and encrypted data together but no use.
I have complete example of encryption and decryption in angular and java you can take this example as it is and make changes according to you.
Install node-forge with command "npm install node-forge".
encrypt(msg, pass) {
const key = CryptoJS.lib.WordArray.random(8).toString();
const iv = CryptoJS.lib.WordArray.random(8).toString();
// encrypt some bytes using GCM mode
const cipher = forge.cipher.createCipher('AES-GCM', key);
cipher.start({
iv: iv,
additionalData: 'nvn', // optional
tagLength: 128 // optional, defaults to 128 bits
});
cipher.update(forge.util.createBuffer(msg));
cipher.finish();
const encrypted = cipher.output;
const encodedB64 = forge.util.encode64(encrypted.data);
const tag = cipher.mode.tag;
const tagB64 = forge.util.encode64(tag.data);
// outputs encrypted hex
const trasmitmsg = key+iv+tagB64+encodedB64;
return trasmitmsg
}
I have used CryptoJS to generate random string because random of node-forge giving nontransferable strings.
java code to decrypt this trasmitmsg is
public String getDecrypt(String transmsg) throws Exception {
String keyString = transmsg.substring(0, 16);
String ivString = transmsg.substring(16, 32);
String additionalString = transmsg.substring(32, 56);
String cipherString = transmsg.substring(56);
byte[] keyBytes = keyString.getBytes();
SecretKey key = new SecretKeySpec(keyBytes, "AES");
byte[] ivBytes = ivString.getBytes();
byte[] one = Base64.getDecoder().decode(cipherString);
byte[] two = Base64.getDecoder().decode(additionalString);
byte[] cipherText = ArrayUtils.addAll(one, two);
return decrypt(cipherText, key, ivBytes);
}
public static String decrypt(byte[] cipherText, SecretKey key, byte[] IV) throws Exception {
// Get Cipher Instance
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
// Create SecretKeySpec
SecretKeySpec keySpec = new SecretKeySpec(key.getEncoded(), "AES");
// Create GCMParameterSpec
GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(GCM_TAG_LENGTH , IV);
// Initialize Cipher for DECRYPT_MODE
cipher.init(Cipher.DECRYPT_MODE, keySpec, gcmParameterSpec);
cipher.updateAAD("nvn".getBytes());
byte[] decryptedText = cipher.doFinal(cipherText);
return new String(decryptedText);
}
Cheers!!!
The problem was with forge buffer it need to convert to node buffer
this code is working now. thanks, #Maarten Bodewes for the advice.
function encrypt(payload) {
//initialize forge random buffer
var key = forge.random.getBytesSync(16);
var iv = forge.random.getBytesSync(16);
let cipher = forge.cipher.createCipher("AES-GCM", key);
cipher.start({iv : iv});
cipher.update(forge.util.createBuffer(payload));
cipher.finish();
let encrypted = cipher.output.data;
let tag = cipher.mode.tag.data;
let encryptedLoad = encrypted+tag;
// node buffer and forge buffer differ, so the forge buffer must be converted to node Buffer
iv = Buffer.from(iv, "binary");
encryptedLoad = Buffer.from(encryptedLoad, "binary");
//Calling RSA Encryption
encryptedKey = RSAencrypt(key);
return {
"payload" : base64url(encryptedLoad) ,
"iv" : base64url(iv),
"key" : base64url.fromBase64(encryptedKey)
};
}

Generate AES key from RSA encoded AES key

What I am trying to do is to encrypt a string with AES, encrypt the AES key getEncoded() value with RSA, then decrypt that AES getEncoded() value so that I get my original string. The public key is loaded from the users certificate, and the private key from file.
The code is given below.
public class Main {
public static void main(String[] args) throws Exception {
String myString = "My Message";
KeyGenerator keyGenerator = KeyGenerator.getInstance("AES");
keyGenerator.init(128);
SecretKey secretKey = keyGenerator.generateKey();
byte[] initializationVector = new byte[128 / 8];//16
SecureRandom prng = new SecureRandom();
prng.nextBytes(initializationVector);
Cipher AESCipherForEncryption = Cipher.getInstance("AES/CBC/PKCS5PADDING");
AESCipherForEncryption.init(Cipher.ENCRYPT_MODE, secretKey, new IvParameterSpec(initializationVector));
byte[] byteVersionOfMyMessage = myString.getBytes();
byte[] byteVersionOfCipherText = AESCipherForEncryption.doFinal(byteVersionOfMyMessage);
String cipherText = new BASE64Encoder().encode(byteVersionOfCipherText);
InputStream in1 = new FileInputStream("user.crt");
CertificateFactory cf1 = CertificateFactory.getInstance("X509");
Certificate c1 = cf1.generateCertificate(in1);
X509Certificate toSendcert = (X509Certificate) c1;
PublicKey publicKey = toSendcert.getPublicKey();
String cipherTextRSA = encryptRSA(publicKey, new String(secretKey.getEncoded()));
String decypheredRSA = decryptRSA(getPrivateKey("user.pk8", "RSA"), cipherTextRSA);
System.out.println(cipherTextRSA);
System.out.println(decypheredRSA);
SecretKey originalKey = new SecretKeySpec(new String(decypheredRSA.getBytes("UTF-8")).getBytes(), 0, new String(decypheredRSA.getBytes("UTF-8")).getBytes().length, "AES");
Cipher AESCipherForDecryption = Cipher.getInstance("AES/CBC/PKCS5PADDING");
AESCipherForDecryption.init(Cipher.DECRYPT_MODE, originalKey, new IvParameterSpec(initializationVector));
byte[] byteVersionOfDecriptedText = AESCipherForDecryption.doFinal(new BASE64Decoder().decodeBuffer(cipherText));
String decMessage = new String(byteVersionOfDecriptedText);
System.out.println(decMessage);
}
public static String encryptRSA(PublicKey pubKey, String message) throws Exception {
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, pubKey);
Base64.Encoder encoder = Base64.getEncoder();
String encryptedString = encoder.encodeToString(cipher.doFinal(message.getBytes("UTF-8")));
return encryptedString;
}
public static PrivateKey getPrivateKey(String filename, String algorithm) throws Exception {
File f = new File(filename);
FileInputStream fis = new FileInputStream(f);
DataInputStream dis = new DataInputStream(fis);
byte[] keyBytes = new byte[(int) f.length()];
dis.readFully(keyBytes);
dis.close();
String temp = new String(keyBytes);
String privKeyPEM = temp.replace("-----BEGIN PRIVATE KEY-----", "");
privKeyPEM = privKeyPEM.replace("-----END PRIVATE KEY-----", "");
privKeyPEM = privKeyPEM.replace("\n", "");
byte[] decoded = Base64.getDecoder().decode(privKeyPEM);
PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(decoded);
KeyFactory kf = KeyFactory.getInstance(algorithm);
return kf.generatePrivate(spec);
}
public static String decryptRSA(PrivateKey prKey, String encrypted) throws Exception {
Base64.Decoder decoder = Base64.getDecoder();
byte[] input = decoder.decode(encrypted);
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.DECRYPT_MODE, prKey);
return new String(cipher.doFinal(input));
}
The error that I keep getting is:
Exception in thread "main" java.security.InvalidKeyException: Invalid AES key length: 28 bytes
at com.sun.crypto.provider.AESCipher.engineGetKeySize(AESCipher.java:509)
at javax.crypto.Cipher.passCryptoPermCheck(Cipher.java:1067)
at javax.crypto.Cipher.checkCryptoPerm(Cipher.java:1038)
at javax.crypto.Cipher.implInit(Cipher.java:805)
at javax.crypto.Cipher.chooseProvider(Cipher.java:864)
at javax.crypto.Cipher.init(Cipher.java:1396)
at javax.crypto.Cipher.init(Cipher.java:1327)
at com.company.Main.main(Main.java:79)
If I don't encrypt and decrypt the secretKey.getEncoded() value, and just use AES without RSA it works properly. Also working with RSA, if I just encrypt some string with a public key, and decrypt it with a private it works. My question would be: "How could I properly encrypt and decrypt the secretKey.getEncoded() value with RSA, so that I can properly encrypt and decrypt myString?".
new String(secretKey.getEncoded())
This won't work as AES keys contain random bytes, and not every byte is a character representative. The problem with the standard string conversion in Java is that it drops unknown characters and bytes instead of generating an exception during encoding / decoding.
RSA operates on bytes, you should not turn the key into string and then back again into bytes as the transformation may be lossy (e.g. dropping 4 of the 32 bytes).
Alternatively - and probably even better - you may want to try the wrapping modes of cipher instead. This should be compatible with some hardware solutions out there. In that case you don't even have to call getEncoded.
OAEP encryption and authenticated encryption modes such as GCM should be preferred over PKCS#1 padding (the default for the Sun providers) and CBC mode encryption.

RSA and AES Decrypt and Encrypt problem

I have generated on my android application a pair of RSA Keys.
I receive from a web service
- an AES Key, encrypted with my RSA public key
- a String encoded with the AES key.
So I must do the following:
- decrypt the AES Key
- decrypt the string with the obtained AES Key.
To generate the RSA Keys I did:
keyGen = KeyPairGenerator.getInstance("RSA");
keyGen.initialize(size);
keypair = keyGen.genKeyPair();
privateKey = keypair.getPrivate();
publicKey = keypair.getPublic();
On RSA decrypt I use :
public static byte[] decryptRSA( PrivateKey key, byte[] text) throws Exception
{
byte[] dectyptedText = null;
Cipher cipher = Cipher.getInstance("RSA/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, key);
dectyptedText = cipher.doFinal(text);
return dectyptedText;
}
On AES decrypt I use:
public static byte[] decryptAES(byte[] key, byte[] text) throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS1Padding");
cipher.init(Cipher.DECRYPT_MODE, skeySpec);
byte[] decrypted = cipher.doFinal(text);
return decrypted;
}
So, in my code, to obtain the decrypted AES Key I do
byte[] decryptedAESKey = sm.decryptRSA(key, Base64.decode(ReceivedBase64EncryptedAESKey));
byte[] decryptedString = sm.decryptAES(decryptedAESKey, Base64.decode(ReceivedEncryptedAESString));
On the end I get a null for decryptedString.
What am I doing wrong ?
Well, the thing is that the key decrypted was 8 byte long and I had to make it 16 byte to be AES 128 bits compatible
So, I made a method to convert it back
private static byte[] GetKey(byte[] suggestedKey)
{
byte[] kRaw = suggestedKey;
ArrayList<Byte> kList = new ArrayList<Byte>();
for (int i = 0; i < 128; i += 8)
{
kList.add(kRaw[(i / 8) % kRaw.length]);
}
byte[] byteArray = new byte[kList.size()];
for(int i = 0; i<kList.size(); i++){
byteArray[i] = kList.get(i);
}
return byteArray;
}
And the rewritten decrypt method:
public static byte[] decryptAES(byte[] key, byte[] text) throws Exception {
SecretKeySpec skeySpec = new SecretKeySpec(GetKey(key), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding","BC");
byte [] iv = new byte[cipher.getBlockSize()];
for(int i=0;i<iv.length;i++)iv[i] = 0;
IvParameterSpec ivSpec = new IvParameterSpec(iv);
cipher.init(Cipher.DECRYPT_MODE, skeySpec, ivSpec);
byte[] decrypted = cipher.doFinal(text);
return decrypted;
}
I'm not sure what language or libraries you are using (looks like Java?), but some really general things to try:
Did you get the encrypted string, ok? Check the length of ReceivedEncryptedAESString and the output of the Base64.decode to check they look alright.
AES decryption can't fail so it must be a problem in the library initialisation. Check the value/state of cipher after the construction step and the init step.
Try a simpler testcase: ignore the RSA encryption and just try to decrypt something using your Cipher object.

Categories

Resources