c# - 在 C# 和 NodeJS 中生成 PBKDF2 key

标签 c# node.js cryptography

我正在尝试使用 AES192 和基于 PBKDF2 密码/盐的 key 在 C# 中加密字节数组,并在 NodeJS 中解密相同的数据。然而,我的 key 生成在 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)。它还使用采用 String 作为密码的 Rfc2898DeriveBytes 构造函数。不幸的是,documentation没有说明使用什么编码将字符串转换为字节。幸运的是,Rfc2898DeriveBytes 确实有 another constructor它采用字节数组作为密码,还采用迭代计数参数,此处为 1000。

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

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

关于c# - 在 C# 和 NodeJS 中生成 PBKDF2 key ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19453920/

相关文章:

c# - 对对象使用 C# 动态方法

c# - ASP.NET Core禁用json补丁

c# - c#中字符串之间的比较

node.js - 使用管道中数组中的对象值执行 $lookup

node.js - Docker 主机名未在 next.js prod 中解析但在开发模式下工作(错误 : getaddrinfo ENOTFOUND)

cryptography - 彩虹攻击到底是什么?

java - 将 SecureRandom 与 SHA-256 结合使用

c# - 字符串每 3 个单词拆分一次

javascript - Mysql-nodejs 嵌套查询

java - Java中的DH key 协议(protocol): why generated keys are moSTLy equal for both parties?