在C#和NodeJ中生成PBKDF2密钥

在C#和NodeJ中生成PBKDF2密钥,c#,node.js,cryptography,C#,Node.js,Cryptography,我试图使用AES192和基于PBKDF2密码/salt的密钥对C#中的字节数组进行加密,并对NodeJS中的相同数据进行解密。但是,我的密钥生成在NodeJS和C#中产生不同的结果 C#代码如下: private void getKeyAndIVFromPasswordAndSalt(string password, byte[] salt, SymmetricAlgorithm symmetricAlgorithm, ref byte[] key, ref byte[] iv)

我试图使用AES192和基于PBKDF2密码/salt的密钥对C#中的字节数组进行加密,并对NodeJS中的相同数据进行解密。但是,我的密钥生成在NodeJS和C#中产生不同的结果

C#代码如下:

    private void getKeyAndIVFromPasswordAndSalt(string password, byte[] salt, SymmetricAlgorithm symmetricAlgorithm, ref byte[] key, ref byte[] iv)
    {
        Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(password, salt);
        key = rfc2898DeriveBytes.GetBytes(symmetricAlgorithm.KeySize / 8);
        iv = rfc2898DeriveBytes.GetBytes(symmetricAlgorithm.BlockSize / 8);
    }

    private byte[] encrypt(byte[] unencryptedBytes, string password, int keySize)
    {
        RijndaelManaged aesEncryption = new RijndaelManaged();
        aesEncryption.KeySize = keySize;
        aesEncryption.BlockSize = 128;
        byte[] key = new byte[keySize];
        byte[] iv = new byte[128];
        getKeyAndIVFromPasswordAndSalt(password, Encoding.ASCII.GetBytes("$391Ge3%£2gfR"), aesEncryption, ref key, ref iv);
        aesEncryption.Key = key;
        aesEncryption.IV = iv;
        Console.WriteLine("iv: {0}", Convert.ToBase64String(aesEncryption.IV));
        Console.WriteLine("key: {0}", Convert.ToBase64String(aesEncryption.Key));
        ICryptoTransform crypto = aesEncryption.CreateEncryptor();
        // The result of the encryption and decryption            
        return crypto.TransformFinalBlock(unencryptedBytes, 0, unencryptedBytes.Length);
    }
NodeJS代码如下所示:

    crypto.pbkdf2("Test", "$391Ge3%£2gfR", 1000, 192/8, (err, key) => {
        var binkey = new Buffer(key, 'ascii');
        var biniv = new Buffer("R6taODpFa1/A7WhTZVszvA==", 'base64');
        var decipher = crypto.createDecipheriv('aes192', binkey, biniv);
        console.log("KEY: " + binkey.toString("base64"));
        var decodedLIL = decipher.update(decryptedBuffer);
        console.log(decodedLIL);
        return;
    });
IV是硬编码的,因为我不知道如何使用pbkdf2计算它。我已经查阅了nodeJS文档以获得更多帮助,但我不知道这里发生了什么


任何帮助都将不胜感激。

我看到的问题之一是英镑符号的编码(
crypto.pbkdf2
默认情况下将密码和salt编码为二进制数组,其中每个字符被截断为最低8位(意味着磅符号变成字节0xA3)

但是,您的C#代码将salt转换为ASCII,其中每个字符被截断为最低的7位(意味着磅符号变成字节0x23)。它还使用Rfc2898DeriveBytes构造函数,该构造函数接受一个字符串作为密码。不幸的是,没有说明使用什么编码将字符串转换为字节。幸运的是,Rfc2898DeriveBytes确实有一个以字节数组作为密码的函数,并且还有一个迭代计数参数,这里是1000

因此,您应该将密码和salt字符串转换为字节数组,方法是将每个字符截断为8位,就像Node.js在默认情况下所做的那样。以下是一个例子:

var bytes=new byte[password.Length];
for(var i=0;i<bytes.Length;i++){
  bytes[i]=(byte)(password[i]&0xFF);
}
var bytes=新字节[password.Length];

对于(var i=0;iThat排序,谢谢。我没有意识到它们都默认使用不同的字符编码。我可以得到一个示例,说明如何通过将每个字符截断为8位来将密码字符串和salt字符串转换为字节数组吗?我真的无法自己计算出来。非常感谢提供一个示例。提前谢谢。请注意这不是IVs的使用方式——您应该为每个加密调用生成一个随机的IV,并将其与密文一起发送。