Encryption compatible between Android and C#
Got some help from http://oogifu.blogspot.com/2009/01/aes-in-java-and-c.html.
Here is my Java class:
package com.neocodenetworks.smsfwd;
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import android.util.Log;
public class Crypto {
public static final String TAG = "smsfwd";
private static Cipher aesCipher;
private static SecretKey secretKey;
private static IvParameterSpec ivParameterSpec;
private static String CIPHER_TRANSFORMATION = "AES/CBC/PKCS5Padding";
private static String CIPHER_ALGORITHM = "AES";
// Replace me with a 16-byte key, share between Java and C#
private static byte[] rawSecretKey = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
private static String MESSAGEDIGEST_ALGORITHM = "MD5";
public Crypto(String passphrase) {
byte[] passwordKey = encodeDigest(passphrase);
try {
aesCipher = Cipher.getInstance(CIPHER_TRANSFORMATION);
} catch (NoSuchAlgorithmException e) {
Log.e(TAG, "No such algorithm " + CIPHER_ALGORITHM, e);
} catch (NoSuchPaddingException e) {
Log.e(TAG, "No such padding PKCS5", e);
}
secretKey = new SecretKeySpec(passwordKey, CIPHER_ALGORITHM);
ivParameterSpec = new IvParameterSpec(rawSecretKey);
}
public String encryptAsBase64(byte[] clearData) {
byte[] encryptedData = encrypt(clearData);
return net.iharder.base64.Base64.encodeBytes(encryptedData);
}
public byte[] encrypt(byte[] clearData) {
try {
aesCipher.init(Cipher.ENCRYPT_MODE, secretKey, ivParameterSpec);
} catch (InvalidKeyException e) {
Log.e(TAG, "Invalid key", e);
return null;
} catch (InvalidAlgorithmParameterException e) {
Log.e(TAG, "Invalid algorithm " + CIPHER_ALGORITHM, e);
return null;
}
byte[] encryptedData;
try {
encryptedData = aesCipher.doFinal(clearData);
} catch (IllegalBlockSizeException e) {
Log.e(TAG, "Illegal block size", e);
return null;
} catch (BadPaddingException e) {
Log.e(TAG, "Bad padding", e);
return null;
}
return encryptedData;
}
private byte[] encodeDigest(String text) {
MessageDigest digest;
try {
digest = MessageDigest.getInstance(MESSAGEDIGEST_ALGORITHM);
return digest.digest(text.getBytes());
} catch (NoSuchAlgorithmException e) {
Log.e(TAG, "No such algorithm " + MESSAGEDIGEST_ALGORITHM, e);
}
return null;
}
}
I used http://iharder.sourceforge.net/current/java/base64/ for the base64 encoding.
Here's my C# class:
using System;
using System.Text;
using System.Security.Cryptography;
namespace smsfwdClient
{
public class Crypto
{
private ICryptoTransform rijndaelDecryptor;
// Replace me with a 16-byte key, share between Java and C#
private static byte[] rawSecretKey = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
public Crypto(string passphrase)
{
byte[] passwordKey = encodeDigest(passphrase);
RijndaelManaged rijndael = new RijndaelManaged();
rijndaelDecryptor = rijndael.CreateDecryptor(passwordKey, rawSecretKey);
}
public string Decrypt(byte[] encryptedData)
{
byte[] newClearData = rijndaelDecryptor.TransformFinalBlock(encryptedData, 0, encryptedData.Length);
return Encoding.ASCII.GetString(newClearData);
}
public string DecryptFromBase64(string encryptedBase64)
{
return Decrypt(Convert.FromBase64String(encryptedBase64));
}
private byte[] encodeDigest(string text)
{
MD5CryptoServiceProvider x = new System.Security.Cryptography.MD5CryptoServiceProvider();
byte[] data = Encoding.ASCII.GetBytes(text);
return x.ComputeHash(data);
}
}
}
I really hope this helps someone else!
How can I find an Android encryption library or class compatible with my C# code?
I wrote a crypto class that should work with your code, given correct configuration.
You can check it out here: https://github.com/Untouchab1e/yubinotes/blob/master/Android/src/com/connectutb/yubinotes/util/Crypto.java
You're using DES in your example, which is a flawed and obsolete algorithm (alternatively use 3DES), so I suggest moving to AES which provides better encryption.
What are the differences between C# and Java (Android) when encrypting using RSA with PKCS1 padding?
Both codes are right. You can encrypt data in same way with Java version and C# version. If one of them is working and another one is failing, probably you are using an incorrect public key (copy/paste error, some different bytes, etc...)
Need help converting c# encryption to java (android) encryption for cross compatibility
Here is the implementation I came up with for this code:
try (ByteArrayOutputStream plainTextStream = new ByteArrayOutputStream())
{
// -- c# like CryptoStream
try (CipherOutputStream decrypterStream =
new CipherOutputStream(plainTextStream, cipher))
{
// -- binaryWriter like c#
try (DataOutputStream binaryWriter = new DataOutputStream(decrypterStream))
{
// -- Encrypt Data
//Decrypt Cipher Text from Message
binaryWriter.write(encryptedMessage,
nonSecretPayloadLength + iv.length,
encryptedMessage.length
- nonSecretPayloadLength
- iv.length
- sentTag.length);
}
//Return Plain Text
//decrypterStream.flush();
} finally {
return plainTextStream.toByteArray();
}
} catch (IOException e) {
e.printStackTrace();
}
Decrypt AES data on android that comes from a C# MVC4 server
If you encrypt with PKCS#7 padding and then decrypt with no padding, it should work just fine, except that you get padding at the end. The padding is just x bytes containing the number x.
I stumbled upon the comment "c# byte goes from 0 to 255, whereas java byte goes from -128-127, so i just subtracted //128 from each c# byte, to get the java byte" and I think that might be your problem (or one problem anyway).
This isn't how two's complement works. Try to fix that first and see if it works.
Related Topics
Multiple Webrequest in Same Session
Using Ienumerable Without Foreach Loop
Memorystream - Cannot Access a Closed Stream
Search Xdocument Using Linq Without Knowing the Namespace
Insert into SQL Db a String That Contain Special Character '
Detect Browser Close on Asp.Net
How to Create a Progress Bar with Rounded Corners in iOS Using Xamarin.Forms
Interop.Word Documents.Open Is Null
How to Get The Http Post Data in C#
How to Ensure Entries with Non-Overlapping Time Ranges
Fill an Array (Or Arraylist) from SQLdatareader
Signed VS. Unsigned Integers for Lengths/Counts
Using Getproperties() with Bindingflags.Declaredonly in .Net Reflection
Best Practice: Direct SQL Access VS. Web Service
How to Stop an Application from Opening