python - AES265 Python 到 C# 转换失败

标签 python c# cryptography

我正在尝试转换几行 Python编码到C#代码。我正面临一个错误,我不知道哪一行导致了该错误。我不知道 Python根本。我想我在切片子数组或解密过程中犯了错误,然后我用不同的方式重写,例如Buffer.BlockCopy但没有运气。
Python source

#Example grabbing JPEG instead of MP4
mediaurl = "url"
mediakey="UdoT3mfVvt3kMp0+MAybMlgVrnEyVAdxSamXQ+qbRog="
salt = "WhatsApp Image Keys"

mediaKeyExpanded = HKDF(base64.b64decode(mediakey),112,salt)
iv = mediaKeyExpanded[:16]
cipherKey = mediaKeyExpanded[16:48]
macKey = mediaKeyExpanded[48:80]

mediaData = urllib2.urlopen(mediaurl).read()
file = mediaData[:-10]
mac = mediaData[-10:]


decryptor = AES.new(cipherKey, AES.MODE_CBC, iv)
imgdata=AESUnpad(decryptor.decrypt(file))

with open('rob.jpg', 'wb') as f:
    f.write(imgdata)

print("file written to rob.jpg")
C# 代码
Hkdf
var hkdf = new Hkdf(System.Security.Cryptography.HashAlgorithmName.SHA256);

var mediakey = Convert.FromBase64String("UdoT3mfVvt3kMp0+MAybMlgVrnEyVAdxSamXQ+qbRog=");
var salt = Encoding.UTF8.GetBytes("WhatsApp Image Keys");

var mediaKeyExpanded = hkdf.Expand(mediakey, 112, salt); //HKDF(base64.b64decode(mediakey), 112, salt)
var length = mediaKeyExpanded.Length;

var iv = mediaKeyExpanded.Skip(0).Take(16).ToArray(); //mediaKeyExpanded[:16]
var cipherKey = mediaKeyExpanded.Skip(16).Take(32).ToArray(); //mediaKeyExpanded[16:48]
var macKey = mediaKeyExpanded.Skip(48).Take(32).ToArray(); //mediaKeyExpanded[48:80]

var mediaData = File.ReadAllBytes("file.enc");
    length = mediaData.Length;
var fileLength = length - 10;
var file = mediaData.Take(fileLength).ToArray(); //mediaData[:-10]
var mac = mediaData.Skip(fileLength).Take(10).ToArray();//mediaData[-10:]

//decryptor = AES.new(cipherKey, AES.MODE_CBC, iv)
//imgdata = AESUnpad(decryptor.decrypt(file))

using (var rijndaelManaged = new RijndaelManaged { 
    Key = cipherKey, IV = iv, Mode = CipherMode.CBC, KeySize = 256, BlockSize = 128
})
{
    rijndaelManaged.Padding = PaddingMode.Zeros;
    using (var memoryStream = new MemoryStream(file))
    using (var cryptoStream = new CryptoStream(memoryStream, rijndaelManaged.CreateDecryptor(cipherKey, iv), CryptoStreamMode.Read))
    using (var fsOut = new FileStream(@"C:\Users\Name\Desktop\file_decrypted.jpg", FileMode.Create))
    {
        int data;
        while ((data = cryptoStream.ReadByte()) != -1)
            fsOut.WriteByte((byte)data);
    }
}
This is the file I'm trying to decrypt.
编辑:
图像文件已成功创建,但由于格式错误或不受支持,任何图像查看器都无法打开。

最佳答案

正如 Artjom B. 已经指出的那样,在确定 MAC 时 C# 代码中存在一个错误,同时已在发布的代码中修复。
但是,将 key 大小显式设置为 256 位或将块大小设置为 128 位没有任何区别,因为这些值由 RijndaelManaged 使用。默认情况下。这对应于 AES,因此它也可以应用于例如AesManaged .
除了MAC确定的bug,C#代码还有两个bug:

  • 对应 HKDF() 来自 C# 代码的 Python 代码是:
    var mediaKeyExtracted = hkdf.Extract(mediakey, null);        
    var mediaKeyExpanded = hkdf.Expand(mediaKeyExtracted, 112, salt); 
    
    这将返回 mediaKeyExpanded 的值对应于 Python 代码中确定的那个,即(十六进制编码):
    a02b98bd6ce9575c95cc938e39bb782ba5d6478c98c0e356ea7ee70b4900f3861db9528cd4490ca02789410b3c3aba4489ebcce2c153a015f213a331d147ba515450edd55f8ff03d8fce4760825351f16b2a23d371e30846c0492e259cabb263d63bc6e098280002cb125fc807a03a2b
    
    这给出了以下值
      iv:        a02b98bd6ce9575c95cc938e39bb782b
      cipherKey: a5d6478c98c0e356ea7ee70b4900f3861db9528cd4490ca02789410b3c3aba44
      macKey:    89ebcce2c153a015f213a331d147ba515450edd55f8ff03d8fce4760825351f1
    
    请注意,名为 salt 的变量实际上不是盐而是信息参数(参见 RFC 5869 ,第 2 节)。
  • 来自 Python 代码,即函数 AESUnpad() AESPad() 可以确定Python代码使用了PKCS7填充。因此,必须在 C# 代码中应用 PKCS7 填充而不是零填充,否则不会删除加密中的 PKCS7 填充:
    rijndaelManaged.Padding = PaddingMode.PKCS7;
    
    请注意,PKCS7 实际上不需要明确指定,因为它是默认值。但是,您必须删除明确指定零填充的行。

  • 通过这些更改 linked file可以使用 mediaKey 解密 UdoT3mfVvt3kMp0+MAybMlgVrnEyVAdxSamXQ+qbRog=和 appInfo WhatsApp Image Keys使用 C# 代码(另见 here)。解密后的文件与使用 Python 代码解密的文件内容相同。

    顺便说一句:随着变量file , iv , macKeymac从 C# 代码中,可以根据说明(参见 here )验证文件,如下所示:
    HMACSHA256 hmac = new HMACSHA256(macKey);
    
    byte[] ivFile = new byte[iv.Length + file.Length];
    Array.Copy(iv, 0, ivFile, 0, iv.Length);
    Array.Copy(file, 0, ivFile, iv.Length, file.Length);
    
    byte[] macCalc = hmac.ComputeHash(ivFile);
    
    byte[] macCalc10 = new byte[10];
    Array.Copy(macCalc, 0, macCalc10, 0, 10);
    
    bool verified =  macCalc10.SequenceEqual(mac);
    
    由于要验证的文件和生成 key ( cipherKeymacKey )和 IV 的数据是从同一个地方下载的(作为 rar 文件,请参见 here ),这是一个相当低的保护.

    关于python - AES265 Python 到 C# 转换失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63750078/

    相关文章:

    javascript - 从 PHP 调用 Python 脚本

    python - 从 CET/CEST 到 UTC 的时间序列转换

    c#如何改变托盘图标

    c# - 继承字典的序列化类不是序列化属性

    python - OSX 10.6.3 上的 Python2.6 未找到 Evt.TickCount()

    python - 尝试连接两个不同维度的数组

    c# - 这段代码会无限循环吗?

    c - 使用 EC_KEY 时 EVP_PKEY_verify 不起作用

    c - MbedTLS 和 .NET BouncyCaSTLe 与 Curve25519 的互操作性问题

    安卓 - javax.crypto.AEADBadTagException