rsa-aes-crypto 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/bin/index.js +142 -0
  2. package/package.json +11 -0
package/bin/index.js ADDED
@@ -0,0 +1,142 @@
1
+ #!/usr/bin/env node
2
+
3
+ const crypto = require('crypto');
4
+ const fs = require('fs');
5
+ const path = require('path');
6
+
7
+ const publicKeyPath = path.join(__dirname, 'public.pem');
8
+ const privateKeyPath = path.join(__dirname, 'private.pem');
9
+
10
+ /** 生成 RSA 公钥/私钥 */
11
+ function generateKeys() {
12
+ const { publicKey, privateKey } = crypto.generateKeyPairSync('rsa', {
13
+ modulusLength: 2048,
14
+ publicKeyEncoding: { type: 'pkcs1', format: 'pem' },
15
+ privateKeyEncoding: { type: 'pkcs1', format: 'pem' },
16
+ });
17
+ fs.writeFileSync(publicKeyPath, publicKey);
18
+ fs.writeFileSync(privateKeyPath, privateKey);
19
+ console.log('✅ RSA 公钥和私钥生成完成');
20
+ }
21
+
22
+ /** 加密文件(混合加密) */
23
+ function encryptFile(inputFile, outputFile) {
24
+ const publicKey = fs.readFileSync(publicKeyPath, 'utf8');
25
+
26
+ // 随机生成 AES key 和 IV
27
+ const aesKey = crypto.randomBytes(32); // AES-256
28
+ const iv = crypto.randomBytes(16);
29
+
30
+ // 用 AES 流加密文件
31
+ const cipher = crypto.createCipheriv('aes-256-cbc', aesKey, iv);
32
+ const input = fs.createReadStream(inputFile);
33
+ const output = fs.createWriteStream(outputFile);
34
+
35
+ // 用 RSA 加密 AES key + IV
36
+ const keyIvBuffer = Buffer.concat([aesKey, iv]); // 32 + 16 = 48 bytes
37
+ const encryptedKeyIv = crypto.publicEncrypt(publicKey, keyIvBuffer);
38
+
39
+ // 写入 RSA 加密的 key 长度 + 加密 key + AES 数据
40
+ const keyLengthBuffer = Buffer.alloc(4);
41
+ keyLengthBuffer.writeUInt32BE(encryptedKeyIv.length, 0);
42
+ output.write(keyLengthBuffer);
43
+ output.write(encryptedKeyIv);
44
+
45
+ input.pipe(cipher).pipe(output);
46
+
47
+ output.on('finish', () => console.log(`✅ 文件加密完成:${outputFile}`));
48
+ }
49
+
50
+ /** 解密文件(混合加密) */
51
+ function decryptFile(inputFile, outputFile) {
52
+ const privateKey = fs.readFileSync(privateKeyPath, 'utf8');
53
+ const input = fs.createReadStream(inputFile);
54
+
55
+ let headerRead = false;
56
+ let encryptedKeyIvLength = 0;
57
+ let encryptedKeyIv = Buffer.alloc(0);
58
+ let remainingBuffers = [];
59
+
60
+ input.on('readable', () => {
61
+ let chunk;
62
+ while ((chunk = input.read()) !== null) {
63
+ if (!headerRead) {
64
+ remainingBuffers.push(chunk);
65
+ const bufferConcat = Buffer.concat(remainingBuffers);
66
+ if (bufferConcat.length >= 4) {
67
+ encryptedKeyIvLength = bufferConcat.readUInt32BE(0);
68
+ if (bufferConcat.length >= 4 + encryptedKeyIvLength) {
69
+ encryptedKeyIv = bufferConcat.slice(
70
+ 4,
71
+ 4 + encryptedKeyIvLength,
72
+ );
73
+ const aesDataStart = 4 + encryptedKeyIvLength;
74
+ const aesData = bufferConcat.slice(aesDataStart);
75
+
76
+ // 解密 AES key + IV
77
+ const keyIvBuffer = crypto.privateDecrypt(
78
+ privateKey,
79
+ encryptedKeyIv,
80
+ );
81
+ const aesKey = keyIvBuffer.slice(0, 32);
82
+ const iv = keyIvBuffer.slice(32, 48);
83
+
84
+ // AES 解密流
85
+ const decipher = crypto.createDecipheriv(
86
+ 'aes-256-cbc',
87
+ aesKey,
88
+ iv,
89
+ );
90
+ const output = fs.createWriteStream(outputFile);
91
+
92
+ // 把已经读到的 AES 数据先解密
93
+ const readable = crypto.Readable.from(aesData);
94
+ readable.pipe(decipher).pipe(output);
95
+
96
+ // 之后剩余的 input 数据直接解密
97
+ input.pipe(decipher);
98
+
99
+ output.on('finish', () =>
100
+ console.log(`✅ 文件解密完成:${outputFile}`),
101
+ );
102
+
103
+ headerRead = true;
104
+ remainingBuffers = null;
105
+ break;
106
+ }
107
+ }
108
+ }
109
+ }
110
+ });
111
+ }
112
+
113
+ // CLI
114
+ const args = process.argv.slice(2);
115
+ if (args[0] === 'genkey') {
116
+ generateKeys();
117
+ } else if (args[0] === 'encrypt') {
118
+ const [_, inputFile, outputFile] = args;
119
+ if (!inputFile || !outputFile) {
120
+ console.log(
121
+ '用法: node rsa_aes_file_crypto.js encrypt <输入文件> <输出文件>',
122
+ );
123
+ } else {
124
+ encryptFile(inputFile, outputFile);
125
+ }
126
+ } else if (args[0] === 'decrypt') {
127
+ const [_, inputFile, outputFile] = args;
128
+ if (!inputFile || !outputFile) {
129
+ console.log(
130
+ '用法: node rsa_aes_file_crypto.js decrypt <输入文件> <输出文件>',
131
+ );
132
+ } else {
133
+ decryptFile(inputFile, outputFile);
134
+ }
135
+ } else {
136
+ console.log(`
137
+ 用法:
138
+ node rsa_aes_file_crypto.js genkey 生成公钥/私钥
139
+ node rsa_aes_file_crypto.js encrypt <in> <out> 加密文件
140
+ node rsa_aes_file_crypto.js decrypt <in> <out> 解密文件
141
+ `);
142
+ }
package/package.json ADDED
@@ -0,0 +1,11 @@
1
+ {
2
+ "name": "rsa-aes-crypto",
3
+ "version": "1.0.1",
4
+ "description": "全局命令行工具,基于 RSA + AES 的文件加解密",
5
+ "bin": {
6
+ "rsa-aes-crypto": "bin/rsa-aes-crypto.js"
7
+ },
8
+ "author": "zifenggao",
9
+ "license": "MIT",
10
+ "dependencies": {}
11
+ }