首页 > 解决方案 > 在.net中加密字符串并在python中解密

问题描述

我正在尝试使用正常工作的 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') 的上述代码的输出 䏺꧴퐄妯৞轴힡莶

任何帮助将不胜感激。

标签: c#asp.netpython-3.xencryptioncryptography

解决方案


看来您PBKDF2HMAC在 python 端的密钥提取不正确。您需要传递正确的参数并获得一个 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使用SHA11000 发子弹。我的建议是你应该至少使用 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.


推荐阅读