在.net中加密字符串并在python中解密

时间:2019-01-03 06:08:53

标签: c# asp.net python-3.x encryption cryptography

我正在尝试使用正常工作的system.Security.Cryptography加密密码 这是代码(.Net)

if (clearText == null)
{
    clearText = "";
}
string EncryptionKey = "****";
byte[] clearBytes = Encoding.Unicode.GetBytes(clearText);
using (Aes encryptor = Aes.Create())
{
    Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
    encryptor.Key = pdb.GetBytes(32);
    encryptor.IV = pdb.GetBytes(16);
    using (MemoryStream ms = new MemoryStream())
    {
        using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
        {
            cs.Write(clearBytes, 0, clearBytes.Length);
            cs.Close();
        }
        clearText = Convert.ToBase64String(ms.ToArray());
    }
}
return clearText;

这是python中的解密代码,无法正常工作

def Decryptstr(self, text):
    try:
        EncryptionKey = "****"
        if text is None:
            return
        else:
            cipherbytes = base64.b64decode(text)
            salt = '\0x49\0x76\0x61\0x6e\0x20\0x4d\0x65\0x64\0x76\0x65\0x64\0x65\0x76'
            key_bytes = KDF.PBKDF2(EncryptionKey, salt, dkLen=32)
            iv = KDF.PBKDF2(EncryptionKey, salt,dkLen=16)
            cipher = AES.new(key_bytes, AES.MODE_CBC, iv)
            password = cipher.decrypt(cipherbytes).decode('utf-16')
            print(password)
            return password
    except Exception as err:
        print(err)

以下是加密字符串('eet123')的上述代码的输出 䏺꧴퐄妯৞轴힡莶

任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:2)

看来您在Python端进行的PBKDF2HMAC键提取不正确。您需要传递正确的参数并获取48个字节的密钥。然后(在您的设计中)将前32个字节用作Key,将后16个字节用作IV

这是一个有效的C# / Python代码对。 C#的第一部分:

static string encrypt(string clearText = "")
{
    if (clearText == null)
    {
        clearText = "";
    }

    string EncryptionKey = "****";
    byte[] clearBytes = Encoding.UTF8.GetBytes(clearText);
    using (Aes encryptor = Aes.Create())
    {
       Rfc2898DeriveBytes pdb = new Rfc2898DeriveBytes(EncryptionKey, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 }, 100000, HashAlgorithmName.SHA1);
       encryptor.Key = pdb.GetBytes(32);
       encryptor.IV = pdb.GetBytes(16);
       encryptor.Mode = CipherMode.CBC;
       using (MemoryStream ms = new MemoryStream())
       {
            using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write))
            {
                cs.Write(clearBytes, 0, clearBytes.Length);
                cs.Close();
            }
        clearText = Convert.ToBase64String(ms.ToArray());
        }
    }
    return clearText;
} 

关于此C#代码:

  1. 默认情况下,Rfc2898DeriveBytes仅使用SHA1且只能进行1000发回合。我的建议是您至少应使用100,000。我见过使用1,000,000回合的代码应用程序。您也可以根据需要更改哈希,但是回合数更为重要。
  2. 也指定模式。尽管默认情况下使用CBC,但我认为最好指定它。
  3. 由于C#使用密钥长度来选择AES算法,因此此代码使用AES-256

现在Python部分:

from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from cryptography.hazmat.backends import default_backend

def Decryptstr(self, text):
    try:
        if text is None:
            return
        else:
            backend = default_backend()
            EncryptionKey = "****"
            salt = bytes([ 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 ])
            kdf = PBKDF2HMAC(algorithm=hashes.SHA1(),length=48,salt=salt,iterations=100000,backend=backend)
            key_parts = kdf.derive(bytes(EncryptionKey, 'utf-8'))
            key = key_bytes[0:32]
            iv = key_bytes[32:]

            cipherbytes = base64.b64decode(text)
            cipher = AES.new(key, AES.MODE_CBC, iv)
            password = cipher.decrypt(cipherbytes).decode('utf-8')
            print(password)
            return password
    except Exception as err:
        print(err)

如您所见,我使用了另一个PBKDF2HMAC库。我用它来创建48个字节,并将前32个字节用作Key,后16个字节用作IV