更新记录

1.0.0(2026-09-07) 下载此版本

首个版本。

  • 摘要算法:MD5、SHA-1、SHA-256、HMAC-SHA256(UTF-8 输入,Hex 输出,另提供 SHA-256 → Base64Url)
  • 对称加密:AES-128 / 192 / 256,ECB / CBC 分组模式,PKCS7 填充,Base64 / Hex 输出,与后端常见 AES 实现互通
  • 编码转换:UTF-8 / Base64 / Base64Url / Hex,不依赖 btoa/atob/TextEncoder/Buffer,iOS JSCore 与小程序环境可用
  • 随机工具:随机字节(优先平台 crypto.getRandomValues)、随机字符串、PKCE verifier、UUID v4
  • PKCE(RFC 7636,S256):createPkce 一步生成 code_verifier / code_challenge
  • 全部算法为纯 JS 本地计算,无原生依赖、无需自定义调试基座,H5 / App / 小程序全端可用
  • 附带 node:test 对拍 node:crypto 的正确性测试(tests/crypto.test.cjs)与 TS 类型声明(js_sdk/index.d.ts)

平台兼容性

uni-app(4.25)

Vue2 Vue3 Chrome Safari app-vue app-nvue Android iOS 鸿蒙
5.0 12
微信小程序 支付宝小程序 抖音小程序 百度小程序 快手小程序 京东小程序 鸿蒙元服务 QQ小程序 飞书小程序 小红书小程序 快应用-华为 快应用-联盟
× × ×

uni-app x(4.25)

Chrome Safari Android iOS 鸿蒙 微信小程序
- - - - - -

fz-utils 基础算法工具库

常用基础算法的纯 JS 工具库(uni_modules 插件),H5 / App(vue、nvue)/ 各家小程序全端可用

  • 全部算法在本地计算,不发起任何网络请求
  • 无原生依赖、不需要制作自定义调试基座,放进 uni_modules 即可用;
  • 不依赖任何浏览器专属 API(crypto.subtlebtoaTextEncoderBuffer),iOS JSCore 与小程序 JS 引擎同样可运行;
  • 支持 Vue2 / Vue3,自带 TS 类型声明(js_sdk/index.d.ts);
  • 每个算法都与 node:crypto 对拍验证(见文末「测试」)。

功能一览

模块 能力 关键函数
encoding UTF-8 / Base64 / Base64Url / Hex 编解码 base64Encode base64Decode utf8Encode utf8Decode bytesToHex hexToBytes
md5 MD5 摘要(32 位小写 Hex) md5
sha1 SHA-1 摘要(40 位小写 Hex,兼容旧接口用) sha1
sha256 SHA-256、HMAC-SHA256、SHA-256 → Base64Url sha256 sha256Bytes sha256Base64Url hmacSha256
aes AES-128 / 192 / 256,ECB / CBC,PKCS7 aesEncrypt aesDecrypt
random 随机字节 / 随机串 / UUID v4 randomBytes randomString randomVerifier uuid
pkce PKCE(RFC 7636,S256)参数对生成 createPkce

快速上手

1. 把 fz-utils 目录放进工程 uni_modules/

2. 按需导入(推荐从汇总入口导入):

import {
    md5, sha256, hmacSha256,        // 摘要
    aesEncrypt, aesDecrypt,         // AES
    base64Encode, base64Decode,     // 编码
    randomString, uuid,             // 随机
    createPkce                      // PKCE
} from '@/uni_modules/fz-utils/js_sdk/index.js'

也可以只引单个模块,减小页面耦合:

import { md5 } from '@/uni_modules/fz-utils/js_sdk/md5.js'
import { aesEncrypt } from '@/uni_modules/fz-utils/js_sdk/aes.js'

3.(可选)跑演示页:测试工程里的 pages/utils/utils(首页「算法工具集」)可交互验证所有函数,可直接参考其调用方式。

⚠️ Options API 页面注意:模板表达式只能访问实例成员,不要<template> 里直接调用导入的函数(会报 _ctx.md5 is not a function),请在 methods 里包一层转发;<script setup> 写法无此限制。

使用方法

1. 摘要哈希(MD5 / SHA-1 / SHA-256 / HMAC)

