This blog is moved to
http://amalhashim.wordpress.com

Tuesday, August 25, 2009

Encyption/Decryption in C# and Java

C# Code


string Decrypt(string textToDecrypt, string key)
{
RijndaelManaged rijndaelCipher = new RijndaelManaged();
rijndaelCipher.Mode = CipherMode.CBC;
rijndaelCipher.Padding = PaddingMode.PKCS7;

rijndaelCipher.KeySize = 0x80;
rijndaelCipher.BlockSize = 0x80;
byte[] encryptedData = Convert.FromBase64String(textToDecrypt);
byte[] pwdBytes = Encoding.UTF8.GetBytes(key);
byte[] keyBytes = new byte[0x10];
int len = pwdBytes.Length;
if (len > keyBytes.Length)
{
len = keyBytes.Length;
}
Array.Copy(pwdBytes, keyBytes, len);
rijndaelCipher.Key = keyBytes;
rijndaelCipher.IV = keyBytes;
byte[] plainText = rijndaelCipher.CreateDecryptor().TransformFinalBlock(encryptedData, 0, encryptedData.Length);
return Encoding.UTF8.GetString(plainText);
}

string Encrypt(string textToEncrypt, string key)
{
RijndaelManaged rijndaelCipher = new RijndaelManaged();
rijndaelCipher.Mode = CipherMode.CBC;
rijndaelCipher.Padding = PaddingMode.PKCS7;

rijndaelCipher.KeySize = 0x80;
rijndaelCipher.BlockSize = 0x80;
byte[] pwdBytes = Encoding.UTF8.GetBytes(key);
byte[] keyBytes = new byte[0x10];
int len = pwdBytes.Length;
if (len > keyBytes.Length)
{
len = keyBytes.Length;
}
Array.Copy(pwdBytes, keyBytes, len);
rijndaelCipher.Key = keyBytes;
rijndaelCipher.IV = keyBytes;
ICryptoTransform transform = rijndaelCipher.CreateEncryptor();
byte[] plainText = Encoding.UTF8.GetBytes(textToEncrypt);
return Convert.ToBase64String(transform.TransformFinalBlock(plainText, 0, plainText.Length));
}


Java Code

String Decrypt(String text, String key) throws Exception{
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] keyBytes= new byte[16];
byte[] b= key.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");
}

String Encrypt(String text, String key)
throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
byte[] keyBytes= new byte[16];
byte[] b= key.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);
}

24 comments:

Anish said...

happy to c u a new title in your blog!!! after a long gap :)

A.m.a.L Hashim said...

I was busy with work and personal life. Soon you can see more...

Unknown said...

Hi,

Can you please let me know how I can do this for DES Coverstions.

Thanks,
Dan

upasana said...

Hi, Can I Decrypt the same text from C# which I encrypted using Java code? What i mean to ask is whether the two versions of code you have given are compatible or not?
thanks..

A.m.a.L Hashim said...

Yes they are completely compatible

upasana said...

Hi Hashim,

Thanks a lot for your reply.

Actually I am trying something similar but it is giving me padding error.

here's what I am trying to do.

I have a java code for encryption which is (attached below) and it looks same as what you have written in your java-Encrypt function.

But when I try to decrypt it using the C# Decrypt version you have provided, I get "Padding is invalid and cannot be removed" exception.

here the java code I'm using:
public String doEncrypt(String keyfilepath, String text)
{

String outtext=null;
try
{
initialize();
File keyfile = new File(keyfilepath);
SecretKey key = readKey(keyfile);
Cipher cipher = Cipher.getInstance(key.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] utf8 = text.getBytes(UNICODE_FORMAT);
byte[] enc = cipher.doFinal(utf8);
outtext = new BASE64Encoder().encode(enc);

}
catch (Exception e)
{

}
System.out.println("\nFinal Output->\n"+outtext);
return outtext;
}

private static SecretKey readKey(File f)
{
// Read the raw bytes from the keyfile
DataInputStream in = new DataInputStream(new FileInputStream(f));
byte[] rawkey = new byte[(int) f.length()];
in.readFully(rawkey);
in.close();

// Convert the raw bytes to a secret key like this
DESedeKeySpec keyspec = new DESedeKeySpec(rawkey);
SecretKeyFactory keyfactory = SecretKeyFactory.getInstance("DESede");
SecretKey key = keyfactory.generateSecret(keyspec);
return key;
}


Please see if you can help..
thnx

upasana said...

forgot to mention where I get this exception. It at this palce in C#-Decrypt() function:

rijndaelCipher.CreateDecryptor().TransformFinalBlock(encryptedData, 0, encryptedData.Length);

A.m.a.L Hashim said...

@Upas - The problem is causing by the key. As for testing purpose use a string value as the Key.

String key = "testKey";

String encValue = Encrypt("text", key);

upasana said...

that didn't help :(

Another thing I noticed.. In your C# code the padding mode is PKCS7. However in Java Code it is PKCS5. Isn't that going to make any difference??

A.m.a.L Hashim said...

Try changing the padding. But the same piece of code is working great and its been used for past 2 years in live system.

fred said...

Thank you for the code Hashim..
I tried it seperately in java and C#, it works gr8...

but when i try to encrypt in java and send it across URL, it throws error...

