i am using AES encryption/decryption in Python3 using the pip pycryptodome
package on Linux (Debian, ubuntu).
now i needed to implement the same program for Windows by using C#.
but the encryption results differs between the two platforms (slightly).
- AES encryptions from Python (Linux) cannot decrypted on C# (Windows),
i get an exception because of wrong padding - AES encryptions from C# (Windows) cannot always decrypted on Python (Linux).
- but it is always possible to decrypt encryptions from the same programming language when it was encrypted with the same language.
EDIT: i installed python 3.11 and pip pycryptodome on the windows system and there the test.py parogram behaves the same as on the linux system. but using python there is no option. i have to stick on C# on the windows system.
AES encryptions/decryptions on python:
t:'TEST+++TEST+++TEST' -> e:'dMTh7CVOf/1PkhTEWRsnv68j' -> d:'TEST+++TEST+++TEST'
AES encryptions/decryptions on C#:
t:'TEST+++TEST+++TEST' -> e:'dMTh7CVOf/1PkhTEWRsnv68jdQ==' -> d:'TEST+++TEST+++TEST'
what i am doing wrong here?
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
import base64
# pip install pycryptodome
from Crypto.Cipher import AES
KEY = b'x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41'
IV = b'x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41x41'
MODE = AES.MODE_CFB
BLOCK = 128
def en(plain_text):
crypto = AES.new(key=KEY, mode=MODE, iv=IV)
crypto.block_size = BLOCK
b_plain = plain_text.encode('utf-8')
b_encrypted = crypto.encrypt(b_plain)
base64_encrypted_text = base64.b64encode(b_encrypted).decode('utf-8')
return base64_encrypted_text
def de(base64_encrypted_text):
crypto = AES.new(key=KEY, mode=MODE, iv=IV)
crypto.block_size = BLOCK
b_encrypted = base64.b64decode(base64_encrypted_text)
b_plain = crypto.decrypt(b_encrypted)
plain_text = b_plain.decode('utf-8')
return plain_text
t = 'TEST+++TEST+++TEST'
e = en(t)
d = de(e)
print(f"t:'{t}' -> e:'{e}' -> d:'{d}'")
# t:'TEST+++TEST+++TEST' -> e:'dMTh7CVOf/1PkhTEWRsnv68j' -> d:'TEST+++TEST+++TEST'
// C# .NET 6.0 Console
//
using System.Security.Cryptography;
byte[] KEY = { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 };
byte[] IV = { 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41 };
CipherMode MODE = CipherMode.CFB;
int BLOCK = 128;
string en(string plain_text)
{
string base64_encrypted_text;
using (var crypto = Aes.Create())
{
crypto.Mode = MODE;
crypto.BlockSize = BLOCK;
crypto.Key = KEY;
crypto.IV = IV;
using (var s_encrypted = new MemoryStream())
{
using (var s_crypto = new CryptoStream(s_encrypted, crypto.CreateEncryptor(KEY, IV), CryptoStreamMode.Write))
{
using (var s_plain = new StreamWriter(s_crypto))
{
s_plain.Write(plain_text);
}
}
base64_encrypted_text = Convert.ToBase64String(s_encrypted.ToArray());
}
}
return base64_encrypted_text;
}
string de(string base64_encrypted_text)
{
string plain_text;
using (var crypto = Aes.Create())
{
crypto.Mode = MODE;
crypto.BlockSize = BLOCK;
crypto.Key = KEY;
crypto.IV = IV;
var b_encrypted = Convert.FromBase64String(base64_encrypted_text);
using (var s_encrypted = new MemoryStream(b_encrypted))
{
using (var s_crypto = new CryptoStream(s_encrypted, crypto.CreateDecryptor(KEY, IV), CryptoStreamMode.Read))
{
using (var s_plain = new StreamReader(s_crypto))
{
plain_text = s_plain.ReadToEnd();
}
}
}
}
return plain_text;
}
var t = "TEST+++TEST+++TEST";
var e = en(t);
var d = de(e);
Console.WriteLine($"t:'{t}' -> e:'{e}' -> d:'{d}'");
// t:'TEST+++TEST+++TEST' -> e:'dMTh7CVOf/1PkhTEWRsnv68jdQ==' -> d:'TEST+++TEST+++TEST'
2
Answers
thank you @relent95 for the hint.
now it works with setting the
crypto.Padding = PaddingMode.None;
. (it was set toPaddingMode.PKCS7
by default)BTW.: the order of settings are very important. e.g.: setting the
crypto.Mode
will alter other settings.NOTE: this is only working in .NET 6.0.
in .NET 4.7 or .NET 4.8 it is still not working!!!
PyCryptoDome correctly implements the CFB(Cipher feedback) mode, where the size of a cipher text is the same as the size of the corresponding plain text and padding is not required. But the
System.Security.Cryptography
of .NET framework prior to 6.0 does not support encrypting without padding in the CFB mode.If you are using .NET 6.0 or later, you can disable padding like this(with attribution to ‘beta-tester’).
And if you are using .NET prior to 6.0(including Mono), you can truncate the cipher text like this.
And as a side note, you don’t need to set the BlockSize property of a cipher. (For example, the block size of AES algorithm is 128 bit by definition.)