Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

Re: AES Interoperability between Perl and C#

by Thelonius (Priest)
on Nov 17, 2005 at 04:06 UTC ( [id://509284]=note: print w/replies, xml ) Need Help??


in reply to AES Interoperability between Perl and C#

I have hardly used C# at all, so this is not great code. I did it just now as a learning experience, cobbling it together from the MSDN examples. I piped the out of the C# program below to the input of this Perl program:
use MIME::Base64; use Crypt::Rijndael; use bytes; use strict; use warnings; $_ = <>; my $in = decode_base64($_); my $key = pack("H*", "01020304050607080910111213141516"); my $cipher = new Crypt::Rijndael $key, Crypt::Rijndael::MODE_CBC or die "Error: $!"; $cipher->set_iv(substr($in, 0, 16)); print "out = '", unpack("N/A", $cipher->decrypt(substr($in, 16))), "'\n";
And here is the C# program:
using System; using System.IO; using System.Text; using System.Security.Cryptography; using System.Net; public class main { public static void Main(string[] args) { byte[] key = {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16}; byte[] IV; string original = "This is a test."; ASCIIEncoding textConverter = new ASCIIEncoding(); RijndaelManaged myRijndael = new RijndaelManaged(); byte[] encrypted; byte[] toEncrypt; byte[] encLen; myRijndael.Mode = CipherMode.CBC; //Create a new initialization vector. myRijndael.GenerateIV(); IV = myRijndael.IV; //Get an encryptor. ICryptoTransform encryptor = myRijndael.CreateEncryptor(key, IV); //Encrypt the data. MemoryStream msEncrypt = new MemoryStream(); // I'm using base64 encoding CryptoStream b64 = new CryptoStream(msEncrypt, new ToBase64Transform(), CryptoStreamMode.Write); b64.Write(IV, 0, IV.Length); // Write IV before encryption CryptoStream csEncrypt = new CryptoStream(b64, encryptor, CryptoStreamMode.Write); //Convert the data to a byte array. toEncrypt = textConverter.GetBytes(original); // Get the string length and convert to bytes in network order encLen = BitConverter.GetBytes( IPAddress.HostToNetworkOrder(toEncrypt.Length)); csEncrypt.Write(encLen, 0, encLen.Length); //Write all data to the crypto stream and flush it. csEncrypt.Write(toEncrypt, 0, toEncrypt.Length); csEncrypt.FlushFinalBlock(); //Get encrypted array of bytes. encrypted = msEncrypt.ToArray(); // Here we write to console, but of course you // may want to include it in an XML response Console.WriteLine(textConverter.GetString(encrypted)); } }

Replies are listed 'Best First'.
Re^2: AES Interoperability between Perl and C#
by ikegami (Patriarch) on Nov 17, 2005 at 07:39 UTC

    Your code doesn't work if the cleartext is not an exact multiple of 16 bytes in length (and maybe even if it is), because Crypt::Rijndael doesn't handle padding. Crypt::CBC handles that.

    Your Perl code manually prepends/extracts the IV to/from the encrypted text. Crypt::CBC handles that.

    Crypt::CBC has other features too, such as generating a random IV when so desired.

    That's why Crypt::Rijndael should be in conjunction with Crypt::CBC instead of using Crypt::Rijndael's CBC mode.

    The fix (and simplification) is:

    use strict; use warnings; use MIME::Base64; use Crypt::CBC; my $key = pack("H*", "01020304050607080910111213141516"); my $cipher = Crypt::CBC->new(-cipher => 'Rijndael'); my $in = decode_base64(<>); print "out = '", unpack("N/A", $cipher->decrypt($in)), "'\n";

    By the way, I removed use bytes since it was useless since you didn't use any numbers except the constants 0 and 16.

    Also, I don't think Crypt::Rijndael's new sets $! (or ever returns false).

    (Untested. I don't have these modules.)

      My program works fine for strings that are not multiples of 16 bytes.

      I could not get Crypt:CBC to work in a compatible way. I might have gotten in to work by experimenting with padding and the IV on both sides, but since my method works, there didn't seem to be any advantage.

        Oh I see! You (redundantly) include the length of the plaintext, and require extra code on the decryption side to remove the padding. If you used Crypt::CBC, you wouldn't need to include the length of the plaintext in the ciphertext.

        Caveat: I'm assuming FlushFinalBlock uses a padding method compatible with Crypt::CBC's. Well, Crypt::CBC since Crypt::CBC can handle any padding, so I guess I meant "compatible with the default Crypt::CBC padding method".

Re^2: AES Interoperability between Perl and C#
by jpfarmer (Pilgrim) on Nov 17, 2005 at 22:03 UTC

    Thank you for the code sample. One part I'm curious about in the C# segment. Do you understand the significance of this block?

    encLen = BitConverter.GetBytes( IPAddress.HostToNetworkOrder(toEncrypt.Length)); csEncrypt.Write(encLen, 0, encLen.Length);

    When I comment it out, the encrypted string becomes much shorter, but it's still decryptable.

      There's two common ways of storing a string.

      1) NUL-terminated.

      The end of the string is marked by the first occurance of a NUL character.

      Pro: The string can be of any length.
      Con: The string cannot contain NULs.

      2) PASCAL string.

      Named after the programming language. The length of the string is stored along with the string itself.

      Pro: The string can contain any character.
      Con: The size of the length field limits the size of the string.

      Thelonius chose the latter. And in this case, the limit on the string length is (2^32)-1 (over 2 billion) since he's using a 32 bit signed int for the length field.

        So by commenting that out, I'm forcing the NUL-terminated mode?

Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Node Status?
node history
Node Type: note [id://509284]
help
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others rifling through the Monastery: (7)
As of 2025-06-12 13:15 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found

    Notices?
    erzuuliAnonymous Monks are no longer allowed to use Super Search, due to an excessive use of this resource by robots.