http://192.168.1.27/Retail/FreightHttpHandler.aspx?&encmsg=6qDDA52OkTTSh8+mTge0Q
w7Qe3P3YABsDF/DbQHFECIwx67gM4lbyH1i7AvnsNYWVjowoWKdsLEF
hM1wPMThdK1faxUTAUSWZBQJswn+FYeioVUxpkl585i3Y+AOocuZTq9gyqE5z5GY1XmTEyzwDqfV
D5yHg+8eWlZLUWj4IvpkeXSxi/bbxlQ5XwnnyN0rkkuoOo+CldGSgzaXOA0cUxcPn9NoRSPTFq8u
vPyyjaTPdXGkjewNUE24e1kds9LZsnjtMkGD6fpzhbbkut+lYrTK9HOE/FX5qHEyjPXjmvAnKk9/
QuHaQBYc056TxSNoVPi8bRPDUCb+JV2iQF6cOjeDTkZUQMF0guKfKC/PHZYmuXOxgQcEtFsTfyVd
y9sr+kyafPtsKcMSNgwxrPjb4rC+qR2d7gLvoM5ahQipchAGBt+dHYAmXt7Ub7S/75TE0AlMFLoT
/BnY26+Mjo0v6NNwdMbX2ZSOb867LQPJa+a/UuHbWS4RZZmamgfncgyPOhaSI9GH60JMMVBZS701
KflmEVgW0zVZoyvuvkh+jGMjPXM2DcurEsbbJoh9qU+AvTNpYHPXccp58/VDuA1flwcRX02dNCIO
zJcccKPBNhhchT6gFjk+uEj5IvGAf3qtP9JEKhDFXnhCBIRfssJMif7e5q+AfbCk3tOfVzQNI96R
gF4adA2k1qUJ3Vf2fFrAF2PyrRryL/slQBui1MNecQ==
Exception in thread "main" java.net.MalformedURLException: Illegal character in
URL
at sun.net.www.http.HttpClient.getURLFile(Unknown Source)
at sun.net.www.protocol.http.HttpURLConnection.writeRequests(Unknown Sou
rce)
at sun.net.www.protocol.http.HttpURLConnection.getInputStream(Unknown So
urce)
at AES.main(AES.java:77)

can you please help me

A.m.a.L Hashim said...

@Fred, if you planning to use it as query string, then 1st encrypt, then do url encoding.

fred said...

hi Hashim, its solved, i removed all line breaks in the encoded string and url got parsed properly...C# was replacing '+' as white space in the encoded string for some reason i am not aware of..i replaced all white spaces with '+' and it got decrypted succesfully :)

Julian said...

Hi Hashim

This is a great simple solution. Works great for me!

Cheers,
Julian

Iain said...

Hi,

I have been trying to implement the above code and wondered if you could provide some help as I am getting an FormatException error when trying to decrypt a query string in a .net website.

I use the following code to encrypt the string in Java/Android( Note I have placed the Encrypt and Decrypt methods in a Class called CryptoFactory:

String urlStr = getString(R.string.website_ip) + "/" + getString(R.string.application_middleware) + "/" + "login.aspx?"
+ "username=" + CryptoFactory.Encrypt(username, "testKey") + "&password=" + CryptoFactory.Encrypt(password, "testKey");

This produces the following urlString:

localhost/MobileM3SMSMiddleLayer/login.aspx?username=[B@4056fd90&password=[B@405202c0

I then use the following C# code to decrypt the query string.

string user = CryptoFactory.Decrypt(Page.Request.QueryString["username"], "testKey");
string pass = CryptoFactory.Decrypt(Page.Request.QueryString["password"], "testKey");

I then get an error at the following line in the Decrypt method.

byte[] encryptedData = Convert.FromBase64String(textToDecrypt);

The Error is a Format Exception and the Error Text is "Invalid character in a Base-64 string".

Any Ideas what could be causing this?

Just to let you know I was initially trying it with the query string values being encoded & encrypted, sent, decoded and finally decrypted but I have removed this extra layer for simplicities sake as I want to understand what is causing this issue with the encryption.

Please help if you have time.


Regards Iain

A.m.a.L Hashim said...

Hi Iain,

I did this work years back. Try to debug the application and see what value comes into the variable textToDecrypt.

FelipeJ.net said...

Thanks a lot, it halped me very much!!

Aly said...

Hi i am a newbie to encryption algorithms, i was looking for an algorithm that could encrypt in java and decrypt in .net and what you have here is just what i need. My question is do i need to import any other packages, create any classes to use the code that you have given or i can just use it as it is?

A.m.a.L Hashim said...

@Aly, no need for any special packages.

Anonymous said...

Great, i used in android Base64 instead of BASE64Encoder and worked great with .net 2
thx :)

Mahesh Patel said...

What about PHP compatibility in this code?
Have you code snippets of PHP with this encrypt/decript logic

Mahesh Patel said...

What about PHP Compatibility with this code?

Have you snippets about this...?

Unknown said...

Actually I am trying something similar but it is giving me padding error.

here's what I am trying to do.

I have a java code for encryption which is (attached below) and it looks same as what you have written in your java-Encrypt function.

But when I try to decrypt it using the C# Decrypt version you have provided, I get "Padding is invalid and cannot be removed" exception.

Unknown said...

Actually I am trying something similar but it is giving me padding error.

here's what I am trying to do.

I have a java code for encryption which is (attached below) and it looks same as what you have written in your java-Encrypt function.

But when I try to decrypt it using the C# Decrypt version you have provided, I get "Padding is invalid and cannot be removed" exception.