AES Decryption not working using with crypto js - javascript

In my code I am encrypting data using AES encryption using crypto.js and i am decrypting the encrypted text
in java.
Encryption and Decryption are working correctly if i try to encrypt and decrypt both in javascript or java.But if i encrypt in javascript
and trying to decrypt in java i am getting below error.
javax.crypto.BadPaddingException: Given final block not properly
padded at
com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:966)
Below is my JSCode:
var keyHex = CryptoJS.enc.Utf8.parse('584771624934175587013168');
var iv = CryptoJS.enc.Hex.parse('000000000000000000000000');
var encrypted = CryptoJS.AES.encrypt('1111', keyHex, {
iv:iv,
mode: CryptoJS.mode.CBC,
padding: CryptoJS.pad.Pkcs7
});
console.log('encryptByAES key: ',encrypted.toString());
Below is my java code.
String key = "584771624934175587013168";
String plainText = "1111";
public String encryptTextusingAES(String text, String kek) throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] keyBytes= new byte[16];
byte[] b= kek.getBytes("UTF-8");
int len= b.length;
if (len> keyBytes.length) len = keyBytes.length;
System.arraycopy(b, 0, keyBytes, 0, len);
SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
IvParameterSpec ivSpec = new IvParameterSpec(keyBytes);
cipher.init(Cipher.ENCRYPT_MODE,keySpec,ivSpec);
byte[] results = cipher.doFinal(text.getBytes("UTF-8"));
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(results);
}
public String decryptTextusingAES(String text, String kek) throws Exception{
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] keyBytes= new byte[16];
byte[] b= kek.getBytes("UTF-8");
int len= b.length;
if (len> keyBytes.length) len = keyBytes.length;
System.arraycopy(b, 0, keyBytes, 0, len);
SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
IvParameterSpec ivSpec = new IvParameterSpec(keyBytes);
cipher.init(Cipher.DECRYPT_MODE,keySpec,ivSpec);
BASE64Decoder decoder = new BASE64Decoder();
byte [] results = cipher.doFinal(decoder.decodeBuffer(text));
return new String(results,"UTF-8");
}
How to decrypt correctly any help will be greatly appreciated!!!!

When you are using a block encryption such as AES, your input needs to be padded before encryption. There are various standard ways of doing this.
In your JS code your are specifying PKCS-7:
padding: CryptoJS.pad.Pkcs7
but in your Java code you are specifying PKCS-5:
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
Make sure you are using the same padding algorithm on both sides.

Related

Hybrid Encrypt in React and Decrypt in Java

I have been stuck in a long time. I am using Hybrid Crypto library in React Native to encrypt the message. Both public and private key are in PEM format.
let crypt = new Crypt({rsaStandard: 'RSA-OAEP'});
let encrypted = crypt.encrypt(publicKey, "This is a message");
return JSON.parse(encrypted).cipher;
This is the code I use to decrypt in Java. I followed this tutorial to read private key from pem file using bouncycastle library.
String str = "M2vFz/28sWhwAK4rGmnFAPRORRTlfa+XYpHFWQsi0bo=";
Security.addProvider(new BouncyCastleProvider());
KeyFactory factory = KeyFactory.getInstance("RSA");
PrivateKey privateKey = generatePrivateKey(factory, RESOURCES_DIR + "private-key.pem");
Cipher decryptCipher = Cipher.getInstance("RSA");
decryptCipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] decryptOut = decryptCipher.doFinal(Base64.getDecoder().decode(str));
System.out.println(new String(decryptOut));
I've been trying many ways, the private key works fine when I decrypt in React but with Java I keep getting javax.crypto.BadPaddingException: Decryption error.
Updated Solution
Because I'm using hybrid crypto so it will include RSA + AES
Flow in frondend: Using AES key to encrypt text => Using public RSA key to encrypt AES key. Then you send everything you need to decrypt (encrypted AES key, Iv, and cipher text)
let crypt = new Crypt({rsaStandard: 'RSAES-PKCS1-V1_5',aesIvSize: 16});
let encrypted = crypt.encrypt(publicKey, str);
const encryptedObj = JSON.parse(encrypted);
return Object.values(encryptedObj.keys)[0] + ',' + encryptedObj.iv + ',' + encryptedObj.cipher;
Flow in java: Using RSA private key to decrypt AES key => Using AES key + Iv to decrypt cipher text
PrivateKey privateKey = generatePrivateKey();
Cipher decryptCipher=Cipher.getInstance("RSA/ECB/PKCS1Padding");
decryptCipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] keyb = decryptCipher.doFinal(Base64.getDecoder().decode(AESkey));
SecretKeySpec skey = new SecretKeySpec(keyb, "AES");
IvParameterSpecivspec = new IvParameterSpec(Base64.getDecoder().decode(iv));
decryptCipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
decryptCipher.init(Cipher.DECRYPT_MODE, skey, ivspec);
byte[] decryptOut = decryptCipher.doFinal(Base64.getDecoder().decode(cipherText));
return new String(decryptOut);