函数 入参 返回
md5(input) 字符串(按 UTF-8 编码)或 Uint8Array 32 位小写 Hex
sha1(input) 同上 40 位小写 Hex
sha256(input) 同上 64 位小写 Hex
sha256Bytes(input) 同上 32 字节 Uint8Array 原始摘要
sha256Base64Url(input) 同上 Base64Url 字符串(PKCE challenge 编码格式)
hmacSha256(message, key) 消息 + 密钥(均可为字符串/字节,密钥超 64 字节自动先摘要) 64 位小写 Hex
md5('hello')                          // '5d41402abc4b2a76b9719d911017c592'
md5('你好,世界 🌊')                    // 中文/emoji 按 UTF-8 处理,结果正确
sha256('hello')                       // '2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824'
hmacSha256('message', 'secret')       // HMAC-SHA256,Hex 输出
sha256Base64Url('some verifier')      // 'xxxxxxxx…'(无 padding 的 url-safe 串)

const bytes = utf8Encode('对字节算摘要')
sha256(bytes)                         // 也可直接对 Uint8Array 计算

2. AES 加解密

函数 签名 说明
aesEncrypt (data, key, iv?, options?) → String 明文(字符串/字节)→ 密文(默认 Base64)
aesDecrypt (data, key, iv?, options?) → String 密文 → 明文(UTF-8 字符串)

参数约定:

  • key:字符串按 UTF-8 取字节,长度必须 16 / 24 / 32 字节(对应 AES-128 / 192 / 256),其他长度直接抛错;
  • iv:CBC 模式必填,16 字节;ECB 模式传 null 或不传;
  • options.mode'CBC'(默认)或 'ECB'
  • options.padding'PKCS7'(默认)或 'NONE'(此时明文/密文长度必须是 16 的倍数);
  • options.output(加密):'base64'(默认)或 'hex'
  • options.input(解密):'base64'(默认)或 'hex'
const key = '1234567890abcdef'            // 16 字节 → AES-128
const iv  = 'fedcba0987654321'            // 16 字节

const cipher = aesEncrypt('机密数据 🌊', key, iv)
// 'xlE8…'(Base64 密文)
const plain = aesDecrypt(cipher, key, iv)
// '机密数据 🌊'

// ECB 模式(不需要 IV)
const c2 = aesEncrypt('data', 'a-32-bytes-key-__________________', null, { mode: 'ECB' })

// Hex 密文(与后端约定 hex 时)
const c3 = aesEncrypt('data', key, iv, { output: 'hex' })
aesDecrypt(c3, key, iv, { input: 'hex' })

与后端互通:处理链路为 UTF-8 → PKCS7 → AES → Base64,与 Java AES/CBC/PKCS7Padding、Node createCipheriv('aes-128-cbc', …)、Python pycryptodome 默认行为一致,双方用相同 key/iv 即可互解。仅注意:Java 侧常见「key 取 md5(password) 的 32 位 hex 字符串(32 字节)」这类约定,请与后端确认 key 的实际取值方式。

3. 编码转换

