1.I have java function which encrypt xml file and return encrypted String.
/// Java Class
import java.security.Key;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
public class Crypt {
public static String key = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
public static byte[] key_Array = Base64.decodeBase64(key);
public static String encrypt(String strToEncrypt)
{
try
{
//Cipher _Cipher = Cipher.getInstance("AES");
//Cipher _Cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING");
//Cipher _Cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
Key SecretKey = new SecretKeySpec(key_Array, "AES");
Cipher _Cipher = Cipher.getInstance("AES");
_Cipher.init(Cipher.ENCRYPT_MODE, SecretKey);
return Base64.encodeBase64String(_Cipher.doFinal(strToEncrypt.getBytes()));
}
catch (Exception e)
{
System.out.println("[Exception]:"+e.getMessage());
}
return null;
}
public static void main(String[] args) {
StringBuilder sb = new StringBuilder();
sb.append("xml file string ...");
String EncryptedString = encrypt(sb.toString());
System.out.println("[EncryptedString]:"+EncryptedString);
}
}
2.I have c# function which decrypt the message which is encrypted by java function.
/// C# Function
private static string Decrypt(string encryptedText)
{
RijndaelManaged aesEncryption = new RijndaelManaged();
aesEncryption.BlockSize = 256;
//aesEncryption.KeySize = 256;
//aesEncryption.Mode = CipherMode.CBC;
//aesEncryption.Padding = PaddingMode.PKCS7;
string keyStr = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
//string ivStr = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
byte[] keyArr = Convert.FromBase64String(keyStr);
//byte[] ivArr = Convert.FromBase64String(ivStr);
aesEncryption.Key = keyArr;
//aesEncryption.IV = ivArr;
ICryptoTransform decrypto = aesEncryption.CreateDecryptor();
byte[] encryptedBytes = Convert.FromBase64CharArray(encryptedText.ToCharArray(), 0, encryptedText.Length);
byte[] decryptedData = decrypto.TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length); /// CryptographicException: Length of the data to decrypt is invalid.
return ASCIIEncoding.UTF8.GetString(decryptedData);
}
Java encrypt function is work well. But the problem is C# function,
when I decrypt I get below error message
CryptographicException: Length of the data to decrypt is invalid.
I searched solutions by using below ref
but I still face the same error.Could anyone give me suggestion please.
I Just change my C# crypto function. Below is my change lists
/// Updated decrypt function
private static string Decrypt(string encryptedText)
{
RijndaelManaged aesEncryption = new RijndaelManaged();
aesEncryption.BlockSize = 128;
aesEncryption.KeySize = 256;
//aesEncryption.Mode = CipherMode.CBC;
aesEncryption.Padding = PaddingMode.None;
string keyStr = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
string ivStr = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
byte[] ivArr = Convert.FromBase64String(ivStr);
byte[] IVkey16BytesValue = new byte[16];
Array.Copy(ivArr, IVkey16BytesValue, 16);
byte[] keyArr = Convert.FromBase64String(keyStr);
byte[] KeyArr32BytesValue = new byte[32];
Array.Copy(keyArr, KeyArr32BytesValue, 32);
aesEncryption.IV = IVkey16BytesValue;
aesEncryption.Key = KeyArr32BytesValue;
ICryptoTransform decrypto = aesEncryption.CreateDecryptor();
byte[] encryptedBytes = Convert.FromBase64CharArray(encryptedText.ToCharArray(), 0, encryptedText.Length);
byte[] decryptedData = decrypto.TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length);
return ASCIIEncoding.UTF8.GetString(decryptedData);
}
In this time, no error occur. But I get decrypted message which i cannot read.
g:�\0�\td��Y\\符O����\rL��W�wHm�>f�\au����%��0��\ ..........
Please let me get your suggestion again.
After I got very helpful suggestions from @deathismyfriend and other, I found out what I am missing in my C# Decrypt function.So I change my function as below.
/// C# Error Fixed Version - CipherMode.ECB
public static string keyStr = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
private static string Encrypt(string PlainText)
{
RijndaelManaged aes = new RijndaelManaged();
aes.BlockSize = 128;
aes.KeySize = 256;
/// In Java, Same with below code
/// Cipher _Cipher = Cipher.getInstance("AES"); // Java Code
aes.Mode = CipherMode.ECB;
byte[] keyArr = Convert.FromBase64String(keyStr);
byte[] KeyArrBytes32Value = new byte[32];
Array.Copy(keyArr, KeyArrBytes32Value, 32);
aes.Key = KeyArrBytes32Value;
ICryptoTransform encrypto = aes.CreateEncryptor();
byte[] plainTextByte = ASCIIEncoding.UTF8.GetBytes(PlainText);
byte[] CipherText = encrypto.TransformFinalBlock(plainTextByte, 0, plainTextByte.Length);
return Convert.ToBase64String(CipherText);
}
private static string Decrypt(string CipherText)
{
RijndaelManaged aes = new RijndaelManaged();
aes.BlockSize = 128;
aes.KeySize = 256;
/// In Java, Same with below code
/// Cipher _Cipher = Cipher.getInstance("AES"); // Java Code
aes.Mode = CipherMode.ECB;
byte[] keyArr = Convert.FromBase64String(keyStr);
byte[] KeyArrBytes32Value = new byte[32];
Array.Copy(keyArr, KeyArrBytes32Value, 32);
aes.Key = KeyArrBytes32Value;
ICryptoTransform decrypto = aes.CreateDecryptor();
byte[] encryptedBytes = Convert.FromBase64CharArray(CipherText.ToCharArray(), 0, CipherText.Length);
byte[] decryptedData = decrypto.TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length);
return ASCIIEncoding.UTF8.GetString(decryptedData);
}
By using upper c# function , now I can decrypt and read cipher text.
Below is what I found out after I getting error again and again.
CryptographicException: Padding is invalid and cannot be removed.
Solution:
_RijndaelManaged.Padding = CipherMode.xxx; ///should toggle here
_RijndaelManaged.Padding = PaddingMode.xxx; ///should toggle here
CryptographicException: Length of the data to decrypt is invalid.
CryptographicException: Specified initialization vector (IV) does not match the block size for this algorithm.
Solution
1. _RijndaelManaged.BlockSize = 128; /// Must be
2. _RijndaelManaged.KeySize = 256; /// Must be
3. _RijndaelManaged.Key = Byte Array Size must be 32 in length ( more detail 32*8 = 256 KeySize )
4. _RijndaelManaged.IV = Byte Array Size must be 16 in length ( more detail 16*8 = 128 BlockSize)
But when it come to security reason, I think I should not use ECB mode.
According to
So I Modify it again in Java and C#.
// Java code - Cipher mode CBC version.
// CBC version need Initialization vector IV.
// Reference from https://stackoverflow.com/questions/6669181/why-does-my-aes-encryption-throws-an-invalidkeyexception/6669812#6669812
import java.security.Key;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
public class CryptoSecurity {
public static String key = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
public static byte[] key_Array = Base64.decodeBase64(key);
public static String encrypt(String strToEncrypt)
{
try
{
//Cipher _Cipher = Cipher.getInstance("AES");
//Cipher _Cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING");
Cipher _Cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
// Initialization vector.
// It could be any value or generated using a random number generator.
byte[] iv = { 1, 2, 3, 4, 5, 6, 6, 5, 4, 3, 2, 1, 7, 7, 7, 7 };
IvParameterSpec ivspec = new IvParameterSpec(iv);
Key SecretKey = new SecretKeySpec(key_Array, "AES");
_Cipher.init(Cipher.ENCRYPT_MODE, SecretKey, ivspec);
return Base64.encodeBase64String(_Cipher.doFinal(strToEncrypt.getBytes()));
}
catch (Exception e)
{
System.out.println("[Exception]:"+e.getMessage());
}
return null;
}
public static String decrypt(String EncryptedMessage)
{
try
{
//Cipher _Cipher = Cipher.getInstance("AES");
//Cipher _Cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING");
Cipher _Cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
// Initialization vector.
// It could be any value or generated using a random number generator.
byte[] iv = { 1, 2, 3, 4, 5, 6, 6, 5, 4, 3, 2, 1, 7, 7, 7, 7 };
IvParameterSpec ivspec = new IvParameterSpec(iv);
Key SecretKey = new SecretKeySpec(key_Array, "AES");
_Cipher.init(Cipher.DECRYPT_MODE, SecretKey, ivspec);
byte DecodedMessage[] = Base64.decodeBase64(EncryptedMessage);
return new String(_Cipher.doFinal(DecodedMessage));
}
catch (Exception e)
{
System.out.println("[Exception]:"+e.getMessage());
}
return null;
}
public static void main(String[] args) {
// TODO Auto-generated method stub
StringBuilder sb = new StringBuilder();
sb.append("xml file string ...");
String outputOfEncrypt = encrypt(sb.toString());
System.out.println("[CryptoSecurity.outputOfEncrypt]:"+outputOfEncrypt);
String outputOfDecrypt = decrypt(outputOfEncrypt);
//String outputOfDecrypt = decrypt(sb.toString());
System.out.println("[CryptoSecurity.outputOfDecrypt]:"+outputOfDecrypt);
}
}
In C#, I modify it like below.
// C# Code, CipherMode.CBC
// CBC version need Initialization vector IV.
public static string keyStr = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
private static string Encrypt(string PlainText)
{
RijndaelManaged aes = new RijndaelManaged();
aes.BlockSize = 128;
aes.KeySize = 256;
// It is equal in java
/// Cipher _Cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
byte[] keyArr = Convert.FromBase64String(keyStr);
byte[] KeyArrBytes32Value = new byte[32];
Array.Copy(keyArr, KeyArrBytes32Value, 32);
// Initialization vector.
// It could be any value or generated using a random number generator.
byte[] ivArr = { 1, 2, 3, 4, 5, 6, 6, 5, 4, 3, 2, 1, 7, 7, 7, 7 };
byte[] IVBytes16Value = new byte[16];
Array.Copy(ivArr, IVBytes16Value, 16);
aes.Key = KeyArrBytes32Value;
aes.IV = IVBytes16Value;
ICryptoTransform encrypto = aes.CreateEncryptor();
byte[] plainTextByte = ASCIIEncoding.UTF8.GetBytes(PlainText);
byte[] CipherText = encrypto.TransformFinalBlock(plainTextByte, 0, plainTextByte.Length);
return Convert.ToBase64String(CipherText);
}
private static string Decrypt(string CipherText)
{
RijndaelManaged aes = new RijndaelManaged();
aes.BlockSize = 128;
aes.KeySize = 256;
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
byte[] keyArr = Convert.FromBase64String(keyStr);
byte[] KeyArrBytes32Value = new byte[32];
Array.Copy(keyArr, KeyArrBytes32Value, 32);
// Initialization vector.
// It could be any value or generated using a random number generator.
byte[] ivArr = { 1, 2, 3, 4, 5, 6, 6, 5, 4, 3, 2, 1, 7, 7, 7, 7 };
byte[] IVBytes16Value = new byte[16];
Array.Copy(ivArr, IVBytes16Value, 16);
aes.Key = KeyArrBytes32Value;
aes.IV = IVBytes16Value;
ICryptoTransform decrypto = aes.CreateDecryptor();
byte[] encryptedBytes = Convert.FromBase64CharArray(CipherText.ToCharArray(), 0, CipherText.Length);
byte[] decryptedData = decrypto.TransformFinalBlock(encryptedBytes, 0, encryptedBytes.Length);
return ASCIIEncoding.UTF8.GetString(decryptedData);
}
Now it all work.
For more detail about AES, click this link which I was given by @deathismyfriend.
It is also very useful.
I believe the blockSize should be 128 and the keysize be 256. The keyStr should be 32 characters long and the IVstr should be 16 characters long. This may help as it describes why 128 bits have to be used for block size and what the key sizes can be. csrc.nist.gov/publications/fips/fips197/fips-197.pdf
You have this in the decrypt method.
aesEncryption.Padding = PaddingMode.None;
I believe you need to put that in the encrypt method also.
Also why not use this method for the key and IV.
aes.Key = ASCIIEncoding.ASCII.GetBytes(keyStr);
aes.IV = ASCIIEncoding.ASCII.GetBytes(ivStr);
On one of my recent projects I was tasked with building up a url with an encrypted portion to pass to another website. They ran java on their server, whereas we developed in c#.
I know this isn't an exact match to what you were tasked to create, but hopefully this can help out others that are trying to find answers :)
I received the following from their developers to build our encryption off from
To accomplish this in c# I did the following:
public String Encrypt(String plainText, String key)
{
var plainBytes = Encoding.UTF8.GetBytes(plainText);
return Convert.ToBase64String(Encrypt(plainBytes, GetRijndaelManaged(key)));
}
private RijndaelManaged GetRijndaelManaged(String secretKey)
{
var keyBytes = new byte[16];
var secretKeyBytes = Encoding.ASCII.GetBytes(secretKey);
Array.Copy(secretKeyBytes, keyBytes, Math.Min(keyBytes.Length, secretKeyBytes.Length));
return new RijndaelManaged
{
Mode = CipherMode.ECB,
Padding = PaddingMode.PKCS7,
KeySize = 128,
BlockSize = 128,
Key = keyBytes,
IV = keyBytes
};
}
private byte[] Encrypt(byte[] plainBytes, RijndaelManaged rijndaelManaged)
{
return rijndaelManaged.CreateEncryptor()
.TransformFinalBlock(plainBytes, 0, plainBytes.Length);
}
I had a problem with this algorithm (in Java only) and I did a litle changes.
Diff Image
// Java code - Cipher mode CBC version.
// CBC version need Initialization vector IV.
// Reference from https://stackoverflow.com/questions/6669181/why-does-my-aes-encryption-throws-an-invalidkeyexception/6669812#6669812
public static String key = "FFClY170hLrhsDnKUEhJ4FhVOnrpNNFFClY170hLrhsDnKUE";
public static byte[] key_Array = Base64.decodeBase64(key);
public static String encrypt(String strToEncrypt) {
try {
//Cipher _Cipher = Cipher.getInstance("AES");
//Cipher _Cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING");
Cipher _Cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
// Initialization vector.
// It could be any value or generated using a random number generator.
byte[] iv = {1, 2, 3, 4, 5, 6, 6, 5, 4, 3, 2, 1, 7, 7, 7, 7};
IvParameterSpec ivspec = new IvParameterSpec(iv);
key_Array = Arrays.copyOf(key_Array, 32);
Key SecretKey = new SecretKeySpec(key_Array, "AES");
_Cipher.init(Cipher.ENCRYPT_MODE, SecretKey, ivspec);
return Base64.encodeBase64String(_Cipher.doFinal(strToEncrypt.getBytes()));
} catch (Exception e) {
System.out.println("[Exception]:" + e.getMessage());
}
return null;
}
public static String decrypt(String EncryptedMessage) {
try {
//Cipher _Cipher = Cipher.getInstance("AES");
//Cipher _Cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING");
Cipher _Cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
// Initialization vector.
// It could be any value or generated using a random number generator.
byte[] iv = {1, 2, 3, 4, 5, 6, 6, 5, 4, 3, 2, 1, 7, 7, 7, 7};
IvParameterSpec ivspec = new IvParameterSpec(iv);
key_Array = Arrays.copyOf(key_Array, 32);
Key SecretKey = new SecretKeySpec(key_Array, "AES");
_Cipher.init(Cipher.DECRYPT_MODE, SecretKey, ivspec);
byte DecodedMessage[] = Base64.decodeBase64(EncryptedMessage);
return new String(_Cipher.doFinal(DecodedMessage));
} catch (Exception e) {
System.out.println("[Exception]:" + e.getMessage());
}
return null;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With