crypto.js 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758
  1. /**
  2. * 条码/二维码内容编码工具(Base64Url)
  3. *
  4. * 设计:
  5. * - 生成端用 Base64Url 对原文编码,并加 `~` 前缀标识;
  6. * - 扫码端识别前缀后 Base64Url 解码还原原文;
  7. * - 无前缀的历史/明文码直接透传,保证向后兼容;
  8. * - 仅防止肉眼直接读取,不是真正的加密。
  9. */
  10. const ENCODE_PREFIX = '~';
  11. function toBase64Url(str) {
  12. const b64 = btoa(unescape(encodeURIComponent(str)));
  13. return b64.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
  14. }
  15. function fromBase64Url(str) {
  16. let b64 = str.replace(/-/g, '+').replace(/_/g, '/');
  17. while (b64.length % 4) b64 += '=';
  18. return decodeURIComponent(escape(atob(b64)));
  19. }
  20. /**
  21. * 编码原文:输出 `~` + Base64Url(原文)。
  22. * @param {string} plain
  23. * @returns {string}
  24. */
  25. export function encryptCode(plain) {
  26. if (plain == null || plain === '') return '';
  27. try {
  28. return ENCODE_PREFIX + toBase64Url(String(plain));
  29. } catch (e) {
  30. console.error('encryptCode failed:', e);
  31. return String(plain);
  32. }
  33. }
  34. /**
  35. * 解码扫码内容:
  36. * - 以 `~` 开头:Base64Url 解码还原原文;失败时回退原值;
  37. * - 不以 `~` 开头:视为明文,直接返回(兼容历史码)。
  38. * @param {string} code
  39. * @returns {string}
  40. */
  41. export function decryptCode(code) {
  42. if (code == null || code === '') return '';
  43. const str = String(code).trim();
  44. if (!str.startsWith(ENCODE_PREFIX)) return str;
  45. try {
  46. return fromBase64Url(str.slice(ENCODE_PREFIX.length));
  47. } catch (e) {
  48. console.error('decryptCode failed:', e, code);
  49. return str;
  50. }
  51. }
  52. export default { encryptCode, decryptCode };