Guys I am working on WP8 C# project and I'm having a problem with AES encryption in C#.
I have written code that encrypts a byte array with a key and an IV and returns a byte array;
AES Encryption in C#
public byte[] encryptAESWithIV(byte[] key, byte[] Text)
{
byte[] encrypted = new byte[48];
byte[] iv = new byte[16] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
encrypted = EncryptStringToBytes_Aes(toHex(Text), key, iv);
byte[] output = new byte[encrypted.Length + iv.Length];
Array.Copy(iv, 0, output, 0, iv.Length);
Array.Copy(encrypted, 0, output, iv.Length, encrypted.Length);
return output;
}
AES Encryption in Java (Android code)
public static byte[] encryptAESWithIV(byte[] key, byte[] clearText)
throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException,
InvalidParameterSpecException, IllegalBlockSizeException,
BadPaddingException, UnsupportedEncodingException {
SecretKeySpec skeySpec = new SecretKeySpec(key, CIPHER_AES);
Cipher cipher = Cipher.getInstance(CIPHER_AES_MODE);
byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
//random.nextBytes(iv);
try {
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, new IvParameterSpec(iv));
} catch (InvalidAlgorithmParameterException e) {
e.printStackTrace();
}
byte[] encrypted = cipher.doFinal(clearText);
byte[] output = new byte[encrypted.length + iv.length];
System.arraycopy(iv, 0, output, 0, iv.length);
System.arraycopy(encrypted, 0, output, iv.length, encrypted.length);
Log.v("encrypt-length",""+encrypted.length);
Log.v("iv-length",""+iv.length);
//Log.d("output_bytes", Arrays.toString(output));
return output;
}
In both cases I have given the same IV, Text and key.
In C# I did not get the same result as with the Java code. The Java code is correct and I want to get the same result in C#.
Related
I wrote two programs in C#. One does the encryption, and the other one does the decryption. The decryption program throws exception of "The input data is not a complete block" with data from the encryption program. However the decryption program works fine with the encrypted data from a Unix encryption program, using PKCS5_PBKDF2_HMAC_SHA1().
Encrypted data is base 64 encoded, and saved in a text file. The first 8 bytes is a salt, the next 16 bytes is an IV, and the rest is the application text.
I would appreciate very much if anyone could help.
public static string DecryptText(string cipherData)
{
if (string.IsNullOrEmpty(_passwd))
return null;
var decodedBytes = Convert.FromBase64String(cipherData);
// First 8 bytes contain the salt used for key derivation. Use the password from the passwd.dat
// file and the salt to derive the key used to encode the credential.
//
var salt = new byte[8];
Buffer.BlockCopy(decodedBytes, 0, salt, 0, 8);
var derivedBytes = new Rfc2898DeriveBytes(_passwd, salt, 1000);
var key = derivedBytes.GetBytes(32);
// Next 16 bytes contain the initialization vector used to encrypt
//
var ivBytes = new byte[16];
Buffer.BlockCopy(decodedBytes, 8, ivBytes, 0, ivBytes.Length);
// Remaining bytes contain the credential cipher text
//
var cipherBytes = new byte[decodedBytes.Length - 8 - 16];
Buffer.BlockCopy(decodedBytes, 8 + 16, cipherBytes, 0, cipherBytes.Length);
string decryptedData = null;
try
{
using (var aes = new AesCryptoServiceProvider())
{
aes.Key = key;
aes.IV = ivBytes;
using (var ms = new MemoryStream())
{
using (var cs = new CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(cipherBytes, 0, cipherBytes.Length);
cs.Close();
}
decryptedData = Encoding.UTF8.GetString(ms.ToArray());
}
}
}
catch (Exception ex)
{
Console.Write("Caught exception while decryption: {0}: ", ex.Message);
}
return decryptedData;
}
public static string EncryptText(string plainData)
{
if (string.IsNullOrEmpty(_passwd))
return null;
var rfc2898db = new Rfc2898DeriveBytes(_passwd, 8, 1000);
byte[] salt = new byte[8];
Buffer.BlockCopy(rfc2898db.Salt, 0, salt, 0, 8);
byte[] key = new byte[32];
Buffer.BlockCopy(rfc2898db.GetBytes(32), 0, key, 0, 32);
string cipherData;
try
{
var aes = new AesCryptoServiceProvider
{
Key = key,
KeySize = 256,
BlockSize = 128,
Mode = CipherMode.CBC,
Padding = PaddingMode.PKCS7
};
aes.GenerateIV();
byte[] encrypted;
using (var ms = new MemoryStream())
{
using (var cs = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write))
{
ms.Write(aes.IV, 0, aes.IV.Length);
ms.Write(salt, 0, 8);
cs.Write(Encoding.UTF8.GetBytes(plainData), 0, plainData.Length);
cs.Close();
}
encrypted = ms.ToArray();
}
byte[] encryptedBytes = new byte[SaltLength + IvLength + encrypted.Length];
Buffer.BlockCopy(salt, 0, encryptedBytes, 0, SaltLength);
Buffer.BlockCopy(aes.IV, 0, encryptedBytes, SaltLength, IvLength);
Buffer.BlockCopy(encrypted, 0, encryptedBytes, SaltLength + IvLength, encrypted.Length);
cipherData = Convert.ToBase64String(encryptedBytes);
}
catch (Exception ex)
{
Console.Write("Caught exception while encryption: {0}", ex.Message);
return null;
}
return cipherData;
}
I am having a problem with my code and cannot figure out the problem.
With fullMsg set to false it works.
If I change fullMsg to true it no longer works even if I set it back to false.
I have no idea what is going on as the byte[] array remains the same in all the cases.
private void sendIndividualMsg(string msg){
//Debug.Log (msg);
byte[] toSend = PackageMsg (msg);
byte[] decoded = UnPackageMsg (toSend);
Debug.Log( System.Text.Encoding.ASCII.GetString(decoded) );
}
private byte[] UnPackageMsg(byte[] msg){
var toDecrypt = msg;
if (fullMsg) {
toDecrypt = new byte[msg.Length - 16];
var decryptIV = new byte[16];
System.Buffer.BlockCopy (msg, 0, decryptIV, 0, 16);
System.Buffer.BlockCopy (msg, 16, toDecrypt, 0, (msg.Length - 16));
//myAes.IV = decryptIV;
}
PrintByteArray (toDecrypt, "ToDecrypt");
byte[] plaintext;
// Create the streams used for decryption.
{
ICryptoTransform decryptor = myAes.CreateDecryptor (myAes.Key, myAes.IV);
MemoryStream msDecrypt = new MemoryStream ();
CryptoStream csDecrypt = new CryptoStream (msDecrypt, decryptor, CryptoStreamMode.Write);
csDecrypt.Write(msg, 0, msg.Length);
csDecrypt.FlushFinalBlock();
csDecrypt.Close();
plaintext = msDecrypt.ToArray();
msDecrypt.Close ();
decryptor.Dispose();
}
if (plaintext.Length > 16) {
byte[] hash = new byte[16];
byte[] hashCalc = new byte[16];
byte[] payload = new byte[plaintext.Length - 16 ];
System.Buffer.BlockCopy (plaintext, 0, hash, 0, 16);
System.Buffer.BlockCopy (plaintext, 16, payload, 0, plaintext.Length - 16);
hashCalc = md5.ComputeHash(payload);
if(ByteArrayCompare(hash, hashCalc)){
return payload;
}else{
return new byte[0];
}
} else {
return new byte[0];
}
}
private byte[] PackageMsg(string msg){
System.Text.ASCIIEncoding ue = new System.Text.ASCIIEncoding();
byte[] bytes = ue.GetBytes(msg);
byte[] hashBytes = md5.ComputeHash(bytes);
byte[] toEncrypt = new byte[bytes.Length + hashBytes.Length];
System.Buffer.BlockCopy(hashBytes, 0, toEncrypt, 0, hashBytes.Length);
System.Buffer.BlockCopy(bytes, 0, toEncrypt, hashBytes.Length, bytes.Length);
//myAes.GenerateIV();
byte[] encrypted;
{
ICryptoTransform encryptor = myAes.CreateEncryptor (myAes.Key, myAes.IV);
MemoryStream msEncrypt = new MemoryStream ();
CryptoStream csEncrypt = new CryptoStream (msEncrypt, encryptor, CryptoStreamMode.Write);
csEncrypt.Write(toEncrypt, 0, toEncrypt.Length);
csEncrypt.FlushFinalBlock();
csEncrypt.Close();
encrypted = msEncrypt.ToArray();
msEncrypt.Close ();
encryptor.Dispose();
}
PrintByteArray (encrypted, "Encrypted");
//SessionBytes + IV + ENCRYPTED( hash + msg)
byte[] finalMsg = new byte[myAes.IV.Length + encrypted.Length ];
System.Buffer.BlockCopy(myAes.IV, 0, finalMsg, 0 , myAes.IV.Length);
System.Buffer.BlockCopy(encrypted, 0, finalMsg, myAes.IV.Length , encrypted.Length);
if (!fullMsg) {
finalMsg = encrypted;
}
return finalMsg;
}
(I want to send the IV through each message, but until I get this working their is no point.)
Basic explanation of the algorithm for encrypting:
If fullMsg is set the encryption is [session][iv][encryptedmsg]
If fullMsg is not set the encryption is [encryptedmsg]
For Decryption the first part of the code is too extract just the encryptedmsg part.
As show by the screenshot of the logs, in both modes the bytes are the same.
--
I have a C# code to decrypt data, now I'm trying to make the same in PHP but I can't get the same result. I know that I missing something but I don't know how to transfer this to PHP. Any ideas? Thanks.
This is the C# code:
public static string Decrypt(string cipherData, string key)
{
byte[] salt = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0 };
byte[] IV = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
PasswordDeriveBytes cdk = new PasswordDeriveBytes(key, salt);
byte[] kex = cdk.CryptDeriveKey("RC2", "SHA1", 128, salt);
RijndaelManaged rijKey = new RijndaelManaged();
rijKey.Mode = CipherMode.CBC;
byte[] textBytes = Convert.FromBase64String(cipherData);
ICryptoTransform decryptor = rijKey.CreateDecryptor(kex, IV);
MemoryStream memoryStream = new MemoryStream(textBytes);
CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read);
byte[] pTextBytes = new byte[(textBytes.Length - 1) + 1];
int decryptedByteCount = cryptoStream.Read(pTextBytes, 0, pTextBytes.Length);
memoryStream.Close();
cryptoStream.Close();
return Encoding.UTF8.GetString(pTextBytes, 0, decryptedByteCount);
}
This is the PHP code trying to make the same (I know that it is incomplete):
function Decrypt($data, $key) {
$method = 'rc2-cbc';
$iv = '0000000000000000';
return utf8_encode(openssl_decrypt($data, $method, sha1($key), OPENSSL_ZERO_PADDING, $iv));
}
I need to encrypt an image, return the string of the encrypted data, then decrypt it
Here's my encryption code :
string plainText = ASCIIEncoding.ASCII.GetString(Imagebytes);
byte[] encrypted;
byte[] key = Encoding.UTF8.GetBytes("M02cnQ51Ji97vwT4");;
// Create an AesCryptoServiceProvider object
using (AesCryptoServiceProvider aesAlg = new AesCryptoServiceProvider())
{
aesAlg.Key = key;
aesAlg.BlockSize = 128;
// Create a decrytor to perform the stream transform.
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
// Create the streams used for encryption.
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
//Write all data to the stream.
swEncrypt.Write(plainText);
}
encrypted = msEncrypt.ToArray();
}
}
}
using (var aesAlg = new AesManaged())
{
aesAlg.Key = new UTF8Encoding().GetBytes("M02cnQ51Ji97vwT4");
aesAlg.IV = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
return UTF8Encoding.UTF8.GetString(encryptor.TransformFinalBlock(Imagebytes, 0, Imagebytes.Length)).Length;
}
My decryption work fine ( because i can receive image / video perfectly )
here's the code:
const string BLOB_KEY = "TTAyY25RNTFKaTk3dndUNA==";
using (RijndaelManaged rm = new RijndaelManaged())
{
rm.Mode = CipherMode.ECB;
rm.Key = Convert.FromBase64String(BLOB_KEY);
rm.IV = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
rm.Padding = PaddingMode.Zeros;
using (MemoryStream ms = new MemoryStream())
{
using (CryptoStream cs = new CryptoStream(ms, rm.CreateDecryptor(),
CryptoStreamMode.Write))
{
cs.Write(image, 0, image.Length);
return ms.ToArray();
}
}
}
What's wrong with my encryption code ?
Your very initial line of code is already wrong:
string plainText = ASCIIEncoding.ASCII.GetString(Imagebytes);
An image is not a string, and plaintext is not necessarily a string either. Both consist of bytes. So you should not be using a StreamWriter either, just a normal stream.
It is likely that data is lost during conversion.
Furthermore, you are writing to a decryption stream and you are using ECB mode at one side and CBC mode at the other.
I would strongly advice you to read into the material and start over.
Thank you, i've changed my code to :
var aesAlg = new AesManaged
{
KeySize = 128,
Key = key,
BlockSize = 128,
Mode = CipherMode.ECB,
Padding = PaddingMode.Zeros,
IV = new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
};
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
return encryptor.TransformFinalBlock(Imagebytes, 0, Imagebytes.Length);
And it works fine !
I'm try to use AES encryption for some text, but the decrypted text is not identical to original one.
Original text: abcd
Decrypted text: ?9T?o??G???x;*
Here is my code:
public static void Main(string[] args)
{
byte[] original = { 97, 98, 99, 100 }; //"abcd"
byte[] key = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
byte[] iv = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
byte[] encrypt = Encrypt(original, key, iv);
byte[] decrypt = Decrypt(encrypt, key, iv);
Console.WriteLine(Encoding.UTF8.GetString(original));
Console.WriteLine(Encoding.UTF8.GetString(decrypt));
Console.ReadKey();
}
public static byte[] Encrypt(byte[] original, byte[] key, byte[] iv)
{
using (var memoryStream = new MemoryStream())
{
using (var aes = new AesManaged { Key = key, IV = iv, Padding = PaddingMode.PKCS7, Mode = CipherMode.CBC })
{
using (var cryptoStream = new CryptoStream(memoryStream, aes.CreateEncryptor(), CryptoStreamMode.Write))
{
cryptoStream.Write(original, 0, original.Length);
}
}
return memoryStream.ToArray();
}
}
public static byte[] Decrypt(byte[] encrypt, byte[] key, byte[] iv)
{
using (var memoryStream = new MemoryStream(encrypt))
{
using (var aes = new AesManaged { Key = key, IV = iv, Padding = PaddingMode.PKCS7, Mode = CipherMode.CBC })
{
using (var cryptoStream = new CryptoStream(memoryStream, aes.CreateEncryptor(), CryptoStreamMode.Read))
{
byte[] decrypt = new byte[encrypt.Length];
cryptoStream.Read(decrypt, 0, decrypt.Length);
return decrypt;
}
}
}
}
What's wrong? Thanks in advance.
You've got this in your decryption code:
using (var cryptoStream = new CryptoStream(memoryStream, aes.CreateEncryptor(),
CryptoStreamMode.Read))
Change it to call aes.CreateDecryptor() and it works fine.
There's something wrong with your decrypt method, use something like this :
public string Decrypt(byte[] EncryptedValue)
{
#region Write the encrypted value to the decryption stream
MemoryStream encryptedStream = new MemoryStream();
CryptoStream decryptStream = new CryptoStream(encryptedStream, DecryptorTransform, CryptoStreamMode.Write);
decryptStream.Write(EncryptedValue, 0, EncryptedValue.Length);
decryptStream.FlushFinalBlock();
#endregion
#region Read the decrypted value from the stream.
encryptedStream.Position = 0;
Byte[] decryptedBytes = new Byte[encryptedStream.Length];
encryptedStream.Read(decryptedBytes, 0, decryptedBytes.Length);
encryptedStream.Close();
#endregion
return UTFEncoder.GetString(decryptedBytes);
}