C# RFC2898DeriveBytes is working but Python PBKDF2 generated key and IV are not working with Python AES Decryption

≯℡__Kan透↙ 提交于 2020-01-14 03:13:51

问题


I have a problem in hand to decrypt the AES encrypted cipher-text which specifications are following The cipher-text consists of: · 256 bytes of RFC2898-derived salt, followed by a message that was AES-encrypted using password, 'password' and derived IV. Sample Message is "This is my secret string, lorem ipsum" and password is "password" which is encrypted using C# code This message is decrypting fine with following c# code

private static readonly int SALT_SIZE = 256;
public static void Decrytor(){
// Encrypted Message
           var cipherText = "i+EKwmlAF0VYh4GwDd+bGf3+yreYsPJW2Oq/w9FXjsp7RI3VqRiqtnqiAD4n6U0JJSTe2ct4B7lgrG+dHxeGcXYEYIERXvU0xnUdH+z3mRwmgYOqCU9HRUKy/z3GKISTm8qH030KTYm3YMBjnKpU8gaRcoDPP/nCiB3o5fPdyspgJgT/qt5BuvwYq7n0qg6ez/Wi4447gq/qHwG3wuuYLSBUCfmIkgGaO1KXqv3SsR8EAhrmMBmPDJfjc3sydNqs5B8J9/JvZFEZULTb8rLQZKQvgHhH9/53Bzs3zmoq0RFbgSueUbyeWb9rLAzYieTz8Yj0srG4GtwPrTPoItc6/hvx5stZ6pX8tgyk9Y3baT0JFMtGgxve7yduy8idTCQdAwRc5NOo4+CBk7P/sIw6+Q==";
            var key = "password";
            // Extract the salt from our cipherText
            var allTheBytes = Convert.FromBase64String(cipherText);
            var saltBytes = allTheBytes.Take(SALT_SIZE).ToArray();
            var cipherTextBytes = allTheBytes.Skip(SALT_SIZE).Take(allTheBytes.Length - SALT_SIZE).ToArray();

            var keyDerivationFunction = new Rfc2898DeriveBytes(key, saltBytes);
            // Derive the previous IV from the Key and Salt
            var keyBytes = keyDerivationFunction.GetBytes(32);
            var ivBytes = keyDerivationFunction.GetBytes(16);

            // Create a decrytor to perform the stream transform.
            // Create the streams used for decryption.
            // The default Cipher Mode is CBC and the Padding is PKCS7 which are both good
            var aesManaged = new AesManaged();
            var decryptor = aesManaged.CreateDecryptor(keyBytes, ivBytes);
            var memoryStream = new MemoryStream(cipherTextBytes);
            var cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read);
            var streamReader = new StreamReader(cryptoStream);

            // Return the decrypted bytes from the decrypting stream.
            Console.WriteLine("\n{0}\n", streamReader.ReadToEnd());
        }

Output is: "This is my secret string, lorem ipsum"

but when I try to decrypt the message by following Python2.7 equivalent implementation, it is not decrypting the first few characters correctly

import base64
from Crypto.Cipher import AES
from Crypto.Protocol import KDF

def p_decrypt( self, text ):
    text_dec = base64.b64decode(text)
    salt = text_dec[:256]
    enc_txt = text_dec[256:]
    key_bytes = KDF.PBKDF2(self.key, salt, dkLen=32)
    iv = KDF.PBKDF2(self.key, salt)
    cipher = AES.new(key_bytes, AES.MODE_CBC, iv)
    return cipher.decrypt(enc_txt)

Output is: "�增��"j�����"t string, lorem ipsum"

Expected output: "This is my secret string, lorem ipsum"

I tried to find the problem, when I used the keyBytes and IV generated by the C# RFC2898DeriveBytes method that also works fine python code but python code is not decrypting the whole message correctly using the PBKDF2 generated keyBytes and IV.

Both C# RFC2898DeriveBytes and python PBKDF2 are generating keyBytes using HMACSHA1 hashing algo but C# RFC2898DeriveBytes method is generated different keyBytes and IV whereas Python PBKDF2 is returning first 16 bytes of generated keyBytes for IV call.

Kindly give me some helpful guidelines on this.

Thanks, M Umer


回答1:


Rfc2898DeriveBytes is a streaming-response object, so concatenating two successive calls is the same as doing one call with both lengths added together.

var pbkdf2WithTwoCalls = new Rfc2898DeriveBytes(...)
var pbkdf2WithOneCall = new Rfc2898DeriveBytes(sameParametersAsAbove);

byte[] twoCallA = pbkdf2WithTwoCalls.GetBytes(32);
byte[] twoCallB = pbkdf2WithTwoCalls.GetBytes(16);

byte[] oneCall = pbkdf2WithOneCall.GetBytes(32 + 16);

if (!oneCall.SequenceEquals(twoCallA.Concat(twoCallB))
    throw new TheUniverseMakesNoSenseException();

So your solution in Python would be to make one 48-byte call to PBKDF2, then split it into the 32-byte AES key and the 16-byte IV.

Your decryption response indicates that the key is correct, but the IV is not.



来源:https://stackoverflow.com/questions/46821018/c-sharp-rfc2898derivebytes-is-working-but-python-pbkdf2-generated-key-and-iv-are

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!