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

如何改进代码生成高安全性、合规的StoreId与TransactionId编码Docket Number?

优化StoreId+TransactionId生成防破解Docket Number方案

需求与现有问题

基于最大3位的StoreId和最大5位的TransactionId生成编码后的Docket Number,要求:

  1. 编码唯一
  2. 长度≤9位
  3. 便于用户读取与复制

现有代码通过反转ID+加减密钥实现编码,但混淆逻辑过于简单,易被第三方破解,需优化提升安全性。

现有代码实现

let myTransKey = 19651;
let myStoreKey = 186;

function generateShortCode(storeId, transactionId) {
  //reverse the ids and then add the respective key
  var SID = storeId.toString().split("").reverse().join("");
  SID = parseInt(SID) + myStoreKey;
  var TID = transactionId.toString().split("").reverse().join("");
  TID = parseInt(TID) + myTransKey;
  var docketNum = `${SID}-${TID}`;
  return docketNum;
}

function decodeShortCode(shortCode) {
  shortCode = shortCode.split("-");
  var storeID = shortCode[0];
  var transactionID = shortCode[1];

  //subtract the same key and then reverse the ids again
  storeID = parseInt(storeID.toString()) - myStoreKey;
  storeID = storeID.toString().split("").reverse().join("");

  transactionID = parseInt(transactionID.toString()) - myTransKey;
  transactionID = transactionID.toString().split("").reverse().join("");

  return {
    storeId: parseInt(storeID),
    shopDate: new Date(),
    transactionId: parseInt(transactionID)
  };
}

优化方案

核心优化思路

  • 替换简单的反转+加减逻辑,改用自定义字符集进制转换+固定偏移混淆,既保证唯一性,又大幅提升破解门槛
  • 严格控制编码长度,确保最终结果远低于9位限制
  • 剔除易混淆字符,提升用户读取、复制的准确性

优化后代码实现

// 自定义字符集:排除0/O、1/I/l等易混淆字符,共32个字符(适配2^5进制,便于计算)
const CHAR_SET = '23456789ABCDEFGHJKLMNPQRSTUVWXYZ';
const CHAR_SET_LEN = CHAR_SET.length;

// 混淆偏移密钥(建议随机生成后固定,不要使用有规律的数值)
const STORE_OFFSET = 127;
const TRANS_OFFSET = 8193;

/**
 * 生成防破解的Docket Number
 * @param {number} storeId 0-999的整数
 * @param {number} transactionId 0-99999的整数
 * @returns {string} 固定7位的编码
 */
function generateDocketNumber(storeId, transactionId) {
  // 输入合法性校验
  if (!Number.isInteger(storeId) || storeId < 0 || storeId > 999) {
    throw new Error('StoreId必须是0-999的整数');
  }
  if (!Number.isInteger(transactionId) || transactionId < 0 || transactionId > 99999) {
    throw new Error('TransactionId必须是0-99999的整数');
  }

  // 混淆StoreId并转3位32进制(32^3=32768 > 999+127=1126,足够容纳)
  let obfuscatedStore = storeId + STORE_OFFSET;
  let storeCode = '';
  for (let i = 0; i < 3; i++) {
    storeCode = CHAR_SET[obfuscatedStore % CHAR_SET_LEN] + storeCode;
    obfuscatedStore = Math.floor(obfuscatedStore / CHAR_SET_LEN);
  }

  // 混淆TransactionId并转4位32进制(32^4=1048576 > 99999+8193=108192,足够容纳)
  let obfuscatedTrans = transactionId + TRANS_OFFSET;
  let transCode = '';
  for (let i = 0; i < 4; i++) {
    transCode = CHAR_SET[obfuscatedTrans % CHAR_SET_LEN] + transCode;
    obfuscatedTrans = Math.floor(obfuscatedTrans / CHAR_SET_LEN);
  }

  // 拼接后得到固定7位的编码
  return storeCode + transCode;
}

/**
 * 解码Docket Number
 * @param {string} docketNum 7位编码字符串
 * @returns {object} 包含storeId、transactionId的对象
 */
function decodeDocketNumber(docketNum) {
  if (typeof docketNum !== 'string' || docketNum.length !== 7) {
    throw new Error('无效的Docket Number格式');
  }

  // 拆分Store编码(前3位)和Transaction编码(后4位)
  const storeCode = docketNum.slice(0, 3);
  const transCode = docketNum.slice(3);

  // 解码StoreId
  let obfuscatedStore = 0;
  for (const char of storeCode) {
    obfuscatedStore = obfuscatedStore * CHAR_SET_LEN + CHAR_SET.indexOf(char);
  }
  const storeId = obfuscatedStore - STORE_OFFSET;
  if (storeId < 0 || storeId > 999) {
    throw new Error('无效的StoreId');
  }

  // 解码TransactionId
  let obfuscatedTrans = 0;
  for (const char of transCode) {
    obfuscatedTrans = obfuscatedTrans * CHAR_SET_LEN + CHAR_SET.indexOf(char);
  }
  const transactionId = obfuscatedTrans - TRANS_OFFSET;
  if (transactionId < 0 || transactionId > 99999) {
    throw new Error('无效的TransactionId');
  }

  return {
    storeId,
    shopDate: new Date(), // 若需真实交易日期,建议在生成时将日期编码进字符串,此处保留原有逻辑
    transactionId
  };
}

方案优势

  1. 高防破解性:自定义字符集的进制转换+随机偏移,第三方无法通过简单的数值反转、加减推断规则;32种字符的7位编码有3.4×10¹⁰种组合,远超实际业务的1×10⁸种有效组合,枚举破解成本极高。
  2. 绝对唯一性:每个StoreId+TransactionId的组合对应唯一的混淆值,转32进制后无重复。
  3. 极致简洁:固定7位编码,远低于9位限制,用户读取、复制更方便。
  4. 低输入错误率:剔除易混淆字符,避免用户将0/O、1/I等字符搞混。

额外建议

  • 混淆偏移密钥(STORE_OFFSET、TRANS_OFFSET)建议用随机数生成器生成,不要使用如100、1000这类有规律的数值,进一步提升安全性。
  • 若需加入交易日期信息,可调整编码结构(比如用2位表示年份后两位+2位表示日期,剩余3位处理StoreId和TransactionId),确保总长度不超过9位即可。
  • 生成编码前必须校验输入范围,避免非法值导致编码异常。

内容的提问来源于stack exchange,提问作者Bipin Raj Sitoula

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 04:02:20