更新记录
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.subtle、btoa、TextEncoder、Buffer),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 引擎。

收藏人数:
下载插件并导入HBuilderX
下载插件ZIP
赞赏(0)
下载 6
赞赏 0
下载 12569887
赞赏 1949
赞赏
京公网安备:11010802035340号