【问题标题】:Convert C# to Python using AES/CBC/NoPadding使用 AES/CBC/NoPadding 将 C# 转换为 Python
【发布时间】:2015-01-06 14:49:34
【问题描述】:

我正在尝试将此 C# 代码转换为 Python (2.7)。问题是解密的结果与python代码有误。 IV 和密钥正确。

我发现了很多关于 Python 和 C# 的主题,但我没有找到答案。

C# 加密:

class Tracer
{
    private static readonly int BlockBitSize = 128;
    private static readonly int KeyBitSize = 256;

    internal static byte[] In(byte[] plainBytes, byte[] uid)
    {
        using (var sha = new SHA512Managed())
        {
            var hash = sha.ComputeHash(uid);
            return In(plainBytes, hash.Skip(32).Take(32).ToArray(), hash.Take(16).ToArray());
        }
    }

    internal static byte[] In(byte[] plainBytes, byte[] key, byte[] iv)
    {
        if (key == null || key.Length != KeyBitSize / 8)
            throw new ArgumentException(String.Format("Key needs to be {0} bit!", KeyBitSize), "key");
        if (iv == null || iv.Length != BlockBitSize / 8)
            throw new ArgumentException(String.Format("IV needs to be {0} bit!", BlockBitSize), "iv");

        using (AesManaged aes = new AesManaged())
        {
            aes.KeySize = KeyBitSize;
            aes.BlockSize = BlockBitSize;
            aes.Mode = CipherMode.CBC;
            aes.Padding = PaddingMode.None;

            using (ICryptoTransform encrypter = aes.CreateEncryptor(key, iv))
                using (MemoryStream cipherStream = new MemoryStream())
                {
                    using (CryptoStream cryptoStream = new CryptoStream(cipherStream, encrypter, CryptoStreamMode.Write))
                    {
                        cryptoStream.Write(plainBytes, 0, plainBytes.Length);
                        cryptoStream.FlushFinalBlock();
                    }
                    return cipherStream.ToArray();
                }
        }
    }

    internal static byte[] Out(byte[] cipherBytes, byte[] uid)
    {
        using (var sha = new SHA512Managed())
        {
            var hash = sha.ComputeHash(uid);
            return Out(cipherBytes, hash.Skip(32).Take(32).ToArray(), hash.Take(16).ToArray());
        }
    }

    internal static byte[] Out(byte[] cipherBytes, byte[] key, byte[] iv)
    {
        if (key == null || key.Length != KeyBitSize / 8)
            throw new ArgumentException(String.Format("Key needs to be {0} bit!", KeyBitSize), "key");
        if (iv == null || iv.Length != BlockBitSize / 8)
            throw new ArgumentException(String.Format("IV needs to be {0} bit!", BlockBitSize), "iv");

        using (AesManaged aes = new AesManaged())
        {
            aes.KeySize = KeyBitSize;
            aes.BlockSize = BlockBitSize;
            aes.Mode = CipherMode.CBC;
            aes.Padding = PaddingMode.None;

            using (ICryptoTransform decrypter = aes.CreateDecryptor(key, iv))
                using (MemoryStream plainStream = new MemoryStream())
                {
                    using (var decrypterStream = new CryptoStream(plainStream, decrypter, CryptoStreamMode.Write))
                        using (var binaryWriter = new BinaryWriter(decrypterStream))
                        {
                            //Decrypt Cipher Text from Message
                            binaryWriter.Write(cipherBytes, 0, cipherBytes.Length);
                        }
                    //Return Plain Text
                    return plainStream.ToArray();
                }
        }
    }
}

Python解密

def AESdecrypt(ciphertext, UID):

    from Crypto.Cipher import AES

    digest = hashlib.sha512(UID).hexdigest()

    iv = BitArray(hex=digest[:32])

    key = BitArray(hex=digest[64:128])

    block40Str = BitArray(hex=ciphertext[1].encode('hex'))

    cipherSpec = AES.new(key.bytes, AES.MODE_CBC, iv.bytes)
    plaintextWithPadding = cipherSpec.decrypt(block40Str.bytes)

注意:对不起我的英语

感谢您的帮助!

编辑:Python 中的 AES 解密返回 64 个字符,这是错误的。原始明文是32。

EDIT2:Python 代码已更新。解密函数现在返回 32 个字符,但仍然出错

【问题讨论】:

  • 我不知道 python 但hexdigest 看起来它返回数据的字符串表示,而不是 C# 使用的二进制值,因此 python 可能使用十六进制的(字符)字节字符串而不是实际的字节。
  • python版本也将ciphertext[1]转成hex,如果ciphertext是字符串,可能只有一个字节。
  • 感谢您的回答。 @AlexK。我试图给出未转换为字符串的实际字节,但解密 aes 函数表示长度不等于 16 的倍数。
  • @JanneKarila。我选择了密文的字符串表示,因为 aes 函数需要一个字符串。也许我不明白,我在这方面的知识不多,你有例子来解决它吗?谢谢
  • 二进制数据的常用表示在 Python 3 中为 bytes,在 Python 2 中为 str

标签: c# python encryption aes


【解决方案1】:

用于生成密钥的摘要和 iv 是用正确的数据生成的,但在字符串中。相反,C# 使用数据的 ByteArray 生成摘要。感谢BitArray Python library,我解决了我的问题:

新的 Python 代码:

def AESdecrypt(ciphertext, UID):

    from Crypto.Cipher import AES

    UIDBytes = BitArray(hex=UID)
    digest = hashlib.sha512(UIDBytes.bytes).hexdigest()

    iv = BitArray(hex=digest[:32])

    key = BitArray(hex=digest[64:128])

    cipherSpec = AES.new(key.bytes, AES.MODE_CBC, iv.bytes)
    plaintextWithoutPadding = cipherSpec.decrypt(ciphertext[1])

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-12-05
    • 2015-11-11
    • 2021-03-05
    • 2014-08-15
    • 2021-09-13
    • 2020-04-30
    • 2021-03-21
    • 1970-01-01
    相关资源
    最近更新 更多