函数 说明
utf8Encode(str) / utf8Decode(bytes) 字符串 ↔ UTF-8 字节(正确处理 emoji 代理对;解码遇非法序列以 U+FFFD 兜底不抛错)
base64Encode(text) / base64Decode(b64) 字符串 ↔ Base64(UTF-8 安全)
bytesToBase64(bytes) / base64ToBytes(b64) 字节 ↔ Base64(解码兼容 Base64Url、缺失 padding、空白字符)
bytesToBase64Url(bytes) / base64UrlToBytes(s) 字节 ↔ Base64Url(+→-/→_、去 =
bytesToHex(bytes) / hexToBytes(hex) 字节 ↔ 小写 Hex(解码忽略空白与大小写)
base64Encode('你好 🌊')                     // '5L2g5aW9IPCfjIo='
base64Decode('5L2g5aW9IPCfjIo=')           // '你好 🌊'
utf8Encode('abc')                          // Uint8Array [97, 98, 99]
bytesToHex(utf8Encode('hi'))               // '6869'
hexToBytes('6869')                         // Uint8Array [104, 105]

4. 随机串与 UUID

函数 说明
randomBytes(len) 随机字节;优先平台 crypto.getRandomValues,不可用退化为 Math.random
randomString(len?, charset?) 随机字符串,默认 32 位、大小写字母+数字;charset 可传 '0123456789' 做数字验证码
randomVerifier(len?) PKCE 字符集(字母数字 -._~)随机串,默认 64 位
uuid() UUID v4(xxxxxxxx-xxxx-4xxx-[89ab]xxx-xxxxxxxxxxxx
randomString(6, '0123456789')   // '830217'  短信验证码场景
randomString(32)                // 默认字母数字
uuid()                          // '3f8a…-4…-8…-…'

随机源说明:H5(https/localhost)、Node、部分运行时有 crypto.getRandomValues 时使用加密级随机;小程序等无此 API 的环境退化为 Math.random,做验证码等非安全场景没问题,密钥类用途请确认运行时支持。

5. PKCE(OAuth 授权码扩展,RFC 7636)

const { codeVerifier, codeChallenge } = createPkce()   // 默认 64 位 verifier
// createPkce(96) 可指定长度(43~128,越界抛错)

// codeVerifier: 自己保存(如 uni.setStorageSync),换 token 时上送
// codeChallenge: BASE64URL(SHA256(codeVerifier)),拼进授权 URL 的 code_challenge 参数
// 即: codeChallenge === sha256Base64Url(codeVerifier)

任何 OAuth 2.0 服务(Dropbox、Google 等)走 PKCE 流程时都可用它生成参数对,再按各服务的授权 URL 模板拼接即可。

常见场景示例

接口签名(HMAC)

const sign = hmacSha256(`path=/order/list&ts=${Date.now()}`, 'server-secret')
uni.request({ url, header: { 'X-Sign': sign }, /* … */ })

本地敏感数据加密

// 存
uni.setStorageSync('token_enc', aesEncrypt(accessToken, localKey, localIv))
// 取
const token = aesDecrypt(uni.getStorageSync('token_enc'), localKey, localIv)

URL 安全传参

const payload = bytesToBase64Url(utf8Encode(JSON.stringify({ uid: 10001 })))

错误处理约定

所有参数校验失败均 throw Error,错误信息以 fz-utils: 开头(如 fz-utils: AES 密钥必须是 16/24/32 字节(UTF-8),当前 10 字节)、fz-utils: PKCS7 填充校验失败)。密钥错误解密时通常表现为 PKCS7 校验失败或解出乱码,注意先核对 key/iv 与编码格式。

目录结构

fz-utils
├── js_sdk
│   ├── encoding.js        UTF-8/Base64/Base64Url/Hex
│   ├── md5.js             MD5
│   ├── sha1.js            SHA-1
│   ├── sha256.js          SHA-256 / HMAC-SHA256
│   ├── aes.js             AES(ECB/CBC + PKCS7)
│   ├── random.js          随机字节/随机串/verifier/UUID
│   ├── pkce.js            PKCE(S256)
│   ├── index.js           汇总导出
│   └── index.d.ts         TS 类型声明
├── tests
│   └── crypto.test.cjs    node:test 对拍 node:crypto 的正确性测试
├── package.json
├── readme.md
└── changelog.md

测试

node --test uni_modules/fz-utils/tests/crypto.test.cjs

覆盖:MD5/SHA-1/SHA-256/HMAC 与 node:crypto 全量对拍(中文、emoji、空串、1KB 跨分组、55/56/63/64 填充边界);AES 三种密钥长度 × ECB/CBC × 多种明文长度双向对拍(我方加密 node 解、node 加密我方解);hex 输入输出;无填充模式;篡改密文检测;PKCE 按 RFC 7636 对拍;Base64/Hex/UTF-8 与 Buffer 对拍。

设计说明

  • 算法类插件选择 js_sdk 纯 JS 形态而非 UTS 原生插件:算法是纯计算,不需要任何原生能力;纯 JS 在全端行为完全一致,也没有 UTS 跨语言(Kotlin / Swift 整型溢出与位运算语义差异)的坑。后续如需原生加速,可保持接口不变,在 utssdk/ 下按平台包一层。
  • AES S-Box 在运行时用 GF(2^8) 指数/对数表求逆元 + 仿射变换生成,避免手抄 256 个常量字节出错。
  • 摘要函数统一支持 string | Uint8Array 入参;哈希类实现全部使用 32 位运算并显式 |0 / >>> 0 收敛,兼容各端 JS 引擎。

隐私、权限声明

1. 本插件需要申请的系统权限列表:

2. 本插件采集的数据、发送的服务器地址、以及数据用途说明:

全部算法在本地纯 JS 计算,不发起任何网络请求,不上传任何数据。

3. 本插件是否包含广告,如包含需详细说明广告表达方式、展示频率:

许可协议

MIT协议

暂无用户评论。