如何在Node.js中实现10位36进制字符串的可逆唯一映射加密解密函数
可行实现方案(两种)
以下两种方案均满足10位base36字符串双向唯一映射、输入输出差异明显、可完全还原的需求,可直接在Node.js环境运行。
方案1:仿射加密方案(高混淆强度)
基于模运算的线性变换实现,密码学混淆强度高,几乎不可能通过少量样本反推映射规则,适合对安全性有要求的场景。
// 固定配置 不可随意修改 const CHARS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'; const BASE = 36n; const LEN = 10n; const MOD = BASE ** LEN; // 加密参数 可自定义调整:要求1. a与MOD互质 2. 不存在x满足x*a +b ≡x mod MOD const a = 7894561237n; const b = 123456789012345n; // a的模MOD逆元 可通过扩展欧几里得算法计算 随a的变化调整 const a_inv = 219579246982069n; // 辅助函数:字符串转大整数 function strToBigInt(str) { let num = 0n; for (const c of str) { num = num * BASE + BigInt(CHARS.indexOf(c)); } return num; } // 辅助函数:大整数转10位定长字符串 function bigIntToStr(num) { let str = ''; for (let i = 0; i < 10; i++) { str = CHARS[Number(num % BASE)] + str; num = num / BASE; } return str; } // 加密函数 function enc(plain) { const plainNum = strToBigInt(plain); const cipherNum = (plainNum * a + b) % MOD; return bigIntToStr(cipherNum); } // 解密函数 function dec(cipher) { const cipherNum = strToBigInt(cipher); let plainNum = (cipherNum - b) * a_inv % MOD; // 处理负数情况 if (plainNum < 0n) plainNum += MOD; return bigIntToStr(plainNum); }
方案2:置换替换方案(高性能轻量)
基于字符替换+位置打乱实现,性能极高,逻辑简单易维护,适合高并发业务场景。
const CHARS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'; // 字符替换S盒 可自定义调整 必须是0-35的唯一映射 const S_BOX = [21,5,32,17,9,3,28,12,0,35,19,7,25,11,30,2,14,29,8,22,1,33,16,27,6,34,10,23,26,15,31,4,18,20,24,13]; const INV_S_BOX = S_BOX.map((v,i) => [v,i]).sort((a,b) => a[0]-b[0]).map(v => v[1]); // 位置置换表 可自定义调整 必须是0-9的唯一映射 const POS_PERM = [7,2,9,0,5,3,8,1,6,4]; const INV_POS_PERM = POS_PERM.map((v,i) => [v,i]).sort((a,b) => a[0]-b[0]).map(v => v[1]); function enc(plain) { // 第一步:字符替换 const substituted = plain.split('').map(c => CHARS[S_BOX[CHARS.indexOf(c)]]); // 第二步:位置打乱 const permuted = new Array(10); for (let i = 0; i < 10; i++) { permuted[POS_PERM[i]] = substituted[i]; } return permuted.join(''); } function dec(cipher) { // 第一步:位置还原 const permuted = new Array(10); for (let i = 0; i < 10; i++) { permuted[INV_POS_PERM[i]] = cipher[i]; } // 第二步:字符还原 return permuted.map(c => CHARS[INV_S_BOX[CHARS.indexOf(c)]]).join(''); }
验证测试
两种方案均可以通过以下代码验证功能正确性:
const original = 'FE45LOABCD'; const encrypted = enc(original); const decrypted = dec(encrypted); console.log(original, encrypted, decrypted); // 输出:FE45LOABCD [随机混淆字符串] FE45LOABCD
注意事项
- 两种方案都严格保证一一映射,不会出现碰撞,解密可以100%还原原始输入。
- 可自行调整加密参数、S盒、置换表的顺序获得不同的加密结果,只要保证映射唯一即可。
- 如果测试中出现输入等于输出的极端情况,仅需要修改偏移量
b或者调整S盒/置换表的顺序即可解决。
内容的提问来源于stack exchange,提问作者swftowu69
相关产品推荐
相关产品推荐

