Encryption Compatible Between Android and C#

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



Leave a reply



Submit