Reputation: 1453
I am preparing to do encryption in sever side(c#) and decrypt in android side (Java) for my api key. Both encryption/decryption in c# was okay. And also, in java, both encryption/decryption also okay. The main problem is generated ciphertext with C# is different with java although I used the same secret key. C# generated cipher text can't be decrypted in Java. I tried like below.
In Java
public static String key = "aaaaaaaabbccccbbaaaaaaaabbccccbb";
private static byte[] key_Array = Base64.decode(key,Base64.DEFAULT);
public static String encrypt(String plainText)
{
try
{
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.encodeToString(cipher.doFinal(plainText.getBytes()),Base64.DEFAULT);
}
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.decode(encryptedMessage,Base64.DEFAULT);
return new String(_Cipher.doFinal(decodedMessage));
}
catch (Exception e)
{
System.out.println("[Exception]:"+e.getMessage());
}
return null;
}
In C#
public class Crypt
{
// C# Code, CipherMode.CBC
// CBC version need Initialization vector IV.
public static string keyStr = "aaaaaaaabbccccbbaaaaaaaabbccccbb";
// FFClY170hLrhsDnKUEhJ4FhVOnrpNNFFClY170hLrhsDnKUE
public 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, 24);
// 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);
}
public 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, 24);
// 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);
}
}
Java Output
Plain Text : hla hla
cipher Text: MW6b3AIpNw5RLmhvAro1Yg==
C# Output
Plain Text : hla hla
cipher Text: qsHRHy05GbRv5Q1QNOUlZQ==
Any ideas or alternative ways will be appreciated. Thanks.
Upvotes: 3
Views: 2192
Reputation: 771
For me this worked perfectly.
In JAVA
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.Key;
import java.util.Base64;
public class Main {
private static String key = "000102030405060708090a0b0c0d0e0f";
public static void main(String[] args) throws Exception {
System.out.print("\nEncrypt2:"+ encrypt("Hello World",key.getBytes(),new byte[16]));
String encry= encrypt("Hello World",key.getBytes(),new
byte[16]);
System.out.print("\nDecrypt2:"+decrypt(encry,key.getBytes(),new byte[16]));
}
public static String encrypt(String plainText, byte[] key, byte[] iv) throws Exception {
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, new IvParameterSpec(iv));
byte[] encryptedData = cipher.doFinal(plainText.getBytes());
return Base64.getEncoder().encodeToString(encryptedData);
}
public static String decrypt(String encryptedText, byte[] key, byte[] iv) throws Exception {
SecretKeySpec secretKeySpec = new SecretKeySpec(key, "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, new IvParameterSpec(iv));
byte[] decryptedData = cipher.doFinal(Base64.getDecoder().decode(encryptedText));
return new String(decryptedData);
}
}
the out put of this will be : b5cCsUojhg71otTVZNxxyA==
In C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace EncryptandDecrypt
{
public class Encrypt
{
public static string keyStr = "000102030405060708090a0b0c0d0e0f";
public static string Encrypt(string plainText, byte[] key, byte[] iv)
{
using (Aes aes = Aes.Create())
{
aes.Key = key;
aes.IV = iv;
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
ICryptoTransform encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
byte[] encryptedData = encryptor.TransformFinalBlock(Encoding.UTF8.GetBytes(plainText), 0, plainText.Length);
return Convert.ToBase64String(encryptedData);
}
}
public static string Decrypt(string encryptedText, byte[] key, byte[] iv)
{
using (Aes aes = Aes.Create())
{
aes.Key = key;
aes.IV = iv;
aes.Mode = CipherMode.CBC;
aes.Padding = PaddingMode.PKCS7;
ICryptoTransform decryptor = aes.CreateDecryptor(aes.Key, aes.IV);
byte[] d1 = Convert.FromBase64String(encryptedText);
int l1 = d1.Length;
int l2 = encryptedText.Length;
byte[] decryptedData = decryptor.TransformFinalBlock(Convert.FromBase64String(encryptedText), 0, Convert.FromBase64String(encryptedText).Length);
return Encoding.UTF8.GetString(decryptedData);
}
}
}
}
Program.cs file
{
Console.WriteLine("Encrynew :" +Encrypt.Encrypt("Hello World", Encoding.UTF8.GetBytes(secretKey),new byte[16]));
string dec = Encrypt.Encrypt("Hello World", Encoding.UTF8.GetBytes(secretKey), new byte[16]);
Console.WriteLine("Decrynew :" + Encrypt.Decrypt(dec, Encoding.UTF8.GetBytes(secretKey), new byte[16]));
}
Upvotes: 0
Reputation: 97322
The problem is that, in your Java code, you're only using a 192-bit key, while in the C# version, you're using a 256-bit key.
Your base64-encoded key is 32 characters, which translates to 24 bytes, which is only 192 bits.
These are the offending lines in Java:
public static String key = "aaaaaaaabbccccbbaaaaaaaabbccccbb"; // 32 characters
private static byte[] key_Array = Base64.decode(key, Base64.DEFAULT); // 24 bytes
Just changing the creation of your Java key array will fix things. Something like:
public static String key = "aaaaaaaabbccccbbaaaaaaaabbccccbb"; // 32 characters
private static byte[] key_Array = new byte[32]; // 32 bytes
static {
// copy the 24 base64-decoded bytes to the key array
System.arraycopy(Base64.decode(key, Base64.DEFAULT), 0, key_Array, 0, 24);
}
Upvotes: 4