2

I'm implementing a webservice client that is required to encrypt the request using 128-bits Rijndael. Because the RijndaelManaged class doesn't exist in Silverlight, I've followed the advice here: This was discussed here: AesManaged and RijndaelManaged

The result is that the result I'm getting is correct (I mean, the same I'm getting using RijndaelManaged) only for the first 32 characters (128 bits), exactly the block size. I can't figure out what I'm doing wrong here. My .Net implementation (RijndaelManaged) goes like this:

private static byte[] Encrypt(byte[] PlainTextBytes, byte[] KeyBytes, string InitialVector)
{
    byte[] InitialVectorBytes = Encoding.UTF8.GetBytes(InitialVector);
    RijndaelManaged SymmetricKey = new RijndaelManaged();
    SymmetricKey.Mode = CipherMode.ECB;
    SymmetricKey.Padding = PaddingMode.PKCS7;
    SymmetricKey.BlockSize = 128;
    ICryptoTransform Encryptor = SymmetricKey.CreateEncryptor(KeyBytes, InitialVectorBytes);
    MemoryStream MemStream = new MemoryStream();
    CryptoStream CryptoStream = new CryptoStream(MemStream, Encryptor, CryptoStreamMode.Write);
    CryptoStream.Write(PlainTextBytes, 0, PlainTextBytes.Length);
    CryptoStream.FlushFinalBlock();
    byte[] CipherTextBytes = MemStream.ToArray();
    MemStream.Close();
    CryptoStream.Close();

    return CipherTextBytes;
}

while my Silverlight is:

private string Encrypt(byte[] PlainTextBytes, byte[] KeyBytes, string InitialVector)
{
    AesManaged SymmetricKey = new AesManaged();
    byte[] InitialVectorBytes = SymmetricKey.IV;
    //NOTE- because Mode and Padding don't exist in AESManaged for Silverlight, I have to do the padding myself
    //for an empty InitalVector (which is my case)
    for (int i = 0; i < InitialVectorBytes.Length; i++) InitialVectorBytes[i] = 0;
    SymmetricKey.BlockSize = 128;
    ICryptoTransform Encryptor = SymmetricKey.CreateEncryptor(KeyBytes, InitialVectorBytes);
    MemoryStream MemStream = new MemoryStream();
    CryptoStream CryptoStream = new CryptoStream(MemStream, Encryptor, CryptoStreamMode.Write);
    CryptoStream.Write(PlainTextBytes, 0, PlainTextBytes.Length);
    CryptoStream.FlushFinalBlock();
    byte[] CipherTextBytes = MemStream.ToArray();
    MemStream.Close();
    CryptoStream.Close();

    return CipherTextBytes;
}
Community
  • 1
  • 1
magarcias
  • 53
  • 1
  • 5

2 Answers2

0

It's not clear that you're really clearing the IV. You're fetching it as a byte array and then clearing that, but I don't know for sure whether the IV property copies the internal value before returning it. I'd use this:

SymmetricKey.BlockSize = 128;
SymmetricKey.IV = new byte[SymmetricKey.BlockSize / 8];

(I'd also stop using PascalCase for parameters and local variables, by the way. The normal convention is to use camelCase for non-constant variables.)

EDIT: Sample code to demonstrate how your code isn't really changing the IV:

AesManaged aes = new AesManaged();
byte[] iv = aes.IV;
iv[0] = 1;
iv[1] = 2;
Console.WriteLine(BitConverter.ToString(iv));      
Console.WriteLine(BitConverter.ToString(aes.IV));

Sample output:

01-02-01-1B-6E-05-B8-2A-C0-86-17-EF-A2-80-60-7B
D8-48-01-1B-6E-05-B8-2A-C0-86-17-EF-A2-80-60-7B

In other words, changing the values in the array isn't changing the IV really.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • @Jon_Skeet Thanks for tip, that's not the problem because the Initial vector is used to create the encryptor later, and the results I'm getting are the same. Thanks for the advice anyway. – magarcias Mar 21 '11 at 07:50
  • @magarcias: *Which* initial vector though? The one that you thought was empty, or the one which is *actually* empty? – Jon Skeet Mar 21 '11 at 07:51
  • @Jon_skeet Either. I've tried setting the initial vector and key, or using them in the CreateEncryptor call, or initializing the vector like you suggested. All options give the same result, apparently these are equivalent: SymmetricKey.Key = KeyBytes; SymmetricKey.IV = InitialVectorBytes; ICryptoTransform Encryptor = SymmetricKey.CreateEncryptor(); and: ICryptoTransform Encryptor = SymmetricKey.CreateEncryptor(KeyBytes, InitialVectorBytes); – magarcias Mar 21 '11 at 10:22
  • @margarcias: Is that having set InitialVectorBytes to a zero-initialized array? (Your code would still be clearer if you'd follow normal .NET naming conventions, btw.) – Jon Skeet Mar 21 '11 at 10:50
0

Your .NET version uses EBC mode for AES while the Silverlight version uses CBC. The first output block is the same in both versions because in ECB mode the initialization vector is not used and in CBC mode the initialization vector is zero. In CBC mode each block is XORed with the previous block (first block is XORed with the initialization vector) and then encrypted while in EBC mode each block is encrypted as it is.

iPDFdev
  • 5,229
  • 2
  • 17
  • 18