我有一个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);
});
}
答案 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);
这解决了第一个错误
第二,我使用的是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);
});
}