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

C# 在.net中加密字符串并在python中解密,c#,asp.net,python-3.x,encryption,cryptography,C#,Asp.net,Python 3.x,Encryption,Cryptography,我正在尝试使用system.Security.Cryptography加密密码,该密码工作正常 这是代码(.Net) 这是python中的解密代码,无法正常工作 def Decryptstr(self, text): try: EncryptionKey = "****" if text is None: return else: cipherbytes = base64.b64decode(

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

这是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”)的上述代码的输出 䏺꧴퐄妯৞軸힡薟


任何帮助都将不胜感激。

您的
PBKDF2HMAC
python端的密钥提取似乎不正确。您需要传递正确的参数并获得48字节的密钥。然后将前32个字节用作
,最后16个字节用作
IV
(在您的设计中)

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

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;
} 
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)
关于此
C#
code:

  • 默认情况下,
    Rfc2898DeriveBytes
    使用
    SHA1
    ,并且仅使用1000轮。我的建议是你至少应该使用100000。我见过使用1000000轮的代码应用程序。如果愿意,您也可以更改哈希,但轮数更重要
  • 也指定模式。尽管默认情况下它使用
    CBC
    ,但我认为最好指定它
  • 由于
    C#
    使用密钥长度选择
    AES
    算法,因此此代码使用
    AES-256
    现在
    Python
    部分:

    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;
    } 
    
    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个字节用作
    键,最后16个字节用作
    IV
    似乎python端的
    PBKDF2HMAC
    键提取不正确。您需要传递正确的参数并获得48字节的密钥。然后将前32个字节用作
    ,最后16个字节用作
    IV
    (在您的设计中)

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

    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;
    } 
    
    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)
    
    关于此
    C#
    code:

  • 默认情况下,
    Rfc2898DeriveBytes
    使用
    SHA1
    ,并且仅使用1000轮。我的建议是你至少应该使用100000。我见过使用1000000轮的代码应用程序。如果愿意,您也可以更改哈希,但轮数更重要
  • 也指定模式。尽管默认情况下它使用
    CBC
    ,但我认为最好指定它
  • 由于
    C#
    使用密钥长度选择
    AES
    算法,因此此代码使用
    AES-256
    现在
    Python
    部分:

    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;
    } 
    
    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个字节,在C#code中,前32个字节作为
    键,后16个字节作为
    IV

    ,您如何告诉
    Aes
    类模式是
    CBC
    ?或者默认为
    CBC
    ?默认情况下,用于加密的分组密码模式为c#@ikerberaI think
    .GetBytes()
    中的CBC。在这种情况下,C#IV是字节[32:48],而Python IV是字节[0:16](这也是密钥的前半部分!)。另外,我不确定
    KDF.PBKDF2
    中的defult哈希算法是什么,但我认为它与
    Rfc2898DeriveBytes
    (SHA1)相同。KDF.PBKDF2和Rfc2898DeriveBytes@t.m.adam的哈希算法都是相同的。用C编写一个完整的实现,对未加密的文本进行往返。然后用python编写另一个完整的实现,实现同样的功能。尝试将它们分解成小块的功能,在这两个方面做相同的事情。这样一来,a)比较阶段的输出并找出它们不一致的地方要容易得多,b)然后引入一个点,其中一个将数据交给另一个,以满足您的原始需求。在C代码中,您如何告诉
    Aes
    类模式是
    CBC
    ?或者默认为
    CBC
    ?默认情况下,用于加密的分组密码模式为c#@ikerberaI think
    .GetBytes()
    中的CBC。在这种情况下,C#IV是字节[32:48],而Python IV是字节[0:16](这也是密钥的前半部分!)。另外,我不确定
    KDF.PBKDF2
    中的defult哈希算法是什么,但我认为它与
    Rfc2898DeriveBytes
    (SHA1)相同。KDF.PBKDF2和Rfc2898DeriveBytes@t.m.adam的哈希算法都是相同的。用C编写一个完整的实现,对未加密的文本进行往返。然后用python编写另一个完整的实现,实现同样的功能。尝试将它们分解成小块的功能,在这两个方面做相同的事情。这样一来,a)比较阶段的输出并找出它们不一致的地方会容易得多,b)然后引入一个点,一个点将数据交给另一个点,以满足您的原始需求。您如何使此url安全?如何使此url安全?