AES解密NodeJ中的文件

时间:2020-03-31 07:38:34

标签: java node.js encryption

我有一个JAVA代码,可以对Windows操作系统上的excel文件进​​行AES加密。我想使用NodeJS在MacOs操作系统上解密相同的文件。我已经在NodeJs中编写了一个解密函数,这给了我以下错误

error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt

这是JAVA代码

import java.security.Key;
import java.io.OutputStream;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;

public class fileEncrypter {
   try {
     final SecretKeySpec key = new SecretKeySpec("1234".getBytes(), "AES");
     final Cipher instance = Cipher.getInstance("AES/ECB/PKCS5Padding");
     final BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(name));
     final BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(name2));
     instance.init(1, key);
     final byte[] b = new byte[4096];
     for (int i = bufferedInputStream.read(b); i > -1; i = bufferedInputStream.read(b)) {
        final byte[] update = instance.update(b, 0, I);
        bufferedOutputStream.write(update, 0, update.length);
     }
     bufferedInputStream.close();
     final byte[] doFinal = instance.doFinal();
     bufferedOutputStream.write(doFinal, 0, doFinal.length);
     bufferedOutputStream.flush();
     bufferedOutputStream.close();
     return "success";
   } catch(Exception obj) {
     System.err.println("Exception occured while encryption:" + obj);
     obj.printStackTrace();
     return obj.toString();
   }
}

这是要解密的NodeJs代码

function Decrypt_AES() {

const ALGORITHM = 'aes-128-ecb';
const ENCRYPTION_KEY = "1234";

var decipher = crypto.createDecipher(ALGORITHM, ENCRYPTION_KEY);
decipher.setAutoPadding(true);
var input = fs.createReadStream('test.enc');
var output = fs.createWriteStream('test_copy.xls');

input.pipe(decipher).pipe(output);

output.on('finish', function () {
    console.log('Encrypted file written to disk!');
});
output.on('error', function (e) {
    console.log(e);
});

}

2 个答案:

答案 0 :(得分:2)

我已经在Java和Node.js中创建了一些示例,这些示例将加密和解密文件。只要使用相同的键和IV值,代码就可以兼容,也就是说,Node代码将解密Java的输出,反之亦然。

现在我在这里使用文本文件作为输入,但是您可以使用任何文件类型作为输入。

我已更新为在ECB模式下使用128位AES。

密钥不能为“ 1234”,因为它必须为128位长,因​​此我使用了下面给出的密钥(16字节/ 128位)。

Java

import java.io.*;
import javax.crypto.*;
import java.security.*;
import javax.crypto.spec.*;

public class fileEncrypter {

  private static final String key = "0123456789ABDCEF";

  public static void main(String[] args)
  {
      encryptFile(key, "java-input.txt", "java-output.txt");
      decryptFile(key, "java-output.txt", "java-decrypted.txt");
  }

  public static void encryptFile(String secret, String inputFile, String outputFile) 
  {
      try 
      {
          Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING");
          cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(secret.getBytes(), "AES"));

          byte[] inputData = readFile(inputFile);
          byte[] outputData = cipher.doFinal(inputData);
          writeToFile(outputFile, outputData);  
      } 
      catch (Exception e) 
      {
          System.out.println("Error while encrypting: " + e.toString());
      }
  }

  public static void decryptFile(String secret, String inputFile, String outputFile) 
    {
        try 
        {
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5PADDING");
            cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(secret.getBytes(), "AES"));

            byte[] inputData = readFile(inputFile);
            byte[] outputData = cipher.doFinal(inputData);
            writeToFile(outputFile, outputData);  
        } 
        catch (Exception e) 
        {
            System.out.println("Error while decrypting: " + e.toString());
        }
    }

    private static byte[] readFile(String fileName) throws IOException {
        byte[] data = new byte[(int) new File(fileName).length()];
        DataInputStream dis = new DataInputStream(new FileInputStream(fileName));
        dis.readFully(data);
        dis.close();
        return data;
    }

    private static void writeToFile(String fileName, byte[] data) throws IOException {
        final BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(fileName));
        bufferedOutputStream.write(data, 0, data.length);
        bufferedOutputStream.close();
    }
}

Node.js

const crypto = require("crypto");
const Algorithm = "aes-128-ecb";
const fs = require("fs");

function encryptFile(key, inputFile, outputFile) {
    const inputData = fs.readFileSync(inputFile);
    const cipher = crypto.createCipheriv(Algorithm, key, Buffer.alloc(0));
    const output = Buffer.concat([cipher.update(inputData) , cipher.final()]);
    fs.writeFileSync(outputFile, output);
}

function decryptFile(key, inputFile, outputFile) {
    const inputData = fs.readFileSync(inputFile);
    const cipher = crypto.createDecipheriv(Algorithm, key, Buffer.alloc(0));
    const output = Buffer.concat([cipher.update(inputData) , cipher.final()]);
    fs.writeFileSync(outputFile, output);
}

const KEY = Buffer.from("0123456789ABDCEF", "utf8");

encryptFile(KEY, "node-input.txt", "node-output.txt");
decryptFile(KEY, "node-output.txt", "node-decrypted.txt");

答案 1 :(得分:2)

我已经在Terry Lennox的帮助下解决了这个问题。首先非常感谢他。

第一个错误:

error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt

这是一个填充问题,默认情况下,nodeJs使用PKCS填充,因此我不得不使用decipher.setAutoPadding(false);

将自动填充设置为false

这解决了第一个错误

第二,我使用的是crypto.createDecipher(ALGORITHM, ENCRYPTION_KEY),它在使用之前先处理密钥。为了解决这个问题,我将功能更改为 crypto.createDecipheriv(ALGORITHM, ENCRYPTION_KEY, null)

这给了我一个错误,因为我们无法通过null代替IV值。

由于ECB不需要任何IV,并且我们不能通过null代替IV,所以我必须将IV值设置为此Buffer.alloc(0)

这是对我有用的代码

function Decrypt_AES() {

    const ALGORITHM = 'aes-128-ecb';
    const key = "1234";
    const ENCRYPTION_KEY = key;

    var IV = Buffer.alloc(0);
    var decipher = crypto.createDecipheriv(ALGORITHM, ENCRYPTION_KEY, IV);
    decipher.setAutoPadding(false);
    var input = fs.createReadStream('test.enc');
    var output = fs.createWriteStream('test_copy.xls');

    input.pipe(decipher).pipe(output);

    output.on('finish', function () {
        console.log('Decrypted file written to disk!');
    });
    output.on('error', function (e) {
        console.log(e);
     });

}