开发者

Using RijndaelManaged encryption in Silverlight

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();
    Mem开发者_Go百科Stream.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;
}


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.


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