[Mono-dev] Question about TransformFinalBlock with SymmetricAlgorithms and CBC

David Wolinsky davidiw at ufl.edu
Fri Jan 30 14:51:14 EST 2009


Sebastien Pouliot wrote:
> On Fri, 2009-01-30 at 13:59 -0500, David Wolinsky wrote:
>   
>> Sebastien Pouliot wrote:
>>     
>>> On Fri, 2009-01-30 at 12:27 -0500, David Wolinsky wrote:
>>>   
>>>       
>>>> Hey guys,
>>>>
>>>> Just wanted to let you know a behavioral difference between .Net and 
>>>> Mono and potentially get advice from you.  The method 
>>>> SA.CreateEncryptor.TransformFinalBlock() differs on the two platforms.  
>>>> Specifically, Mono appears to continue from where the last one ended, 
>>>> whereas .Net repeats itself (i.e. the IV is the same IV you inserted 
>>>> when the ICryptoTransform was created).
>>>>
>>>> Below is a sample.
>>>>
>>>> using System;
>>>> using System.Security.Cryptography;
>>>>
>>>> public class tdes_test {
>>>>   public static void Main() {
>>>>     RijndaelManaged rm = new RijndaelManaged();
>>>>     byte[] key = new byte[rm.KeySize / 8];
>>>>     for(int i = 0; i < key.Length; i++) {
>>>>       key[i] = (byte) i;
>>>>     }
>>>>     byte[] iv = new byte[rm.BlockSize / 8];
>>>>     for(int i = 0; i < iv.Length; i++) {
>>>>       iv[i] = (byte) i;
>>>>     }
>>>>     ICryptoTransform encryptor = rm.CreateEncryptor(key, iv);
>>>>     byte[] data = new byte[111];
>>>>     for(int i = 0; i < data.Length; i++) {
>>>>       data[i] = (byte) i;
>>>>     }
>>>>
>>>>     byte[] encrypted_data = encryptor.TransformFinalBlock(data, 0, 
>>>> data.Length);
>>>>     for(int i = 0; i < encrypted_data.Length; i++) {
>>>>       Console.Write(encrypted_data[i]);
>>>>     }
>>>>     Console.WriteLine("\n");
>>>>     encrypted_data = encryptor.TransformFinalBlock(data, 0, data.Length);
>>>>     for(int i = 0; i < encrypted_data.Length; i++) {
>>>>       Console.Write(encrypted_data[i]);
>>>>     }
>>>>   }
>>>> }
>>>>
>>>>
>>>> We're currently using this on a datagram security system and on Mono 
>>>> (not sure if .Net is the same) creation of Encryptors and Decryptors is 
>>>> expensive.  Any thoughts or suggestions?
>>>>     
>>>>         
>>> Your code should always* look at ICryptoTransform.CanReuseTransform
>>> before reusing a transform. If false then it cannot be reused.
>>>
>>> * since you should be using the factory methods to create ciphers
>>> (e.g. Rijndael.Create) and you can't be sure what exact class the
>>> runtime will instantiate (nor it's behavior).
>>>
>>> Sebastien
>>>
>>>
>>>   
>>>       
>> Thanks for the reply.
>>
>> In our deployed code, I actually use SymmetricAlgorithm.Create(string), 
>> and it is a cleaner API, this was just a test.
>>     
>
> Great :)
>
>   
>> Now on to the "ReuseTransform" part.  We'd expect the same result in 
>> both .Net and Mono, but it is different.  .Net returns true, while Mono 
>> returns false.  (This is both with and without Rijndael.Create).  Am I 
>> wrong in expecting the same behavior from both platforms?
>>     
>
> Yes and no. We generally tend to do the exact same (good or bad) thing -
> but this one is an exception because you should not expect any specific
> value, either true or false *even* on MS platforms alone. That's
> because:
>
> (a) it could change in the future (e.g. the default Rijndael could be
> provided by a CSP or CNG provider in future frameworks). This is less
> likely for RijndaelManaged but you can't be sure this is what you'll
> receive when using the factory methods; 
>
> 	or more likely (i.e. it could occur today)
>
> (b) someone could have an alternative implementation (e.g. native or
> hardware acceleration) and have its machine.config redirect the
> "default" Rijndael implementation to some custom code.
>
> In both case you cannot assume if you can, or can't, reuse a transform
> without checking the property. So yes Mono has a different default value
> - but this is not the real (or the major) issue.
>
> Sebastien
>
>
>   
Thanks for the wealth of information and making it clear.  I agree this 
is not the issue, obviously we cannot use the TransformFinalBlock 
without a) creating decryptors and encryptors each time or b) force 
users to use a frozen mono version.  So back to the original question...

"We're currently using this on a datagram security system and on Mono 
(not sure if .Net is the same) creation of Encryptors and Decryptors is 
expensive. Any thoughts or suggestions?"

Could we yank out the guts of Mono's FinalEncrypt/FinalDecrypt and just 
use the TransformBlock instead of the internal calls without worries?  
Is there another approach that I am blind to?

Thanks,
David


More information about the Mono-devel-list mailing list