【问题标题】:problem implementing c# decryption client in python在python中实现c#解密客户端的问题
【发布时间】:2019-06-25 01:37:38
【问题描述】:

我有一个解密 AES 加密消息的 c# 客户端。我尝试在我的python客户端实现c#逻辑,结果不一样,满是问号和模糊字符。

我正在使用 python 3.5 和运行 mint x64 的 pycrypto。 下面提供的 c# 客户端和我的 python 版本的代码:

c#代码:

string EncryptionKey = "MAKV2SPBNI99212"; 
byte[] cipherBytes = Convert.FromBase64String(cipherText); //Get the encrypted message's bytes
using (Aes encryptor = Aes.Create()) //Create a new AES object
                {
                    //Decrypt the text
                    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.CreateDecryptor(), CryptoStreamMode.Write))
                        {
                            cs.Write(cipherBytes, 0, cipherBytes.Length);
                            cs.Close();
                        }
                        plainText = Encoding.Unicode.GetString(ms.ToArray());
                    }

我的python版本:

def decode_base64(data, altchars=b'+/'):
    """Decode base64, padding being optional.

    :param data: Base64 data as an ASCII byte string
    :returns: The decoded byte string.

    """
    data = re.sub(rb'[^a-zA-Z0-9%s]+' % altchars, b'', data)  # normalize
    missing_padding = len(data) % 4
    if missing_padding:
        data += b'='* (4 - missing_padding)
    return base64.b64decode(data, altchars)

def decode_message(data, key):
    enc_txt = decode_base64(bytes(data, 'utf-16'))
    salt_t = ["0x49", "0x76", "0x61", "0x6e", "0x20", "0x4d", "0x65", "0x64", "0x76", "0x65", "0x64", "0x65", "0x76"]
    salt = bytes([int(x, 0) for x in salt_t])
    key_bytes = KDF.PBKDF2(key, salt, 32, 1000)
    # iv = enc_txt[:16] // using this line instead of the below line, has no effects on final result
    iv = KDF.PBKDF2(key, salt, 16, 1000)
    cipher = AES.new(key_bytes, AES.MODE_CBC, iv)
    return cipher.decrypt(enc_txt).decode('utf-16')

c# 客户端按预期工作,但我的 python 客户端导致字符模糊,而不是实际的预期消息。

我遇到了这个post 我想我有类似的问题,但我无法理解提供的答案。 任何答案将不胜感激。提前致谢。

更新:C# 服务器端加密: 这也是 C# 服务器端加密代码,我认为这个问题涵盖了基于链接问题的场景的多个方面,并且可以作为任何面临相同问题的人的参考(编码、加密、填充......)

string EncryptionKey = "MAKV2SPBNI99212"; //Declare the encryption key (it's not the best thing to do)
byte[] clearBytes = Encoding.Unicode.GetBytes(clearText); //Get the bytes of the message
using (Aes encryptor = Aes.Create()) //Create a new aes object
            {
                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); //Set the encryption key
                encryptor.IV = pdb.GetBytes(16); //Set the encryption IV

                using (MemoryStream ms = new MemoryStream()) //Create a new memory stream
                {
                    using (CryptoStream cs = new CryptoStream(ms, encryptor.CreateEncryptor(), CryptoStreamMode.Write)) //Create a new crypto stream
                    {
                        cs.Write(clearBytes, 0, clearBytes.Length); //Write the command to the crypto stream
                        cs.Close(); //Close the crypto stream
                    }
                    cipherText = System.Convert.ToBase64String(ms.ToArray()); //Convert the encrypted bytes to a Base64 string

【问题讨论】:

  • 你试过utf-8吗?
  • 你好!是的,但它不起作用。我遇到的编码类似于post
  • 如果您发布 C# 加密部分以了解密文是什么样子(关于 BOM),将会很有帮助。只能更改 Python 代码还是 C# 代码?

标签: c# python aes


【解决方案1】:
  • Python代码中IV被错误判断,代码修改如下:

    keyiv = KDF.PBKDF2(key, salt, 48, 1000)
    key = keyiv[:32]
    iv = keyiv[32:48]
    
  • 另外,C#代码中使用了PKCS7填充,所以在解密时Python代码中需要取消填充。一种可能是Crypto.Util.Padding

    import Crypto.Util.Padding as padding
    
    ...
    
    decryptedPadded = cipher.decrypt(enc_txt)
    decrypted = padding.unpad(decryptedPadded, 16)  # Pkcs7 unpadding
    return decrypted.decode('utf-16')               # UTF-16LE decoding including BOM-removal
    

    在 C# 代码中,UTF-16LE (Encoding.Unicode) 编码的数据被加密。数据前面有一个 2 字节的 BOM (0xFFFE)。在 UTF-16LE 解码过程中会自动删除此 BOM。

  • Python 代码中的decode_base64 方法似乎是从here 采用的。此方法应重建丢失的 Base64 填充。我不太确定为什么这里有必要这样做。此外,调用该方法时密文的 UTF-16 编码对我来说似乎毫无意义。其实对密文进行简单的Base64解码就足够了:

    import base64
    ...
    enc_txt = base64.b64decode(data)
    

    但也许我错过了这里的某些方面。

【讨论】:

  • 我感谢您的友好且绝对有用的解决方案,它解决了我的问题。提前致谢。关于你提到的 decode_base64,我完全同意你的看法。我的情况是一个特殊的情况,我不会解密整个收到的 base64 消息,而只是解密其中的一部分,因此很容易出现填充错误。
【解决方案2】:

@Topaco 感谢您的解释和回答。

在此处粘贴完整代码,供面临相同问题的人参考。

import base64
import Crypto.Util.Padding as padding
from Crypto.Cipher import AES
from Crypto.Protocol import KDF
from pbkdf2 import PBKDF2

def decrypt(data, key):
        enc_txt = base64.b64decode(data)
        salt_t = ["0x49", "0x76", "0x61", "0x6e", "0x20", "0x4d", "0x65", "0x64", "0x76", "0x65", "0x64", "0x65", "0x76"]
        salt = bytes([int(x, 0) for x in salt_t])
        key_bytes = KDF.PBKDF2(key, salt, 32, 1000)
        iv = KDF.PBKDF2(key, salt, 48, 1000)[32:48]
        cipher = AES.new(key_bytes, AES.MODE_CBC, iv)
        decryptedPadded = cipher.decrypt(enc_txt)
        decrypted = padding.unpad(decryptedPadded, 16)  # Pkcs7 unpadding
        return decrypted.decode('utf-16')        # UTF-16LE decoding including BOM-removal

【讨论】:

    猜你喜欢
    • 2014-07-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-02
    • 2019-01-17
    • 2017-11-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多