【问题标题】:Unable to decrypt a pdf file Using 'aes-256-cbc' algorithm in node js无法在节点 js 中使用“aes-256-cbc”算法解密 pdf 文件
【发布时间】:2020-10-05 13:18:59
【问题描述】:

我正在尝试使用节点 js 解密 PDF 文件,第三方使用 C# 加密的 PDF 文件。

我很难过,因为我不断收到此错误:

 D:\IMP\DevOps Implementation\New folder (2)> node index1.js
internal/crypto/cipher.js:172
  const ret = this[kHandle].final();
                            ^
Error: error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt
    at Decipheriv.final (internal/crypto/cipher.js:172:29)
    at Object.AESCrypt.decrypt (D:\IMP\DevOps Implementation\New folder (2)\index1.js:12:18)
    at D:\IMP\DevOps Implementation\New folder (2)\index1.js:57:24
    at FSReqCallback.readFileAfterClose [as oncomplete] (internal/fs/read_file_context.js:63:3) {
  library: 'digital envelope routines',
  function: 'EVP_DecryptFinal_ex',
  reason: 'bad decrypt',
  code: 'ERR_OSSL_EVP_BAD_DECRYPT'
}

我们正在使用以下代码进行加密(C#)

  private void FileEncrypt(string inputFile, string outputfile, string password)

        {

            byte[] salt = GenerateSalt();

            byte[] passwords = Encoding.UTF8.GetBytes(password);

            RijndaelManaged AES = new RijndaelManaged();

            AES.KeySize = 256;

            AES.BlockSize = 128;

            

            var key = new Rfc2898DeriveBytes(passwords, salt, 50000);

            AES.Key = key.GetBytes(AES.KeySize / 8);

            AES.IV = key.GetBytes(AES.BlockSize / 8);

            AES.Mode = CipherMode.CBC;

            AES.Padding = PaddingMode.Zeros;

            using (FileStream fsCrypt = new FileStream(inputFile + ".aes", FileMode.Create))

            {

                fsCrypt.Write(salt, 0, salt.Length);

                using (CryptoStream cs = new CryptoStream(fsCrypt, AES.CreateEncryptor(), CryptoStreamMode.Write))

                {

                    using (FileStream fsIn = new FileStream(inputFile, FileMode.Open))

                    {

                        byte[] buffer = new byte[1048576];

                        int read;

                        while ((read = fsIn.Read(buffer, 0, buffer.Length)) > 0)

                        {

                            cs.Write(buffer, 0, read);

                        }

                    }

                }

            }

        }

我们正在使用以下代码进行解密(Node js)

AESCrypt.encrypt = function(cryptkey, iv, cleardata) {
    var encipher = crypto.createCipheriv('aes-256-cbc', cryptkey, iv);
    return Buffer.concat([
        encipher.update(cleardata),
        encipher.final()
    ]);
}

function decrypted(){
var enc;
fs.readFile('./resource/test.pdf', function (err,data) {
    if (err) {
        return console.log(err);
    }
    
    var bufferenc = new Buffer.from(data); 

    var dec = AESCrypt.decrypt(cryptkey,iv, bufferenc);    
        console.log(dec);
   // var buffer = new Buffer.from(dec);                                          
    fs.writeFileSync('./resource/decrypted.pdf',dec); 
    
});
}

无法在节点 js 中使用 'aes-256-cbc' 算法解密 pdf 文件

【问题讨论】:

  • 您使用的是完全不同的库(两者都是半生不熟的)。相反,请使用信誉良好、经过良好审核的库,例如 libsodium(libsodium 具有 node 和 c# 的绑定)。你的 KDF 方法就足以搞砸了。
  • @Woodstock:KDF 看起来是 PBKDF2。
  • 我在您的 C# 代码中看到的两个错误。 1) 零填充,以及 2) 未能将最终块写入文件。如果 PDF 文件不能以零字节结尾,则 #1 不是错误。
  • @President James K. Polk:我可以根据您的建议(使用 pkcs7 填充)解密 pdf 文件,但解密后的 pdf 已损坏,我的代码有什么问题??

标签: node.js encryption cryptography aes node-crypto


【解决方案1】:

您可以尝试使用此代码来解密 pdf 数据,它适用于我的 C# 代码:

const fs = require('fs');
const crypto = require("crypto");

function FileDecrypt(inputFile, outputfile, password)
{
    // Read the entire file into the buffer.
    let buffer = fs.readFileSync(inputFile);

    // Read the first eight bytes as a salt.
    let salt = buffer.slice(0,8);
    let cipherText = buffer.slice(8);

    // use key derivation function to get key and iv.
    let derivedBytes = crypto.pbkdf2Sync(password, salt, 50000, 48, "sha1");
    let key = derivedBytes.slice(0, 32);
    let iv = derivedBytes.slice(32);

    let cipher = crypto.createDecipheriv('aes-256-cbc', key, iv);
    // Switch off auto padding in this context
    cipher.setAutoPadding(false);

    let decryptedData = Buffer.concat([cipher.update(cipherText), cipher.final()]);
    fs.writeFileSync(outputfile, decryptedData);    
}

FileDecrypt("encrypted.pdf", "node-decrypted.pdf", "password");

【讨论】:

  • 我正在使用您的代码,但面临以下问题:错误:错误:0606506D:数字信封例程:EVP_DecryptFinal_ex:最终块长度错误。我正在使用自定义密码和 IV 进行加密(c#),我想使用相同的自定义密码和 IV(节点 js)解密 pdf
  • 不完全是(据我所知)。我们可以打开或关闭自动填充,然后我们可以实现自己的填充类型。
  • 关于问题错误:错误:0606506D:数字信封例程:EVP_DecryptFinal_ex:错误的最终块长度
  • 这可能是键之间的一些差异。我们必须确保我们使用完全相同的密钥和 iv 进行加密和解密。
猜你喜欢
  • 2022-09-27
  • 2020-01-14
  • 2013-08-11
  • 2017-09-18
  • 2022-12-12
  • 2015-08-22
  • 2017-09-28
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多