You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js Crypto:求每次加密结果不同、短文本加密长度<10的加解密方法

咱们先搞清楚原来的加密结果为啥这么长:
你的AES-256-CBC是块加密算法,块大小固定16字节——明文“1”只有1字节,会被自动填充到16字节,加密后还是16字节。再加上16字节的IV转成hex是32个字符,加密后的16字节转hex又是32个,再加上分隔符“XX”,32+2+32=66,这就难怪长度超标了。

要实现「每次加密结果不同」+「加密“1”后长度<10字符」,咱们可以换个思路,用流加密模式+更紧凑的编码方式,具体方案如下:

核心思路

  • 改用AES-256-CTR模式:这是流加密,不需要填充明文,加密1字节的明文只会得到1字节的密文,直接缩短密文长度;
  • 用base64代替hex编码:hex是每字节转2个字符,base64是每3字节转4个字符,空间利用率高很多;
  • 使用4字节的随机nonce:既保证每次加密结果不同(随机nonce),又能控制总长度——4字节nonce+1字节密文=5字节,转base64后是7个字符,完全符合<10的要求。

实现代码

const crypto = require('crypto');
const ENCRYPTION_KEY = 'Must256bytes(32characters)secret'; // 必须是32字符(256位)
const NONCE_LENGTH = 4; // 4字节随机nonce,低频率使用足够安全

function encrypt(text) {
  // 生成随机nonce
  const nonce = crypto.randomBytes(NONCE_LENGTH);
  // 创建CTR加密器
  const cipher = crypto.createCipheriv('aes-256-ctr', Buffer.from(ENCRYPTION_KEY), nonce);
  // 加密明文(流加密无需填充,密文长度和明文一致)
  const encrypted = Buffer.concat([cipher.update(text.toString()), cipher.final()]);
  // 拼接nonce和密文,转base64返回
  return Buffer.concat([nonce, encrypted]).toString('base64');
}

function decrypt(text) {
  try {
    // 把base64转成Buffer
    const buffer = Buffer.from(text, 'base64');
    // 拆分nonce(前4字节)和密文(剩余部分)
    const nonce = buffer.slice(0, NONCE_LENGTH);
    const encryptedText = buffer.slice(NONCE_LENGTH);
    // 创建CTR解密器
    const decipher = crypto.createDecipheriv('aes-256-ctr', Buffer.from(ENCRYPTION_KEY), nonce);
    // 解密
    const decrypted = Buffer.concat([decipher.update(encryptedText), decipher.final()]);
    return decrypted.toString();
  } catch (err) {
    return 'NULL';
  }
}

安全性说明

  • 4字节nonce的碰撞概率:对于同一个密钥,理论上每加密2^16次才会有1%的碰撞概率,如果你不是高频加密(比如每秒上万次),这个长度完全够用;
  • 如果需要更高的安全性(比如高频场景),可以把NONCE_LENGTH改成8,此时加密“1”的结果是11个字符,虽然超过了10,但安全性大幅提升——你可以根据自己的实际需求权衡。

内容的提问来源于stack exchange,提问作者Gopalakrishnan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:35:08