@king-3/file-kit 1.3.1 → 1.4.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/dist/cli.js +44 -20
  2. package/package.json +2 -1
package/dist/cli.js CHANGED
@@ -6,7 +6,8 @@ import fs from "node:fs/promises";
6
6
  import { Buffer } from "node:buffer";
7
7
  import { accessSync, existsSync, mkdirSync } from "node:fs";
8
8
  import { confirm, intro, isCancel, outro, password, select, spinner, text } from "@clack/prompts";
9
- import { createCipheriv, createDecipheriv, pbkdf2Sync, randomBytes } from "node:crypto";
9
+ import { createCipheriv, createDecipheriv, randomBytes } from "node:crypto";
10
+ import { argon2id, hash } from "argon2";
10
11
  import path$1 from "node:path/posix";
11
12
  import ffmpegPath from "@ffmpeg-installer/ffmpeg";
12
13
  import { execa } from "execa";
@@ -164,8 +165,16 @@ const base64ToBuffer = (data) => Buffer.from(data, "base64");
164
165
  //#endregion
165
166
  //#region src/utils/time.ts
166
167
  function nowUTC8() {
167
- const now = /* @__PURE__ */ new Date();
168
- return new Date(now.getTime() + 480 * 60 * 1e3).toISOString().replace("T", " ").substring(0, 19);
168
+ return (/* @__PURE__ */ new Date()).toLocaleString("zh-CN", {
169
+ timeZone: "Asia/Shanghai",
170
+ year: "numeric",
171
+ month: "2-digit",
172
+ day: "2-digit",
173
+ hour: "2-digit",
174
+ minute: "2-digit",
175
+ second: "2-digit",
176
+ hour12: false
177
+ }).replace(/\//g, "-");
169
178
  }
170
179
 
171
180
  //#endregion
@@ -225,7 +234,7 @@ async function base64ToFile(archiveData, outputDir = ".") {
225
234
  //#endregion
226
235
  //#region src/config/defaults.ts
227
236
  const CLI_NAME = "File Kit";
228
- const CLI_VERSION = "1.3.1";
237
+ const CLI_VERSION = "1.4.1";
229
238
  const CLI_ALIAS = "fkt";
230
239
  /**
231
240
  * 默认配置
@@ -349,7 +358,7 @@ async function getInputPath(providedPath, options) {
349
358
  }
350
359
  return inputPath;
351
360
  }
352
- async function getPassword(providedPwd) {
361
+ async function getPassword(providedPwd, options) {
353
362
  let userPwd = providedPwd;
354
363
  if (!userPwd) {
355
364
  userPwd = await password$1({
@@ -359,14 +368,14 @@ async function getPassword(providedPwd) {
359
368
  if (value.length < 6) return "密码长度至少 6 位";
360
369
  }
361
370
  });
362
- await password$1({
371
+ if (options?.confirm) await password$1({
363
372
  message: "请再次输入密码:",
364
373
  validate: (value) => {
365
374
  if (value !== userPwd) return "两次密码不一致";
366
375
  }
367
376
  });
368
377
  } else if (typeof userPwd === "string" && userPwd.length < 6) {
369
- logger.error(`'密码长度至少 6 位'`);
378
+ logger.error("密码长度至少 6 位");
370
379
  process.exit(1);
371
380
  }
372
381
  return userPwd;
@@ -441,7 +450,7 @@ var base64_default = defineCommand({
441
450
  const typedArgs = args;
442
451
  const ctx = createCommandContext(rawArgs);
443
452
  ctx.showIntro();
444
- tryCatch(async () => {
453
+ await tryCatch(async () => {
445
454
  const inputPath = await ctx.getInput(typedArgs.input, {
446
455
  message: "请输入文件路径",
447
456
  placeholder: "file.txt"
@@ -459,9 +468,14 @@ var base64_default = defineCommand({
459
468
  //#region src/config/crypto-algorithm.ts
460
469
  const CRYPTO_ALGORITHM = {
461
470
  name: "aes-256-gcm",
462
- ivLength: 16,
471
+ ivLength: 12,
463
472
  saltLength: 32,
464
- iterations: 1e5
473
+ keyLength: 32,
474
+ argon2: {
475
+ memoryCost: 131072,
476
+ timeCost: 3,
477
+ parallelism: 4
478
+ }
465
479
  };
466
480
 
467
481
  //#endregion
@@ -469,8 +483,18 @@ const CRYPTO_ALGORITHM = {
469
483
  /**
470
484
  * 从密码派生密钥
471
485
  */
472
- const deriveKey = (password$2, salt) => {
473
- return pbkdf2Sync(password$2, salt, 1e5, 32, "sha256");
486
+ const deriveKey = async (password$2, salt) => {
487
+ const { argon2: argon2Config } = CRYPTO_ALGORITHM;
488
+ const result = await hash(password$2, {
489
+ type: argon2id,
490
+ salt,
491
+ memoryCost: argon2Config.memoryCost,
492
+ timeCost: argon2Config.timeCost,
493
+ parallelism: argon2Config.parallelism,
494
+ hashLength: CRYPTO_ALGORITHM.keyLength,
495
+ raw: true
496
+ });
497
+ return Buffer.from(result);
474
498
  };
475
499
  /**
476
500
  * 加密文件
@@ -485,7 +509,7 @@ async function encrypt(filePath, outputPath, options) {
485
509
  const fileExt = getFileExt(filePath);
486
510
  const salt = randomBytes(CRYPTO_ALGORITHM.saltLength);
487
511
  const iv = randomBytes(CRYPTO_ALGORITHM.ivLength);
488
- const key = deriveKey(options.password, salt);
512
+ const key = await deriveKey(options.password, salt);
489
513
  const cipher = createCipheriv(CRYPTO_ALGORITHM.name, key, iv);
490
514
  const encrypted = Buffer.concat([cipher.update(fileBuffer), cipher.final()]);
491
515
  const authTag = cipher.getAuthTag();
@@ -526,7 +550,7 @@ async function decrypt(archiveData, outputDir = ".", options) {
526
550
  const iv = base64ToBuffer(file.iv);
527
551
  const authTag = base64ToBuffer(file.authTag);
528
552
  const encrypted = base64ToBuffer(file.encrypted);
529
- const key = deriveKey(options.password, salt);
553
+ const key = await deriveKey(options.password, salt);
530
554
  const decipher = createDecipheriv(CRYPTO_ALGORITHM.name, key, iv);
531
555
  decipher.setAuthTag(authTag);
532
556
  let decrypted;
@@ -573,14 +597,14 @@ var decrypt_default = defineCommand({
573
597
  const typedArgs = args;
574
598
  const ctx = createCommandContext(rawArgs);
575
599
  ctx.showIntro();
576
- tryCatch(async () => {
600
+ await tryCatch(async () => {
577
601
  const inputPath = await ctx.getInput(typedArgs.input, {
578
602
  message: "请输入文件路径",
579
603
  placeholder: "*.crypto.txt",
580
604
  validateExtension: ".crypto.txt"
581
605
  });
582
606
  const outputDir = await ctx.getOutput(typedArgs.output, { defaultDir: path.dirname(inputPath) });
583
- const password$2 = await getPassword(typedArgs.password);
607
+ const password$2 = await getPassword(typedArgs.password, { confirm: false });
584
608
  const loading$1 = ctx.loading("正在解密");
585
609
  const outputPath = await decrypt(await loadArchive(inputPath, "crypto"), outputDir, { password: password$2 });
586
610
  loading$1.close(`文件已解密到: ${cyan(outputPath)}`);
@@ -617,13 +641,13 @@ var encrypt_default = defineCommand({
617
641
  const typedArgs = args;
618
642
  const ctx = createCommandContext(rawArgs);
619
643
  ctx.showIntro();
620
- tryCatch(async () => {
644
+ await tryCatch(async () => {
621
645
  const inputPath = await ctx.getInput(typedArgs.input, {
622
646
  message: "请输入文件路径",
623
647
  placeholder: "file.txt"
624
648
  });
625
649
  const outputDir = await ctx.getOutput(typedArgs.output, { defaultDir: path$1.dirname(inputPath) });
626
- const password$2 = await getPassword(typedArgs.password);
650
+ const password$2 = await getPassword(typedArgs.password, { confirm: true });
627
651
  console.log(gray("│"));
628
652
  logger.warn(yellow("请妥善保管密码,丢失后无法恢复文件!"));
629
653
  const outputPath = buildOutputPath(inputPath, outputDir, "crypto.txt");
@@ -657,7 +681,7 @@ var restore_default = defineCommand({
657
681
  const typedArgs = args;
658
682
  const ctx = createCommandContext(rawArgs);
659
683
  ctx.showIntro();
660
- tryCatch(async () => {
684
+ await tryCatch(async () => {
661
685
  const inputPath = await ctx.getInput(typedArgs.input, {
662
686
  message: "请输入文件路径",
663
687
  placeholder: "*.base64.txt",
@@ -899,7 +923,7 @@ var video_to_audio_default = defineCommand({
899
923
  const typedArgs = args;
900
924
  const ctx = createCommandContext(rawArgs);
901
925
  ctx.showIntro();
902
- tryCatch(async () => {
926
+ await tryCatch(async () => {
903
927
  const inputPath = await ctx.getInput(typedArgs.input, {
904
928
  message: "请输入视频文件路径",
905
929
  placeholder: "video.mp4"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@king-3/file-kit",
3
- "version": "1.3.1",
3
+ "version": "1.4.1",
4
4
  "description": "多功能文件工具箱(Base64 转换 · 视频转音频 · 加密/解密)",
5
5
  "type": "module",
6
6
  "keywords": [
@@ -41,6 +41,7 @@
41
41
  "@clack/prompts": "^0.11.0",
42
42
  "@ffmpeg-installer/ffmpeg": "^1.1.0",
43
43
  "ansis": "^4.2.0",
44
+ "argon2": "^0.44.0",
44
45
  "citty": "^0.1.6",
45
46
  "execa": "^9.6.1"
46
47
  },