[PYTHON-CRYPTO] AES 128 CBC encrypt decrypt size problems

C. Collis koniosis at GMAIL.COM
Fri Nov 21 11:02:54 CET 2008


Hey,

I'm trying to implement rfc 3566 in Python using M2Crypto.

There seem to be some issues however!


Given this python code:
--------------------------------------
from M2Crypto import EVP
import StringIO

def encrypt(data, key, iv):
    buffer = StringIO.StringIO()
    cipher = EVP.Cipher('aes_128_cbc', key=key, iv=iv, op=1)
    buffer.write(cipher.update(data))
    buffer.write(cipher.final())
    data = buffer.getvalue()

    return data


def decrypt(data, key, iv):
    buffer = StringIO.StringIO()
    cipher = EVP.Cipher('aes_128_cbc', key=key, iv=iv, op=0)
    buffer.write(cipher.update(data))
    buffer.write(cipher.final())
    data = buffer.getvalue()
    
    return data

key = bytearray('\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f')
pt = bytearray('\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01')
iv = bytearray('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
ct = encrypt(pt, key, iv)

print "PT Len:", len(pt), "Data: ", repr([hex(x) for x in pt])
print "CT Len:", len(ct), "Data: ", repr([hex(ord(x)) for x in ct])

pt2 = decrypt(ct, key, iv)

assert pt == pt2

--------------------------------------

The CT len is 32 bytes! According to the RFC it should be only 16 bytes. I tried exactly the same test in 
C# .NET using the System.Security.Cryptography library and I get the correct, expected 16 byte CT 
value.

What is strange is that M2Crypto and C# produce the same first 16 bytes of encrypted data, but 
M2Crypto then adds another 16 bytes of junk to the end!

If I try and decrypt the CT data (32 bytes) that M2Crypto produces in C#, I get a 32 byte PT value 
where the first 16 bytes are the correct value and the second 16 bytes are junk!

If I try the other way around and use the encrypted CT data from C# (16 bytes) and try and decrypt it 
using M2Crypto I get a 15 byte PT value that is correct but missing the last byte!

Why is M2Crypto doubling the size of my PT when encrypting and why can't it handle a 16 byte CT value 
correctly? In C# I can decrypt the 16 byte CT value back to the 16 byte PT value as expected.

This is making it impossible to implement the RFC as M2Crypto doesn't appear to produce the correct 
results for AES-128-CBC mode encryption! While M2Crypto can encrypt and decrypt data processed by 
itself it is unable to work with other crypto implementations, what am I missing?


The C# Program is:


---------------------------
using System;
using System.IO;
using System.Security.Cryptography;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            EncryptK1();
            DecryptPythonK1CT();
            Console.ReadKey();
        }

        static byte[] K1 = new byte[] { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 
0x01, 0x01, 0x01, 0x01, 0x01 };
        static byte[] IV = new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
0x00, 0x00, 0x00, 0x00, 0x00 };
        static byte[] KEY = new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 
0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };


        public static void DecryptPythonK1CT()
        {
            Console.WriteLine("Decrypting Python Encrypted K1 Value using C#...");

            byte[] ct = new byte[] { 195, 82, 128, 87, 84, 35, 127, 49, 26, 192, 255, 244, 227, 224, 62, 
120, 169, 125, 222, 82, 14, 200, 65, 189, 3, 69, 101, 3, 189, 71, 131, 144 };

            byte[] pt = Decrypt(KEY, IV, ct);

            Console.Write("K1 Python CT:\t");
            Print(ct);

            Console.Write("K1 C# PT:\t");
            Print(pt);

            Console.WriteLine("");
        }


        public static void EncryptK1()
        {
            Console.WriteLine("Encrypting K1 Value using C#...");

            byte[] ct = Encrypt(KEY, IV, K1);

            Console.Write("K1 PT:\t\t");
            Print(K1);

            Console.Write("K1 C# CT:\t");
            Print(ct);

            Console.WriteLine("");
        }


        static private void Print(byte[] b)
        {
            for (int i = 0; i < b.Length; i++)
            {
                Console.Write(string.Format("{0:X}", b[i]));
            }

            Console.WriteLine();
        }


        private static byte[] Encrypt(byte[] key, byte[] iv, byte[] data)
        {
            byte[] ciphertext = new byte[0];

            Rijndael cipher = RijndaelManaged.Create();
            cipher.Padding = PaddingMode.None;
            cipher.Mode = CipherMode.CBC;

            ICryptoTransform encryptor = cipher.CreateEncryptor(key, iv);

            using (MemoryStream memoryStream = new MemoryStream())
            {
                using (CryptoStream cryptoStream = new CryptoStream(
                    memoryStream, encryptor, CryptoStreamMode.Write))
                {
                    cryptoStream.Write(data, 0, data.Length);

                    cryptoStream.FlushFinalBlock();

                    ciphertext = memoryStream.ToArray();
                }
            }

            return ciphertext;
        }



        private static byte[] Decrypt(byte[] key, byte[] iv, byte[] data)
        {
            byte[] plaintext = new byte[0];

            Rijndael cipher = RijndaelManaged.Create();
            cipher.Padding = PaddingMode.None;
            cipher.Mode = CipherMode.CBC;

            ICryptoTransform decryptor = cipher.CreateDecryptor(key, iv);

            using (MemoryStream memoryStream = new MemoryStream())
            {
                using (CryptoStream cryptoStream = new CryptoStream(
                    memoryStream, decryptor, CryptoStreamMode.Write))
                {

                    cryptoStream.Write(data, 0, data.Length);

                    cryptoStream.FlushFinalBlock();

                    plaintext = memoryStream.ToArray();
                }
            }

            return plaintext;
        }
    }
}
---------------------------

The output of this C# program is:

-----------------------
Encrypting K1 Value using C#...
K1 PT:          1111111111111111
K1 C# CT:     C352805754237F311AC0FFF4E3E03E78

Decrypting Python Encrypted K1 Value using C#...
K1 Python CT:  C352805754237F311AC0FFF4E3E03E78A97DDE52EC841BD345653BD478390
K1 C# PT:       111111111111111110101010101010101010101010101010
-----------------------

Any help greatly appriciated!!

Thanks



More information about the python-crypto mailing list