encrypt_pdf.ts 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. // scripts/encrypt_pdf.ts
  2. import * as fs from 'fs'
  3. import * as path from 'path'
  4. import * as crypto from 'crypto'
  5. import { fileURLToPath } from 'url'
  6. const __filename = fileURLToPath(import.meta.url);
  7. const __dirname = path.dirname(__filename);
  8. const PDF_DIR = path.resolve(__dirname, '../../public/pdf')
  9. // 生成一个256位(32字节)的密钥
  10. function generateKey(): Buffer {
  11. return crypto.randomBytes(32) // 256 bits = 32 bytes
  12. }
  13. function getKey(password: string): Buffer {
  14. return crypto.createHash('sha256').update(password).digest()
  15. }
  16. function encryptGCM(inputPath: string, outputPath: string, password: string): void {
  17. const key = getKey(password)
  18. const iv = crypto.randomBytes(12) // GCM 推荐的 IV 长度
  19. console.log(`✔ iv: ${iv.toString('base64')}`)
  20. const input = fs.readFileSync(inputPath)
  21. const cipher = crypto.createCipheriv('aes-256-gcm', key, iv)
  22. const encrypted = Buffer.concat([cipher.update(input), cipher.final()])
  23. // console.log(`✔ encrypted: ${encrypted.toString('base64')}`)
  24. const authTag = cipher.getAuthTag()
  25. console.log(`✔ authTag: ${authTag.toString('base64')}`)
  26. const passwordBuffer = Buffer.from(password, 'base64')
  27. const passwordLen = passwordBuffer.length
  28. const lenBuf = Buffer.alloc(4)
  29. lenBuf.writeUInt32BE(passwordLen)
  30. const output = Buffer.concat([iv, encrypted, authTag, passwordBuffer, lenBuf]) // 格式:[IV][DATA][TAG][PASSWORD][PASSWORD_LEN]
  31. fs.writeFileSync(outputPath, output)
  32. console.log(`✔ Encrypted (GCM): ${path.basename(inputPath)}`)
  33. }
  34. function encryptAllPDFs(): void {
  35. const files = fs.readdirSync(PDF_DIR)
  36. for (const file of files) {
  37. const fullPath = path.join(PDF_DIR, file)
  38. if (!fs.statSync(fullPath).isFile() || !file.endsWith('.pdf')) continue
  39. const encPath = fullPath + '.enc'
  40. if (fs.existsSync(encPath)) {
  41. console.log(`⏭ Skipped (already encrypted): ${file}`)
  42. continue
  43. }
  44. const key = generateKey()
  45. encryptGCM(fullPath, encPath, key.toString('base64'))
  46. }
  47. }
  48. encryptAllPDFs()