将C#加密算法转换为Python 3

时间:2019-05-02 15:20:24

标签: c# python .net encryption aes

已为我提供了一种现有的加密算法,该算法需要在通过API发送密码之前对密码进行加密。

除Python之外,我没有其他语言的经验,因此我无法理解复制该语言需要执行的功能。

我相信C#中AES的默认模式是CBC。我想我已经复制了所需的大部分工作,但是我需要填充数据,而且我不知道确切会发生在哪个阶段,或者在哪里添加长度。我不了解C代码中发生的顺序。我也相信默认的填充方法是PKCS#7,尽管我很高兴对此进行任何纠正。

Original code

public static string EncryptStringToBytes_Aes(string username, string password)
{
    string encrypted = string.Empty;
    byte[] clearBytes = Encoding. UTF8.GetBytes(password);
    using (Aes aesAlg = Aes.Create())
    {
        byte[] k;
        byte[] iv;
          byte[] bytes = Encoding.UTF8.GetBytes(username);
        k = SHA256.Create().ComputeHash(bytes);
        iv = MD5.Create().ComputeHash(bytes);
        aesAlg.Key = k;
        aesAlg.IV = iv;

        ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, 
        aesAlg.IV);

        using (MemoryStream msEncrypt = new MemoryStream())
        {
                using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, 
                encryptor, CryptoStreamMode.Write))
                {
                    csEncrypt.Write(clearBytes, 0, clearBytes.Length);
                }
                encrypted = Convert.ToBase64String(msEncrypt.ToArray());
        }
    }
    return encrypted;
}
python recreation

from Crypto.Cipher import AES
import hashlib
username = "example"
password = "example2"
mode = AES.MODE_CBC
clearbytes = password.encode('utf-8')
bytes = username.encode('utf-8')
key = hashlib.sha256(bytes).digest()
iv = hashlib.md5(bytes).digest()

encryptor = AES.new(key, mode, IV = iv)
length = password + '0' + str(len(clearbytes))
encrypted= encryptor.encrypt(length).encode('base64')

我收到“ ValueError:输入字符串的长度必须为16的倍数”。

当我尝试了一些填充时,编码状态为“ AttributeError:'bytes'对象没有属性'encode'”

我希望可以阅读此代码的人可以帮助我完成在Python中重新创建功能的最后步骤。

2 个答案:

答案 0 :(得分:1)

看着docs,您没有正确使用密码模块。

调用AES.new()时,您传递的密钥必须是16个字符的字节字符串,因此您需要填充key属性以使其具有16个字节的长度。

encrypt()方法采用字节字符串作为输入,因为您似乎试图传递一个长度(在示例中甚至没有定义)。

您的评论建议您还是通过了它,否则您将看不到AttributeError异常。

您看到的AttributeError是因为Cipher.encrypt()返回一个字节数组,而字节数组没有encode()方法。您首先需要将字节数组转换为字符串。来自here的以下代码段应有所帮助:

import array
decoded = array.array('b', your_input).tostring().decode('utf-8') 

您显然应该将'utf-8'替换为'base64'

答案 1 :(得分:1)

我相信我已经成功了,这里结合了答案和评论。不需要填充密钥,因为哈希已经是16的倍数。(希望成功的)以下代码供参考。 (不幸的是,在测试连接之前,我还有另外两节C#代码要翻译!)

Python Conversion

from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
import hashlib
import base64


username = "example"
password = "example"
mode = AES.MODE_CBC
bytes = username.encode('utf-8')
data_for_padding = password + '0' + str(len(password))
padded = pad(data_for_padding)

key = hashlib.sha256(bytes).digest()
iv = hashlib.md5(bytes).digest()
encryptor = AES.new(key, mode, IV = iv)
clearbytes = padded.encode('utf-8')
ciphertext = encryptor.encrypt(clearbytes)

result = base64.b64encode(ciphertext)