java - AES 解密 NodeJs 中的文件
问题描述
我有一个 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);
});
}
解决方案
我在 Java 和 Node.js 中创建了一些用于加密和解密文件的示例。只要使用相同的密钥和 IV 值,代码就会兼容,也就是说,Node 代码将解密 Java 的输出,反之亦然。
现在我在这里使用文本文件作为输入,但您可以使用任何文件类型作为输入。
我已更新为在 ECB 模式下使用 128 位 AES。
密钥不能是“1234”,因为它必须是 128 位长,所以我使用了下面给出的密钥(16 字节/128 位)。
爪哇
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();
}
}
节点.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");
推荐阅读
- vb.net - 在键入 vb.net windows 应用程序时,如何在文本框中将值格式化为印度货币?
- python - Django:像 LoginView 这样的通用表单在哪里呈现函数字典填充以及如何更改它
- javascript - 为什么 html 画布动画会为每个新矩形渲染一个临时间隙?
- batch-file - 批处理文件中的“nul”是什么?
- javascript - setTimeout 无法访问变量
- sql - 排序字母+字符+数字?
- mysql - MariaDB 使用 PHP PDO 存储与原始字段不同的值的 varbinary 字段
- mysql - MySQL 查询在子查询中使用 JOINS 太慢
- python - 如何从列表中删除标点符号
- vue.js - Nuxt js如何在商店中调度动作并改变状态