在JavaScript/Node.js中如何不转字符串实现数字对数字的加解密?
MongoDB数字字段无字符串转换加解密实现方案
核心采用**格式保持加密(Format-Preserving Encryption, FPE)**实现,这是NIST认证的标准加密算法,专门用于加密后输出和输入同类型、同范围的结果,完全满足数字输入输出、无需转字符串、可逆、唯一的需求。
适用前提
- 待加密的number字段为固定取值范围,不能是无上限的任意大数,比如常规32位有符号整数、64位有符号整数、固定精度的浮点数都支持
- 需要提前独立存储对称加密密钥和业务调整参数(tweak),密钥不能和MongoDB存储的数据放在同一集群
实现步骤
- 明确加密数值范围:如果是整数直接取字段的取值上下限;如果是浮点数,先按精度放大为整数,比如保留2位小数的浮点数统一乘以100转为整数,全程都是数值运算,无需转字符串
- 选择对应语言的FPE标准实现,优先选择FF1、FF3算法的成熟封装库,无需自行实现加密逻辑
- 加密时直接传入原始数值、密钥、tweak参数,输出的加密结果为同类型数字,直接写入MongoDB的number字段即可
- 解密时将MongoDB读取到的加密数字直接传入解密方法,使用相同的密钥和tweak,直接得到原始数字
边界注意事项
- 加密前需要对超出取值范围的数值做校验拦截,避免加密后出现溢出问题
- 相同的原始数值、相同密钥和tweak会得到相同的加密结果,保证唯一性,不会出现碰撞
- 不要使用自行实现的异或、固定位移位等弱加密逻辑,这类逻辑容易被暴力破解,安全性无保障
代码示例(Node.js环境)
使用成熟的fpe-ff1库实现,全程输入输出都是数字类型,无字符串转换:
const FF1 = require('fpe-ff1'); // 初始化加密实例,指定加密范围为32位有符号整数(0~2^31-1) const fpeInstance = new FF1({ key: Buffer.from('YOUR_32BYTE_SECRET_KEY'), tweak: Buffer.from('YOUR_BUSINESS_TWEAK'), radix: 10, max: 2147483647 }); // 加密,输入原始数字 const encryptedNumber = fpeInstance.encrypt(123456789); // 输出为数字类型,例如 876543219,可直接存入MongoDB // 解密,输入从MongoDB读取的加密数字 const originalNumber = fpeInstance.decrypt(encryptedNumber); // 输出为原始数字 123456789
内容的提问来源于stack exchange,提问作者Yash Kulshrhestha
相关产品推荐
相关产品推荐

