AES 128 CBC encrypt decrypt size problems
"C. Collis" <[email protected]> Fri, 21 Nov 2008 11:02:54 +0100
| Newsgroups | gmane.comp.python.cryptography |
|---|---|
| Message-ID | <LISTSERV%[email protected]> |
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 =3D StringIO.StringIO()
cipher =3D EVP.Cipher('aes_128_cbc', key=3Dkey, iv=3Div, op=3D1)
buffer.write(cipher.update(data))
buffer.write(cipher.final())
data =3D buffer.getvalue()
return data
def decrypt(data, key, iv):
buffer =3D StringIO.StringIO()
cipher =3D EVP.Cipher('aes_128_cbc', key=3Dkey, iv=3Div, op=3D0)
buffer.write(cipher.update(data))
buffer.write(cipher.final())
data =3D buffer.getvalue()
=20=20=20=20
return data
key =3D bytearray('\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x=
0d\x0e\x0f')
pt =3D bytearray('\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x01\x0=
1\x01\x01')
iv =3D bytearray('\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x0=
0\x00\x00')
ct =3D 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 =3D decrypt(ct, key, iv)
assert pt =3D=3D pt2
--------------------------------------
The CT len is 32 bytes! According to the RFC it should be only 16 bytes. =
I tried exactly the same test in=20
C# .NET using the System.Security.Cryptography library and I get the corr=
ect, expected 16 byte CT=20
value.
What is strange is that M2Crypto and C# produce the same first 16 bytes o=
f encrypted data, but=20
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=20
where the first 16 bytes are the correct value and the second 16 bytes ar=
e junk!
If I try the other way around and use the encrypted CT data from C# (16 b=
ytes) and try and decrypt it=20
using M2Crypto I get a 15 byte PT value that is correct but missing the l=
ast byte!
Why is M2Crypto doubling the size of my PT when encrypting and why can't =
it handle a 16 byte CT value=20
correctly? In C# I can decrypt the 16 byte CT value back to the 16 byte P=
T value as expected.
This is making it impossible to implement the RFC as M2Crypto doesn't app=
ear to produce the correct=20
results for AES-128-CBC mode encryption! While M2Crypto can encrypt and d=
ecrypt data processed by=20
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 =3D new byte[] { 0x01, 0x01, 0x01, 0x01, 0x01, 0=
x01, 0x01, 0x01, 0x01, 0x01, 0x01,=20
0x01, 0x01, 0x01, 0x01, 0x01 };
static byte[] IV =3D new byte[] { 0x00, 0x00, 0x00, 0x00, 0x00, 0=
x00, 0x00, 0x00, 0x00, 0x00, 0x00,=20
0x00, 0x00, 0x00, 0x00, 0x00 };
static byte[] KEY =3D new byte[] { 0x00, 0x01, 0x02, 0x03, 0x04, =
0x05, 0x06, 0x07, 0x08, 0x09,=20
0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
public static void DecryptPythonK1CT()
{
Console.WriteLine("Decrypting Python Encrypted K1 Value using=
C#...");
byte[] ct =3D new byte[] { 195, 82, 128, 87, 84, 35, 127, 49,=
26, 192, 255, 244, 227, 224, 62,=20
120, 169, 125, 222, 82, 14, 200, 65, 189, 3, 69, 101, 3, 189, 71, 131, 14=
4 };
byte[] pt =3D 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 =3D 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 =3D 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 =3D new byte[0];
Rijndael cipher =3D RijndaelManaged.Create();
cipher.Padding =3D PaddingMode.None;
cipher.Mode =3D CipherMode.CBC;
ICryptoTransform encryptor =3D cipher.CreateEncryptor(key, iv=
);
using (MemoryStream memoryStream =3D new MemoryStream())
{
using (CryptoStream cryptoStream =3D new CryptoStream(
memoryStream, encryptor, CryptoStreamMode.Write))
{
cryptoStream.Write(data, 0, data.Length);
cryptoStream.FlushFinalBlock();
ciphertext =3D memoryStream.ToArray();
}
}
return ciphertext;
}
private static byte[] Decrypt(byte[] key, byte[] iv, byte[] data)=
{
byte[] plaintext =3D new byte[0];
Rijndael cipher =3D RijndaelManaged.Create();
cipher.Padding =3D PaddingMode.None;
cipher.Mode =3D CipherMode.CBC;
ICryptoTransform decryptor =3D cipher.CreateDecryptor(key, iv=
);
using (MemoryStream memoryStream =3D new MemoryStream())
{
using (CryptoStream cryptoStream =3D new CryptoStream(
memoryStream, decryptor, CryptoStreamMode.Write))
{
cryptoStream.Write(data, 0, data.Length);
cryptoStream.FlushFinalBlock();
plaintext =3D 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: C352805754237F311AC0FFF4E3E03E78A97DDE52EC841BD345653BD478=
390
K1 C# PT: 111111111111111110101010101010101010101010101010
-----------------------
Any help greatly appriciated!!
Thanks