Javascript Crypto AES decrypt

This is the crypto AES encryption code in server side. How can I decrypt in javascript. I can't find any decryption logic having both iv and key with padding.
public static String encrypt(String key, String initVector, String value) {
try {
IvParameterSpec iv = new IvParameterSpec("l353b3l3jk3bk3j3".getBytes("UTF-8"));
SecretKeySpec skeySpec = new SecretKeySpec("2353c3l3jk3bk3j8".getBytes("UTF-8"), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
byte[] encrypted = cipher.doFinal(value.getBytes());
System.out.println("encrypted string: " + Base64.encodeBase64String(encrypted));
return Base64.encodeBase64String(encrypted);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
You can use CryptoJS in the following way:
var decryptedData = CryptoJS.AES.decrypt(cipherText, CryptoJS.enc.Base64.parse(key),
{
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7 //default
});
console.log('Decrypted Data: ' + decrypted);
PKCS5 is not supported by this library but you should not be using it as it was designed for DES rather than AES. However if you dont want to change it then you can still use PKCS7 for decryption and it will work because the difference is in the block size both paddings supports. PKCS5 only works with 8-byte blocks whereas PKCS7 works with block sizes betwheen 1 and 255 bytes. DES uses block size of 8 bytes.

How to use cryptojs aes decrypt from java code with iv param and SecretKeySpec

From java code I have a code:
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS7Padding", new BouncyCastleProvider());
byte[] keys = Base64.decodeBase64(encryptionKey);
SecretKey speckey = new SecretKeySpec(keys, "AES");
byte[] ivParam = new byte[cipher.getBlockSize()];
System.arraycopy(speckey.getEncoded(), 0, ivParam, 0, ivParam.length);
cipher.init(cipherMode, speckey, new IvParameterSpec(ivParam));
return cipher;
In javascript I have a script to decrypt but it doesn't work:
var decrypted = CryptoJS.AES.decrypt(encrypted, key, {
iv: iv,
padding: CryptoJS.pad.Pkcs7,
mode: CryptoJS.mode.CBC
})
console.log("Decrypted: ", decrypted.toString(CryptoJS.enc.Utf8));
I know we need to parse iv(Like this var iv = CryptoJS.enc.Hex.parse(pass); but it doesn't work), key and maybe encrypted first to rub decrypted but I don't know with the Java code above How we can parse iv and key to decrypted. Who has worked in this please help me. Thanks so much <3

Using CryptoJS to encrypt and Aes Manager to decrypt

I am using CryptoJS to encrypt a message and send it to the server, and decrypting it on the other end in C# using Aes Manager. I get a response back when I send it to the server, but it isn't correct.
Javascript:
this.CryptoJS=require("crypto-js");
var temp=this.CryptoJS.AES.encrypt("hello","yyyyyyyyyyyyyyyyyyyyyyyyyyyyykey",{
keySize:128/8,
iv:this.CryptoJS.enc.Utf8.parse("helllooohelllooo"),
mode:this.CryptoJS.mode.CBC,
padding:this.CryptoJS.pad.ZeroPadding
});
data.text=temp.toString(); // This is how I send it to the server
C#:
byte[] Key = UTF8Encoding.UTF8.GetBytes("yyyyyyyyyyyyyyyyyyyyyyyyyyyyykey");
byte[] toBytes = UTF8Encoding.UTF8.GetBytes("helllooohelllooo");
AesManaged aes = new AesManaged();
aes.Key = Key;
aes.IV = toBytes;
aes.Padding = PaddingMode.Zeros;
aes.Mode = CipherMode.CBC;
aes.KeySize = 128;
aes.BlockSize = 128;
byte[] bytes = Convert.FromBase64String(data.text);
UTF8Encoding utf8 = new UTF8Encoding();
using (ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV))
{
MemoryStream MS = new MemoryStream(bytes);
CryptoStream CS = new CryptoStream(MS, decryptor, CryptoStreamMode.Write);
CS.Write(bytes, 0, bytes.Length);
CS.FlushFinalBlock();
MS.Position = 0;
bytes = new byte[MS.Length];
MS.Read(bytes, 0, bytes.Length);
Plaintext = utf8.GetString(bytes);
var temp = 5;
}
This is what I get as a result from the Plaintext variable: t�k�\a``\u007f������\f^,F~\u0017�\u001fp��#5�\u007f\\
You should explicitly pass the key, plaintext and IV as binary data rather than strings:
let iv = CryptoJS.enc.Utf8.parse("helllooohelllooo");
let pt = CryptoJS.enc.Utf8.parse("hello");
let key = CryptoJS.enc.Utf8.parse("yyyyyyyyyyyyyyyyyyyyyyyyyyyyykey");
Then use in the code like so:
CryptoJS.AES.encrypt(pt, key, ...);
Note that your use of zero padding, fixed IV, and no HMAC or AEAD mode makes the code you have completely insecure. You definitely should not use it. Consult this GitHub repository for examples of secure encryption between JavaScript and C#.
I was able to fix my problem i was not converting the original key to utf8 and once i did that it fixed itself
Resource

Encrypt in VB.NET Rijndael Managed and Decrypt in Javascript CryptoJS

I'm making an app that has to decrypt QRs and well... It doesn't, because i get the QR string but i cannot decrypt it.
I'm using this encryption method in VB.NET, and it works perfectly when i read an decrypt from VB.NET:
Private Function GetCodedQR(ByVal str As String) As String
Dim sToEncrypt As String = str
Dim encrypted() As Byte
' Create an Rijndael object
' with the specified key and IV.
Using rijAlg = Rijndael.Create()
rijAlg.Padding = PaddingMode.Zeros
rijAlg.Mode = CipherMode.CBC
rijAlg.KeySize = 256
rijAlg.BlockSize = 256
rijAlg.Key = System.Text.Encoding.ASCII.GetBytes("12345678912345678912345678912345")
rijAlg.IV = System.Text.Encoding.ASCII.GetBytes("123452hheeyy66#cs!9hjv887mxx7#8y")
' Create an encryptor to perform the stream transform.
Dim encryptor As ICryptoTransform = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV)
' Create the streams used for encryption.
Using msEncrypt As New MemoryStream()
Using csEncrypt As New CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)
Using swEncrypt As New StreamWriter(csEncrypt)
'Write all data to the stream.
swEncrypt.Write(sToEncrypt)
End Using
encrypted = msEncrypt.ToArray()
End Using
End Using
End Using
sToEncrypt = Convert.ToBase64String(encrypted)
Return sToEncrypt
End Function
But when im using JS (CryptoJS) to decrypt the message it just dont work!
var iv = CryptoJS.enc.Utf8.parse('123452hheeyy66#cs!9hjv887mxx7#8y');
var decrypted = CryptoJS.AES.decrypt(encrypted, '12345678912345678912345678912345', { iv: iv, mode: CryptoJS.mode.CBC, padding: CryptoJS.pad.ZeroPadding });
Please help me I'm doing my best but JS is not my thing.

Categories

Resources