├── .gitignore ├── README.md ├── crypt.js ├── errors.js ├── file_encrypt.js ├── file_encrypt_test.js ├── package-lock.json └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | # ignore packages 2 | 3 | *.zip 4 | *.rar 5 | *.tar.gz 6 | *.tar 7 | *.7z 8 | 9 | # ignore files 10 | 11 | *.log 12 | *.log.* 13 | *.crypt 14 | 15 | # ignore dirs 16 | 17 | node_modules/* 18 | .idea 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # node-file-encrypt 2 | 3 | A file encrypt & decrypt package based on TEA 4 | 5 | # get & use 6 | 7 | 1. get it 8 | 9 | ```bash 10 | git clone git@github.com:fiefdx/node-file-encrypt.git 11 | 12 | or 13 | 14 | npm install node-file-encrypt 15 | 16 | ``` 17 | 2. use it 18 | 19 | ```javascript 20 | import fs from 'fs'; 21 | 22 | import { FileEncrypt } from 'node-file-encrypt'; 23 | 24 | let filePath = '/home/breeze/Develop/fast2array.tar'; // source file path 25 | let encryptPath = ''; 26 | 27 | { // encrypt file 28 | // to FileEncrypt can be passed 4 Arguments 29 | // filePath - the path of the file that should be encrypted 30 | // outPath - this is optional - the Path for the encrypted file 31 | // fileEnding - this is optional - a custom fileEnding like '.myFile', default is '.crypt' 32 | // cryptFileName - this is optional - boolean if the filename should be hashed, default is true 33 | let f = new FileEncrypt(filePath); 34 | f.openSourceFile(); 35 | f.encrypt('111111'); 36 | encryptPath = f.encryptFilePath; 37 | console.log("encrypt sync done"); 38 | } 39 | 40 | { // decrypt file 41 | fs.unlink(filePath, function() {}); 42 | let f = new FileEncrypt(encryptPath); 43 | f.openSourceFile(); 44 | f.decrypt('111111'); 45 | console.log("decrypt sync done"); 46 | } 47 | 48 | { // get original file name from encrypted file 49 | let f = new FileEncrypt(encryptPath); 50 | f.openSourceFile(); 51 | console.log(f.info('111111')); 52 | } 53 | 54 | { // encrypt & decrypt file async 55 | let f = new FileEncrypt(filePath); 56 | f.openSourceFile(); 57 | f.encryptAsync('111111').then(function() { 58 | encryptPath = f.encryptFilePath; 59 | console.log("encrypt async done"); 60 | fs.unlink(filePath, function() {}); 61 | let d = new FileEncrypt(encryptPath); 62 | d.openSourceFile(); 63 | d.decryptAsync('111111').then(function() { 64 | console.log("decrypt async done"); 65 | }); 66 | }); 67 | } 68 | ``` 69 | 70 | ```bash 71 | $ sudo npm install -g node-file-encrypt 72 | $ crypt -h 73 | Usage: crypt [OPTION]... 74 | 75 | Options: 76 | -e : encrypt input file 77 | -d : decrypt input file 78 | -p : password 79 | -i : input file path (include file name) 80 | -o : output file path (exclude file name) 81 | -h : get this help 82 | ``` 83 | -------------------------------------------------------------------------------- /crypt.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | import util from 'util'; 4 | 5 | import logUpdate from 'log-update'; 6 | import duration from 'duration'; 7 | import minimist from 'minimist'; 8 | import { FileEncrypt as fileEncrypt } from './file_encrypt.js'; 9 | 10 | const argv = minimist(process.argv.slice(2)); 11 | 12 | let defaults = { 13 | p: '', // password 14 | i: '', // input file path 15 | o: '', // output file path 16 | e: false, // encrypt 17 | d: false, // decrypt 18 | l: false // list original file name 19 | }; 20 | let options = {}; 21 | const frames = ['-', '\\', '|', '/']; 22 | let frameN = 0; 23 | 24 | 25 | function help() { 26 | console.log(util.format( 27 | `Usage: crypt [OPTION]... 28 | 29 | Options: 30 | -e : encrypt input file 31 | -d : decrypt input file 32 | -l : list original file name 33 | -p : password 34 | -i : input file path (include file name) 35 | -o : output file path (exclude file name), if not specified, then it is input file's base path (exclude file name) 36 | -h : get this help 37 | `)); 38 | } 39 | 40 | async function main() { 41 | 42 | // parse options 43 | for (let k in defaults) { 44 | options[k] = argv[k] || defaults[k]; 45 | } 46 | options.p = '' + options.p; 47 | 48 | try { 49 | if (options.h) { 50 | help(); 51 | } else if (options.l && options.p != '' && options.i != '') { // list original file name 52 | let f = new fileEncrypt(options.i, options.o); 53 | f.openSourceFile(); 54 | let name = f.info(options.p).name || '' 55 | console.log(name); 56 | } else if (options.e && options.p != '' && options.i != '') { // encrypt file 57 | let f = new fileEncrypt(options.i, options.o); 58 | f.openSourceFile(); 59 | await f.encryptAsync(options.p, function(percent, startAt) { 60 | const frame = frames[frameN = ++frameN % frames.length]; 61 | const useTime = duration(startAt, new Date()).toString(1); 62 | const message = `${frame} encrypt: ${percent}% - ${useTime}`; 63 | logUpdate(message); 64 | }, function(err) { 65 | if (err) console.log("err: " + err); 66 | else console.log(f.encryptFilePath); 67 | }); 68 | } else if (options.d && options.p != '' && options.i != '') { // decrypt file 69 | let f = new fileEncrypt(options.i, options.o); 70 | f.openSourceFile(); 71 | await f.decryptAsync(options.p, function(percent, startAt){ 72 | const frame = frames[frameN = ++frameN % frames.length]; 73 | const useTime = duration(startAt, new Date()).toString(1); 74 | const message = `${frame} decrypt: ${percent}% - ${useTime}`; 75 | logUpdate(message); 76 | }, function(err) { 77 | if (err) console.log("err: " + err); 78 | console.log(f.decryptFilePath); 79 | }); 80 | } else { 81 | help(); 82 | } 83 | } catch (e) { 84 | console.log(e.message); 85 | } 86 | 87 | process.exit(0); 88 | } 89 | 90 | main(); 91 | -------------------------------------------------------------------------------- /errors.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | -------------------------------------------------------------------------------- /file_encrypt.js: -------------------------------------------------------------------------------- 1 | /* - - - - - - - - - - - - - - - - file encrypt by fiefdx- - - - - - - - - - - - - - - - - */ 2 | 3 | "use strict"; 4 | 5 | import path from 'path'; 6 | import fs from 'fs'; 7 | import util from 'util'; 8 | 9 | import tea from 'node-tea'; 10 | import sha1 from 'sha1'; 11 | 12 | let encrypt_block_size = 1024 * 8; 13 | 14 | const fsRead = util.promisify(fs.read); 15 | const fsOpen = util.promisify(fs.open); 16 | const fsWrite = util.promisify(fs.write); 17 | const fsWriteFile = util.promisify(fs.writeFile); 18 | const fsClose = util.promisify(fs.close); 19 | 20 | 21 | function getEncryptLength(length) { 22 | let fillN = (8 - (length + 2)) % 8; 23 | if (fillN < 0) { 24 | fillN += 8; 25 | } 26 | fillN += 2; 27 | return 1 + length + fillN + 7; 28 | } 29 | 30 | function intToBytes(i) { 31 | let b = new Array(4); 32 | b[3] = i & 0x000000ff; 33 | b[2] = (i >>> 8) & 0x000000ff; 34 | b[1] = (i >>> 16) & 0x000000ff; 35 | b[0] = (i >>> 24) & 0x000000ff; 36 | return b; 37 | } 38 | 39 | function bytesToInt(b) { 40 | let i; 41 | i = (((b[0] & 0x000000ff) << 24)| 42 | ((b[1] & 0x000000ff) << 16)| 43 | ((b[2] & 0x000000ff) << 8)| 44 | (b[3] & 0x000000ff)); 45 | return i; 46 | } 47 | 48 | function longToBytes(i) { 49 | let b = new Array(8); 50 | b[7] = i & 0x00000000000000ff; 51 | b[6] = (i >>> 8) & 0x00000000000000ff; 52 | b[5] = (i >>> 16) & 0x00000000000000ff; 53 | b[4] = (i >>> 24) & 0x00000000000000ff; 54 | b[3] = (i >>> 32) & 0x00000000000000ff; 55 | b[2] = (i >>> 40) & 0x00000000000000ff; 56 | b[1] = (i >>> 48) & 0x00000000000000ff; 57 | b[0] = (i >>> 56) & 0x00000000000000ff; 58 | return b; 59 | } 60 | 61 | function bytesToLong(b) { 62 | let i; 63 | i = (((b[0] & 0x00000000000000ff) << 56)| 64 | ((b[1] & 0x00000000000000ff) << 48)| 65 | ((b[2] & 0x00000000000000ff) << 40)| 66 | ((b[3] & 0x00000000000000ff) << 32)| 67 | ((b[4] & 0x00000000000000ff) << 24)| 68 | ((b[5] & 0x00000000000000ff) << 16)| 69 | ((b[6] & 0x00000000000000ff) << 8)| 70 | (b[7] & 0x00000000000000ff)); 71 | return i; 72 | } 73 | 74 | export function FileEncrypt(inPath, outPath, fileType, cryptFileName = true) { 75 | this.inPath = inPath; 76 | this.outPath = outPath || path.dirname(this.inPath); // if not specified outPath, then outPath will be inPath's base path 77 | this.fileName = path.basename(inPath); 78 | this.fileSize = 0; 79 | this.fileHeader = 'crypt'; 80 | this.fileType = fileType || '.crypt'; 81 | this.cryptFileName = cryptFileName; 82 | this.fileNamePos = 0; 83 | this.fileNameLen = 0; 84 | this.filePos = 0; 85 | this.fileLen = 0; 86 | this.encryptFileName = ''; 87 | this.encryptFilePath = ''; 88 | this.decryptFilePath = ''; 89 | this.fp = null; 90 | this.progressCallInterval = 100; // 100 milliseconds 91 | } 92 | 93 | FileEncrypt.prototype.openSourceFile = function() { 94 | if (fs.existsSync(this.inPath) && fs.lstatSync(this.inPath).isFile()) { 95 | const stats = fs.statSync(this.inPath); 96 | this.fileSize = stats.size; 97 | this.fp = fs.openSync(this.inPath, 'r'); 98 | } else { 99 | throw new Error(util.format("File [%s] doesn't exists!", this.inPath)); 100 | } 101 | } 102 | 103 | FileEncrypt.prototype.encrypt = function(key, progressCallback) { // progressCallback(percent, startAt) 104 | let startAt = new Date(); 105 | let lastCallAt = new Date(); 106 | 107 | if (this.cryptFileName) { 108 | let fileNameHash = sha1(this.fileName); 109 | let timestamp = util.format("%d", Date.now()); 110 | this.encryptFileName = sha1(util.format("%s%s%s", fileNameHash, this.fileSize, timestamp)) + this.fileType; 111 | this.encryptFilePath = path.join(this.outPath, this.encryptFileName); 112 | } else { 113 | let fileName = this.fileName.replace(/\.[^.]*$/, '') + this.fileType; 114 | this.encryptFilePath = path.join(this.outPath, fileName); 115 | } 116 | let cryptFp = null; 117 | if (!fs.existsSync(this.encryptFilePath)) { 118 | cryptFp = fs.openSync(this.encryptFilePath, 'w'); 119 | } else { 120 | throw new Error(util.format("Encrypt file [%s] exists already!", this.encryptFilePath)); 121 | } 122 | if (this.fp && cryptFp) { 123 | if (key != '') { 124 | if (progressCallback && typeof progressCallback === 'function') { 125 | progressCallback(0, startAt); 126 | } 127 | let headerFileName = tea.strToBytes(tea.encrypt(this.fileName, key)); 128 | this.fileNamePos = 25; 129 | this.fileNameLen = headerFileName.length; 130 | this.filePos = this.fileNamePos + this.fileNameLen; 131 | fs.writeFileSync(cryptFp, new Buffer.from(tea.strToBytes(this.fileHeader)), {encoding: 'binary', flag: 'a'}); 132 | fs.writeFileSync(cryptFp, new Buffer.from(intToBytes(this.fileNamePos)), {encoding: 'binary', flag: 'a'}); 133 | fs.writeFileSync(cryptFp, new Buffer.from(intToBytes(this.fileNameLen)), {encoding: 'binary', flag: 'a'}); 134 | fs.writeFileSync(cryptFp, new Buffer.from(intToBytes(this.filePos)), {encoding: 'binary', flag: 'a'}); 135 | fs.writeFileSync(cryptFp, new Buffer.from(longToBytes(this.fileLen)), {encoding: 'binary', flag: 'a'}); 136 | fs.writeFileSync(cryptFp, new Buffer.from(headerFileName), {encoding: 'binary', flag: 'a'}); 137 | let currentPos = 0; 138 | while (true) { 139 | let buf = new Buffer.alloc(encrypt_block_size); 140 | let size = fs.readSync(this.fp, buf, 0, encrypt_block_size, currentPos); 141 | if (size == 0) { 142 | fs.closeSync(this.fp); 143 | break; 144 | } 145 | let cryptBuf = new Buffer.from(tea.encryptBytes(Array.from(buf.slice(0, size)), key)); 146 | this.fileLen += cryptBuf.length; 147 | fs.writeFileSync(cryptFp, cryptBuf, {encoding: 'binary', flag: 'a'}); 148 | currentPos += encrypt_block_size; 149 | let now = Date.now(); 150 | if (progressCallback && typeof progressCallback === 'function' && currentPos < this.fileSize && now - lastCallAt.getTime() >= this.progressCallInterval) { 151 | let percent = Math.floor(currentPos * 100 / this.fileSize); 152 | if (percent > 100) { 153 | percent = 100; 154 | } 155 | progressCallback(percent, startAt); 156 | lastCallAt = new Date(); 157 | } 158 | } 159 | fs.writeSync(cryptFp, new Buffer.from(longToBytes(this.fileLen)), 0, 8, 17); 160 | if (progressCallback && typeof progressCallback === 'function') { 161 | progressCallback(100, startAt); 162 | } 163 | } else { 164 | throw new Error("Password is empty!"); 165 | } 166 | 167 | fs.closeSync(cryptFp); 168 | } 169 | } 170 | 171 | FileEncrypt.prototype.decrypt = function(key, progressCallback) { // progressCallback(percent, startAt) 172 | let startAt = new Date(); 173 | let lastCallAt = new Date(); 174 | let cryptFp = null; 175 | if (this.fp) { 176 | let fileHeader = new Buffer.alloc(this.fileHeader.length); 177 | fs.readSync(this.fp, fileHeader, 0, 5); 178 | if (tea.bytesToStr(Array.from(fileHeader)) == this.fileHeader) { 179 | if (key != '') { 180 | if (progressCallback && typeof progressCallback === 'function') { 181 | progressCallback(0, startAt); 182 | } 183 | let fileNamePosBuf = new Buffer.alloc(4); 184 | let fileNameLenBuf = new Buffer.alloc(4); 185 | let filePosBuf = new Buffer.alloc(4); 186 | let fileLenBuf = new Buffer.alloc(8); 187 | fs.readSync(this.fp, fileNamePosBuf, 0, 4); 188 | fs.readSync(this.fp, fileNameLenBuf, 0, 4); 189 | fs.readSync(this.fp, filePosBuf, 0, 4); 190 | fs.readSync(this.fp, fileLenBuf, 0, 8); 191 | this.fileNamePos = bytesToInt(Array.from(fileNamePosBuf)); 192 | this.fileNameLen = bytesToInt(Array.from(fileNameLenBuf)); 193 | this.filePos = bytesToInt(Array.from(filePosBuf)); 194 | this.fileLen = bytesToLong(Array.from(fileLenBuf)); 195 | let fileNameBuf = new Buffer.alloc(this.fileNameLen); 196 | fs.readSync(this.fp, fileNameBuf, 0, this.fileNameLen, this.fileNamePos); 197 | let fileName = tea.bytesToStr(tea.decryptBytes(Array.from(fileNameBuf), key)); 198 | this.decryptFilePath = path.join(this.outPath, fileName); 199 | if (!fs.existsSync(this.decryptFilePath)) { 200 | cryptFp = fs.openSync(this.decryptFilePath, 'w'); 201 | } else { 202 | throw new Error(util.format("Decrypt file [%s] exists already!", this.decryptFilePath)); 203 | } 204 | let cryptLength = getEncryptLength(encrypt_block_size); 205 | let currentPos = this.filePos; 206 | while (true) { 207 | let size = 0; 208 | let buf = new Buffer.alloc(cryptLength); 209 | if (this.fileLen < cryptLength) { 210 | size = fs.readSync(this.fp, buf, 0, this.fileLen, currentPos); 211 | } else { 212 | size = fs.readSync(this.fp, buf, 0, cryptLength, currentPos); 213 | } 214 | if (size == 0) { 215 | fs.closeSync(this.fp); 216 | break; 217 | } 218 | this.fileLen -= size; 219 | let decryptBytes = tea.decryptBytes(Array.from(buf.slice(0, size)), key); 220 | fs.writeFileSync(cryptFp, new Buffer.from(decryptBytes), {encoding: 'binary', flag: 'a'}); 221 | currentPos += size; 222 | let now = Date.now(); 223 | if (progressCallback && typeof progressCallback === 'function' && currentPos < this.fileSize && now - lastCallAt.getTime() >= this.progressCallInterval) { 224 | let percent = Math.floor(currentPos * 100 / this.fileSize); 225 | if (percent > 100) { 226 | percent = 100; 227 | } 228 | progressCallback(percent, startAt); 229 | lastCallAt = new Date(); 230 | } 231 | } 232 | fs.closeSync(cryptFp); 233 | if (progressCallback && typeof progressCallback === 'function') { 234 | progressCallback(100, startAt); 235 | } 236 | } else { 237 | throw new Error("Password is empty!"); 238 | } 239 | } else { 240 | throw new Error(util.format("This file [%s] is not a encrypt file!", this.inPath)); 241 | } 242 | } 243 | } 244 | 245 | FileEncrypt.prototype.encryptAsync = async function(key, progressCallback, callback) { 246 | let err = null; 247 | let startAt = new Date(); 248 | let lastCallAt = new Date(); 249 | 250 | if (this.cryptFileName) { 251 | let fileNameHash = sha1(this.fileName); 252 | let timestamp = util.format("%d", Date.now()); 253 | this.encryptFileName = sha1(util.format("%s%s%s", fileNameHash, this.fileSize, timestamp)) + this.fileType; 254 | this.encryptFilePath = path.join(this.outPath, this.encryptFileName); 255 | } else { 256 | let fileName = this.fileName.replace(/\.[^.]*$/, '') + this.fileType; 257 | this.encryptFilePath = path.join(this.outPath, fileName); 258 | } 259 | let cryptFp = null; 260 | if (!fs.existsSync(this.encryptFilePath)) { 261 | cryptFp = await fsOpen(this.encryptFilePath, 'w'); 262 | if (this.fp && cryptFp) { 263 | if (key != '') { 264 | if (progressCallback && typeof progressCallback === 'function') { 265 | progressCallback(0, startAt); 266 | } 267 | let headerFileName = tea.strToBytes(tea.encrypt(this.fileName, key)); 268 | this.fileNamePos = 25; 269 | this.fileNameLen = headerFileName.length; 270 | this.filePos = this.fileNamePos + this.fileNameLen; 271 | await fsWriteFile(cryptFp, new Buffer.from(tea.strToBytes(this.fileHeader)), {encoding: 'binary', flag: 'a'}); 272 | await fsWriteFile(cryptFp, new Buffer.from(intToBytes(this.fileNamePos)), {encoding: 'binary', flag: 'a'}); 273 | await fsWriteFile(cryptFp, new Buffer.from(intToBytes(this.fileNameLen)), {encoding: 'binary', flag: 'a'}); 274 | await fsWriteFile(cryptFp, new Buffer.from(intToBytes(this.filePos)), {encoding: 'binary', flag: 'a'}); 275 | await fsWriteFile(cryptFp, new Buffer.from(longToBytes(this.fileLen)), {encoding: 'binary', flag: 'a'}); 276 | await fsWriteFile(cryptFp, new Buffer.from(headerFileName), {encoding: 'binary', flag: 'a'}); 277 | let currentPos = 0; 278 | while (true) { 279 | let buf = new Buffer.alloc(encrypt_block_size); 280 | let r = await fsRead(this.fp, buf, 0, encrypt_block_size, currentPos); 281 | let size = r.bytesRead; 282 | if (size == 0) { 283 | await fsClose(this.fp); 284 | break; 285 | } 286 | let cryptBuf = new Buffer.from(tea.encryptBytes(Array.from(buf.slice(0, size)), key)); 287 | this.fileLen += cryptBuf.length; 288 | await fsWriteFile(cryptFp, cryptBuf, {encoding: 'binary', flag: 'a'}); 289 | currentPos += encrypt_block_size; 290 | let now = Date.now(); 291 | if (progressCallback && typeof progressCallback === 'function' && currentPos < this.fileSize && now - lastCallAt.getTime() >= this.progressCallInterval) { 292 | let percent = Math.floor(currentPos * 100 / this.fileSize); 293 | if (percent > 100) { 294 | percent = 100; 295 | } 296 | progressCallback(percent, startAt); 297 | lastCallAt = new Date(); 298 | } 299 | } 300 | await fsWrite(cryptFp, new Buffer.from(longToBytes(this.fileLen)), 0, 8, 17); 301 | if (progressCallback && typeof progressCallback === 'function') { 302 | progressCallback(100, startAt); 303 | } 304 | } else { 305 | err = new Error("Password is empty!"); 306 | } 307 | await fsClose(cryptFp); 308 | } 309 | } else { 310 | err = new Error(util.format("Encrypt file [%s] exists already!", this.encryptFilePath)); 311 | } 312 | if (callback) { 313 | callback(err); 314 | } 315 | } 316 | 317 | FileEncrypt.prototype.decryptAsync = async function(key, progressCallback, callback) { // progressCallback(percent, startAt) 318 | let err = null; 319 | let startAt = new Date(); 320 | let lastCallAt = new Date(); 321 | let cryptFp = null; 322 | if (this.fp) { 323 | let fileHeader = new Buffer.alloc(this.fileHeader.length); 324 | await fsRead(this.fp, fileHeader, 0, 5, 0); 325 | if (tea.bytesToStr(Array.from(fileHeader)) == this.fileHeader) { 326 | if (key != '') { 327 | if (progressCallback && typeof progressCallback === 'function') { 328 | progressCallback(0, startAt); 329 | } 330 | let fileNamePosBuf = new Buffer.alloc(4); 331 | let fileNameLenBuf = new Buffer.alloc(4); 332 | let filePosBuf = new Buffer.alloc(4); 333 | let fileLenBuf = new Buffer.alloc(8); 334 | await fsRead(this.fp, fileNamePosBuf, 0, 4, 5); 335 | await fsRead(this.fp, fileNameLenBuf, 0, 4, 9); 336 | await fsRead(this.fp, filePosBuf, 0, 4, 13); 337 | await fsRead(this.fp, fileLenBuf, 0, 8, 17); 338 | this.fileNamePos = bytesToInt(Array.from(fileNamePosBuf)); 339 | this.fileNameLen = bytesToInt(Array.from(fileNameLenBuf)); 340 | this.filePos = bytesToInt(Array.from(filePosBuf)); 341 | this.fileLen = bytesToLong(Array.from(fileLenBuf)); 342 | let fileNameBuf = new Buffer.alloc(this.fileNameLen); 343 | await fsRead(this.fp, fileNameBuf, 0, this.fileNameLen, this.fileNamePos); 344 | let fileName = tea.bytesToStr(tea.decryptBytes(Array.from(fileNameBuf), key)); 345 | this.decryptFilePath = path.join(this.outPath, fileName); 346 | if (!fs.existsSync(this.decryptFilePath)) { 347 | cryptFp = await fsOpen(this.decryptFilePath, 'w'); 348 | let cryptLength = getEncryptLength(encrypt_block_size); 349 | let currentPos = this.filePos; 350 | while (true) { 351 | let size = 0; 352 | let buf = new Buffer.alloc(cryptLength); 353 | if (this.fileLen < cryptLength) { 354 | let r = await fsRead(this.fp, buf, 0, this.fileLen, currentPos); 355 | size = r.bytesRead; 356 | } else { 357 | let r = await fsRead(this.fp, buf, 0, cryptLength, currentPos); 358 | size = r.bytesRead; 359 | } 360 | if (size == 0) { 361 | await fsClose(this.fp); 362 | break; 363 | } 364 | this.fileLen -= size; 365 | let decryptBytes = tea.decryptBytes(Array.from(buf.slice(0, size)), key); 366 | await fsWriteFile(cryptFp, new Buffer.from(decryptBytes), {encoding: 'binary', flag: 'a'}); 367 | currentPos += size; 368 | let now = Date.now(); 369 | if (progressCallback && typeof progressCallback === 'function' && currentPos < this.fileSize && now - lastCallAt.getTime() >= this.progressCallInterval) { 370 | let percent = Math.floor(currentPos * 100 / this.fileSize); 371 | if (percent > 100) { 372 | percent = 100; 373 | } 374 | progressCallback(percent, startAt); 375 | lastCallAt = new Date(); 376 | } 377 | } 378 | await fsClose(cryptFp); 379 | if (progressCallback && typeof progressCallback === 'function') { 380 | progressCallback(100, startAt); 381 | } 382 | } else { 383 | err = new Error(util.format("Decrypt file [%s] exists already!", this.decryptFilePath)); 384 | } 385 | 386 | } else { 387 | err = new Error("Password is empty!"); 388 | } 389 | } else { 390 | err = new Error(util.format("This file [%s] is not a encrypt file!", this.inPath)); 391 | } 392 | } 393 | if (callback) { 394 | callback(err); 395 | } 396 | } 397 | 398 | FileEncrypt.prototype.info = function(key) { 399 | let result = {name: ''}; 400 | if (this.fp) { 401 | let fileHeader = new Buffer.alloc(this.fileHeader.length); 402 | fs.readSync(this.fp, fileHeader, 0, 5); 403 | if (tea.bytesToStr(Array.from(fileHeader)) == this.fileHeader) { 404 | if (key != '') { 405 | let fileNamePosBuf = new Buffer.alloc(4); 406 | let fileNameLenBuf = new Buffer.alloc(4); 407 | let filePosBuf = new Buffer.alloc(4); 408 | let fileLenBuf = new Buffer.alloc(8); 409 | fs.readSync(this.fp, fileNamePosBuf, 0, 4); 410 | fs.readSync(this.fp, fileNameLenBuf, 0, 4); 411 | fs.readSync(this.fp, filePosBuf, 0, 4); 412 | fs.readSync(this.fp, fileLenBuf, 0, 8); 413 | this.fileNamePos = bytesToInt(Array.from(fileNamePosBuf)); 414 | this.fileNameLen = bytesToInt(Array.from(fileNameLenBuf)); 415 | this.filePos = bytesToInt(Array.from(filePosBuf)); 416 | this.fileLen = bytesToLong(Array.from(fileLenBuf)); 417 | let fileNameBuf = new Buffer.alloc(this.fileNameLen); 418 | fs.readSync(this.fp, fileNameBuf, 0, this.fileNameLen, this.fileNamePos); 419 | result.name = tea.bytesToStr(tea.decryptBytes(Array.from(fileNameBuf), key)); 420 | } else { 421 | throw new Error("Password is empty!"); 422 | } 423 | } else { 424 | throw new Error(util.format("This file [%s] is not a encrypt file!", this.inPath)); 425 | } 426 | } 427 | fs.closeSync(this.fp); 428 | return result; 429 | } 430 | -------------------------------------------------------------------------------- /file_encrypt_test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | import fs from 'fs'; 4 | 5 | import { FileEncrypt } from './file_encrypt.js'; 6 | 7 | 8 | let filePath = '/home/breeze/Develop/fast2array.tar'; 9 | let outPath = '/home/breeze/Develop/'; 10 | let encryptPath = ''; 11 | 12 | 13 | { 14 | let f = new FileEncrypt(filePath); 15 | f.openSourceFile(); 16 | f.encrypt('111111'); 17 | encryptPath = f.encryptFilePath; 18 | console.log("encrypt sync done"); 19 | } 20 | 21 | { 22 | let f = new FileEncrypt(filePath, outPath, '.myFile'); 23 | f.openSourceFile(); 24 | f.encrypt('111111'); 25 | encryptPath = f.encryptFilePath; 26 | console.log("encrypt sync with custom ending done"); 27 | } 28 | 29 | { 30 | let f = new FileEncrypt(filePath, outPath, '.myFile', false); 31 | f.openSourceFile(); 32 | f.encrypt('111111'); 33 | encryptPath = f.encryptFilePath; 34 | console.log("encrypt sync with custom ending and not encrypted fileName done"); 35 | } 36 | 37 | 38 | { 39 | fs.unlink(filePath, function() {}); 40 | let f = new FileEncrypt(encryptPath); 41 | f.openSourceFile(); 42 | f.decrypt('111111'); 43 | console.log("decrypt sync done"); 44 | } 45 | 46 | { 47 | let f = new FileEncrypt(encryptPath); 48 | f.openSourceFile(); 49 | console.log(f.info('111111')); 50 | } 51 | 52 | { 53 | let f = new FileEncrypt(filePath); 54 | f.openSourceFile(); 55 | f.encryptAsync('111111').then(function() { 56 | encryptPath = f.encryptFilePath; 57 | console.log("encrypt async done"); 58 | fs.unlink(filePath, function() {}); 59 | let d = new FileEncrypt(encryptPath); 60 | d.openSourceFile(); 61 | d.decryptAsync('111111').then(function() { 62 | console.log("decrypt async done"); 63 | }); 64 | }); 65 | } 66 | -------------------------------------------------------------------------------- /package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-file-encrypt", 3 | "version": "0.0.7", 4 | "lockfileVersion": 2, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "node-file-encrypt", 9 | "version": "0.0.7", 10 | "license": "MIT", 11 | "dependencies": { 12 | "duration": "latest", 13 | "log-update": "latest", 14 | "minimist": "latest", 15 | "node-tea": "latest", 16 | "sha1": "latest" 17 | }, 18 | "bin": { 19 | "crypt": "crypt.js" 20 | } 21 | }, 22 | "node_modules/@types/color-name": { 23 | "version": "1.1.1", 24 | "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", 25 | "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==" 26 | }, 27 | "node_modules/ansi-escapes": { 28 | "version": "4.3.1", 29 | "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz", 30 | "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==", 31 | "dependencies": { 32 | "type-fest": "^0.11.0" 33 | }, 34 | "engines": { 35 | "node": ">=8" 36 | }, 37 | "funding": { 38 | "url": "https://github.com/sponsors/sindresorhus" 39 | } 40 | }, 41 | "node_modules/ansi-regex": { 42 | "version": "5.0.1", 43 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 44 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", 45 | "engines": { 46 | "node": ">=8" 47 | } 48 | }, 49 | "node_modules/ansi-styles": { 50 | "version": "4.2.1", 51 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", 52 | "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", 53 | "dependencies": { 54 | "@types/color-name": "^1.1.1", 55 | "color-convert": "^2.0.1" 56 | }, 57 | "engines": { 58 | "node": ">=8" 59 | }, 60 | "funding": { 61 | "url": "https://github.com/chalk/ansi-styles?sponsor=1" 62 | } 63 | }, 64 | "node_modules/astral-regex": { 65 | "version": "2.0.0", 66 | "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", 67 | "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", 68 | "engines": { 69 | "node": ">=8" 70 | } 71 | }, 72 | "node_modules/charenc": { 73 | "version": "0.0.2", 74 | "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", 75 | "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=", 76 | "engines": { 77 | "node": "*" 78 | } 79 | }, 80 | "node_modules/cli-cursor": { 81 | "version": "3.1.0", 82 | "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", 83 | "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", 84 | "dependencies": { 85 | "restore-cursor": "^3.1.0" 86 | }, 87 | "engines": { 88 | "node": ">=8" 89 | } 90 | }, 91 | "node_modules/color-convert": { 92 | "version": "2.0.1", 93 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 94 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 95 | "dependencies": { 96 | "color-name": "~1.1.4" 97 | }, 98 | "engines": { 99 | "node": ">=7.0.0" 100 | } 101 | }, 102 | "node_modules/color-name": { 103 | "version": "1.1.4", 104 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 105 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" 106 | }, 107 | "node_modules/crypt": { 108 | "version": "0.0.2", 109 | "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", 110 | "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=", 111 | "engines": { 112 | "node": "*" 113 | } 114 | }, 115 | "node_modules/d": { 116 | "version": "1.0.1", 117 | "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", 118 | "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", 119 | "dependencies": { 120 | "es5-ext": "^0.10.50", 121 | "type": "^1.0.1" 122 | } 123 | }, 124 | "node_modules/duration": { 125 | "version": "0.2.2", 126 | "resolved": "https://registry.npmjs.org/duration/-/duration-0.2.2.tgz", 127 | "integrity": "sha512-06kgtea+bGreF5eKYgI/36A6pLXggY7oR4p1pq4SmdFBn1ReOL5D8RhG64VrqfTTKNucqqtBAwEj8aB88mcqrg==", 128 | "dependencies": { 129 | "d": "1", 130 | "es5-ext": "~0.10.46" 131 | } 132 | }, 133 | "node_modules/emoji-regex": { 134 | "version": "8.0.0", 135 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 136 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" 137 | }, 138 | "node_modules/es5-ext": { 139 | "version": "0.10.53", 140 | "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", 141 | "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", 142 | "dependencies": { 143 | "es6-iterator": "~2.0.3", 144 | "es6-symbol": "~3.1.3", 145 | "next-tick": "~1.0.0" 146 | } 147 | }, 148 | "node_modules/es6-iterator": { 149 | "version": "2.0.3", 150 | "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", 151 | "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", 152 | "dependencies": { 153 | "d": "1", 154 | "es5-ext": "^0.10.35", 155 | "es6-symbol": "^3.1.1" 156 | } 157 | }, 158 | "node_modules/es6-symbol": { 159 | "version": "3.1.3", 160 | "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", 161 | "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", 162 | "dependencies": { 163 | "d": "^1.0.1", 164 | "ext": "^1.1.2" 165 | } 166 | }, 167 | "node_modules/ext": { 168 | "version": "1.4.0", 169 | "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", 170 | "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", 171 | "dependencies": { 172 | "type": "^2.0.0" 173 | } 174 | }, 175 | "node_modules/ext/node_modules/type": { 176 | "version": "2.0.0", 177 | "resolved": "https://registry.npmjs.org/type/-/type-2.0.0.tgz", 178 | "integrity": "sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow==" 179 | }, 180 | "node_modules/is-fullwidth-code-point": { 181 | "version": "3.0.0", 182 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 183 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", 184 | "engines": { 185 | "node": ">=8" 186 | } 187 | }, 188 | "node_modules/log-update": { 189 | "version": "4.0.0", 190 | "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", 191 | "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", 192 | "dependencies": { 193 | "ansi-escapes": "^4.3.0", 194 | "cli-cursor": "^3.1.0", 195 | "slice-ansi": "^4.0.0", 196 | "wrap-ansi": "^6.2.0" 197 | }, 198 | "engines": { 199 | "node": ">=10" 200 | }, 201 | "funding": { 202 | "url": "https://github.com/sponsors/sindresorhus" 203 | } 204 | }, 205 | "node_modules/mimic-fn": { 206 | "version": "2.1.0", 207 | "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", 208 | "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", 209 | "engines": { 210 | "node": ">=6" 211 | } 212 | }, 213 | "node_modules/minimist": { 214 | "version": "1.2.7", 215 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", 216 | "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==", 217 | "funding": { 218 | "url": "https://github.com/sponsors/ljharb" 219 | } 220 | }, 221 | "node_modules/next-tick": { 222 | "version": "1.0.0", 223 | "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", 224 | "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" 225 | }, 226 | "node_modules/node-tea": { 227 | "version": "0.0.5", 228 | "resolved": "https://registry.npmjs.org/node-tea/-/node-tea-0.0.5.tgz", 229 | "integrity": "sha1-cUkMO+sgJ+72tI27RV9K0Lh9uV4=" 230 | }, 231 | "node_modules/onetime": { 232 | "version": "5.1.0", 233 | "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz", 234 | "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==", 235 | "dependencies": { 236 | "mimic-fn": "^2.1.0" 237 | }, 238 | "engines": { 239 | "node": ">=6" 240 | } 241 | }, 242 | "node_modules/restore-cursor": { 243 | "version": "3.1.0", 244 | "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", 245 | "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", 246 | "dependencies": { 247 | "onetime": "^5.1.0", 248 | "signal-exit": "^3.0.2" 249 | }, 250 | "engines": { 251 | "node": ">=8" 252 | } 253 | }, 254 | "node_modules/sha1": { 255 | "version": "1.1.1", 256 | "resolved": "https://registry.npmjs.org/sha1/-/sha1-1.1.1.tgz", 257 | "integrity": "sha1-rdqnqTFo85PxnrKxUJFhjicA+Eg=", 258 | "dependencies": { 259 | "charenc": ">= 0.0.1", 260 | "crypt": ">= 0.0.1" 261 | }, 262 | "engines": { 263 | "node": "*" 264 | } 265 | }, 266 | "node_modules/signal-exit": { 267 | "version": "3.0.2", 268 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", 269 | "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" 270 | }, 271 | "node_modules/slice-ansi": { 272 | "version": "4.0.0", 273 | "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", 274 | "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", 275 | "dependencies": { 276 | "ansi-styles": "^4.0.0", 277 | "astral-regex": "^2.0.0", 278 | "is-fullwidth-code-point": "^3.0.0" 279 | }, 280 | "engines": { 281 | "node": ">=10" 282 | }, 283 | "funding": { 284 | "url": "https://github.com/chalk/slice-ansi?sponsor=1" 285 | } 286 | }, 287 | "node_modules/string-width": { 288 | "version": "4.2.0", 289 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", 290 | "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", 291 | "dependencies": { 292 | "emoji-regex": "^8.0.0", 293 | "is-fullwidth-code-point": "^3.0.0", 294 | "strip-ansi": "^6.0.0" 295 | }, 296 | "engines": { 297 | "node": ">=8" 298 | } 299 | }, 300 | "node_modules/strip-ansi": { 301 | "version": "6.0.0", 302 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", 303 | "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", 304 | "dependencies": { 305 | "ansi-regex": "^5.0.0" 306 | }, 307 | "engines": { 308 | "node": ">=8" 309 | } 310 | }, 311 | "node_modules/type": { 312 | "version": "1.2.0", 313 | "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", 314 | "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" 315 | }, 316 | "node_modules/type-fest": { 317 | "version": "0.11.0", 318 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz", 319 | "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==", 320 | "engines": { 321 | "node": ">=8" 322 | }, 323 | "funding": { 324 | "url": "https://github.com/sponsors/sindresorhus" 325 | } 326 | }, 327 | "node_modules/wrap-ansi": { 328 | "version": "6.2.0", 329 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", 330 | "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", 331 | "dependencies": { 332 | "ansi-styles": "^4.0.0", 333 | "string-width": "^4.1.0", 334 | "strip-ansi": "^6.0.0" 335 | }, 336 | "engines": { 337 | "node": ">=8" 338 | } 339 | } 340 | }, 341 | "dependencies": { 342 | "@types/color-name": { 343 | "version": "1.1.1", 344 | "resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz", 345 | "integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==" 346 | }, 347 | "ansi-escapes": { 348 | "version": "4.3.1", 349 | "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.1.tgz", 350 | "integrity": "sha512-JWF7ocqNrp8u9oqpgV+wH5ftbt+cfvv+PTjOvKLT3AdYly/LmORARfEVT1iyjwN+4MqE5UmVKoAdIBqeoCHgLA==", 351 | "requires": { 352 | "type-fest": "^0.11.0" 353 | } 354 | }, 355 | "ansi-regex": { 356 | "version": "5.0.1", 357 | "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", 358 | "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" 359 | }, 360 | "ansi-styles": { 361 | "version": "4.2.1", 362 | "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz", 363 | "integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==", 364 | "requires": { 365 | "@types/color-name": "^1.1.1", 366 | "color-convert": "^2.0.1" 367 | } 368 | }, 369 | "astral-regex": { 370 | "version": "2.0.0", 371 | "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", 372 | "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==" 373 | }, 374 | "charenc": { 375 | "version": "0.0.2", 376 | "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz", 377 | "integrity": "sha1-wKHS86cJLgN3S/qD8UwPxXkKhmc=" 378 | }, 379 | "cli-cursor": { 380 | "version": "3.1.0", 381 | "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", 382 | "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", 383 | "requires": { 384 | "restore-cursor": "^3.1.0" 385 | } 386 | }, 387 | "color-convert": { 388 | "version": "2.0.1", 389 | "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", 390 | "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", 391 | "requires": { 392 | "color-name": "~1.1.4" 393 | } 394 | }, 395 | "color-name": { 396 | "version": "1.1.4", 397 | "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", 398 | "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" 399 | }, 400 | "crypt": { 401 | "version": "0.0.2", 402 | "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz", 403 | "integrity": "sha1-iNf/fsDfuG9xPch7u0LQRNPmxBs=" 404 | }, 405 | "d": { 406 | "version": "1.0.1", 407 | "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", 408 | "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", 409 | "requires": { 410 | "es5-ext": "^0.10.50", 411 | "type": "^1.0.1" 412 | } 413 | }, 414 | "duration": { 415 | "version": "0.2.2", 416 | "resolved": "https://registry.npmjs.org/duration/-/duration-0.2.2.tgz", 417 | "integrity": "sha512-06kgtea+bGreF5eKYgI/36A6pLXggY7oR4p1pq4SmdFBn1ReOL5D8RhG64VrqfTTKNucqqtBAwEj8aB88mcqrg==", 418 | "requires": { 419 | "d": "1", 420 | "es5-ext": "~0.10.46" 421 | } 422 | }, 423 | "emoji-regex": { 424 | "version": "8.0.0", 425 | "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", 426 | "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" 427 | }, 428 | "es5-ext": { 429 | "version": "0.10.53", 430 | "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.53.tgz", 431 | "integrity": "sha512-Xs2Stw6NiNHWypzRTY1MtaG/uJlwCk8kH81920ma8mvN8Xq1gsfhZvpkImLQArw8AHnv8MT2I45J3c0R8slE+Q==", 432 | "requires": { 433 | "es6-iterator": "~2.0.3", 434 | "es6-symbol": "~3.1.3", 435 | "next-tick": "~1.0.0" 436 | } 437 | }, 438 | "es6-iterator": { 439 | "version": "2.0.3", 440 | "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", 441 | "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", 442 | "requires": { 443 | "d": "1", 444 | "es5-ext": "^0.10.35", 445 | "es6-symbol": "^3.1.1" 446 | } 447 | }, 448 | "es6-symbol": { 449 | "version": "3.1.3", 450 | "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", 451 | "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", 452 | "requires": { 453 | "d": "^1.0.1", 454 | "ext": "^1.1.2" 455 | } 456 | }, 457 | "ext": { 458 | "version": "1.4.0", 459 | "resolved": "https://registry.npmjs.org/ext/-/ext-1.4.0.tgz", 460 | "integrity": "sha512-Key5NIsUxdqKg3vIsdw9dSuXpPCQ297y6wBjL30edxwPgt2E44WcWBZey/ZvUc6sERLTxKdyCu4gZFmUbk1Q7A==", 461 | "requires": { 462 | "type": "^2.0.0" 463 | }, 464 | "dependencies": { 465 | "type": { 466 | "version": "2.0.0", 467 | "resolved": "https://registry.npmjs.org/type/-/type-2.0.0.tgz", 468 | "integrity": "sha512-KBt58xCHry4Cejnc2ISQAF7QY+ORngsWfxezO68+12hKV6lQY8P/psIkcbjeHWn7MqcgciWJyCCevFMJdIXpow==" 469 | } 470 | } 471 | }, 472 | "is-fullwidth-code-point": { 473 | "version": "3.0.0", 474 | "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", 475 | "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" 476 | }, 477 | "log-update": { 478 | "version": "4.0.0", 479 | "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", 480 | "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", 481 | "requires": { 482 | "ansi-escapes": "^4.3.0", 483 | "cli-cursor": "^3.1.0", 484 | "slice-ansi": "^4.0.0", 485 | "wrap-ansi": "^6.2.0" 486 | } 487 | }, 488 | "mimic-fn": { 489 | "version": "2.1.0", 490 | "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", 491 | "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==" 492 | }, 493 | "minimist": { 494 | "version": "1.2.7", 495 | "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", 496 | "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==" 497 | }, 498 | "next-tick": { 499 | "version": "1.0.0", 500 | "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", 501 | "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" 502 | }, 503 | "node-tea": { 504 | "version": "0.0.5", 505 | "resolved": "https://registry.npmjs.org/node-tea/-/node-tea-0.0.5.tgz", 506 | "integrity": "sha1-cUkMO+sgJ+72tI27RV9K0Lh9uV4=" 507 | }, 508 | "onetime": { 509 | "version": "5.1.0", 510 | "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.0.tgz", 511 | "integrity": "sha512-5NcSkPHhwTVFIQN+TUqXoS5+dlElHXdpAWu9I0HP20YOtIi+aZ0Ct82jdlILDxjLEAWwvm+qj1m6aEtsDVmm6Q==", 512 | "requires": { 513 | "mimic-fn": "^2.1.0" 514 | } 515 | }, 516 | "restore-cursor": { 517 | "version": "3.1.0", 518 | "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", 519 | "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", 520 | "requires": { 521 | "onetime": "^5.1.0", 522 | "signal-exit": "^3.0.2" 523 | } 524 | }, 525 | "sha1": { 526 | "version": "1.1.1", 527 | "resolved": "https://registry.npmjs.org/sha1/-/sha1-1.1.1.tgz", 528 | "integrity": "sha1-rdqnqTFo85PxnrKxUJFhjicA+Eg=", 529 | "requires": { 530 | "charenc": ">= 0.0.1", 531 | "crypt": ">= 0.0.1" 532 | } 533 | }, 534 | "signal-exit": { 535 | "version": "3.0.2", 536 | "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", 537 | "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" 538 | }, 539 | "slice-ansi": { 540 | "version": "4.0.0", 541 | "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", 542 | "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", 543 | "requires": { 544 | "ansi-styles": "^4.0.0", 545 | "astral-regex": "^2.0.0", 546 | "is-fullwidth-code-point": "^3.0.0" 547 | } 548 | }, 549 | "string-width": { 550 | "version": "4.2.0", 551 | "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", 552 | "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", 553 | "requires": { 554 | "emoji-regex": "^8.0.0", 555 | "is-fullwidth-code-point": "^3.0.0", 556 | "strip-ansi": "^6.0.0" 557 | } 558 | }, 559 | "strip-ansi": { 560 | "version": "6.0.0", 561 | "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", 562 | "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", 563 | "requires": { 564 | "ansi-regex": "^5.0.0" 565 | } 566 | }, 567 | "type": { 568 | "version": "1.2.0", 569 | "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", 570 | "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" 571 | }, 572 | "type-fest": { 573 | "version": "0.11.0", 574 | "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.11.0.tgz", 575 | "integrity": "sha512-OdjXJxnCN1AvyLSzeKIgXTXxV+99ZuXl3Hpo9XpJAv9MBcHrrJOQ5kV7ypXOuQie+AmWG25hLbiKdwYTifzcfQ==" 576 | }, 577 | "wrap-ansi": { 578 | "version": "6.2.0", 579 | "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", 580 | "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", 581 | "requires": { 582 | "ansi-styles": "^4.0.0", 583 | "string-width": "^4.1.0", 584 | "strip-ansi": "^6.0.0" 585 | } 586 | } 587 | } 588 | } 589 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-file-encrypt", 3 | "version": "0.0.8", 4 | "description": "a file encrypt & decrypt package based on TEA", 5 | "main": "file_encrypt.js", 6 | "type": "module", 7 | "scripts": { 8 | "test": "echo \"Error: no test specified\" && exit 1" 9 | }, 10 | "bin": { 11 | "crypt": "./crypt.js" 12 | }, 13 | "dependencies": { 14 | "node-tea": "latest", 15 | "sha1": "latest", 16 | "minimist": "latest", 17 | "log-update": "latest", 18 | "duration": "latest" 19 | }, 20 | "repository": { 21 | "type": "git", 22 | "url": "git+https://github.com/fiefdx/node-file-encrypt.git" 23 | }, 24 | "keywords": [ 25 | "file", 26 | "encrypt", 27 | "decrypt", 28 | "tea" 29 | ], 30 | "author": "fiefdx", 31 | "license": "MIT", 32 | "bugs": { 33 | "url": "https://github.com/fiefdx/node-file-encrypt/issues" 34 | }, 35 | "homepage": "https://github.com/fiefdx/node-file-encrypt#readme" 36 | } 37 | --------------------------------------------------------------------------------