484 lines
13 KiB
Markdown
484 lines
13 KiB
Markdown
# laoqianjunzi-crypto
|
|
|
|
`laoqianjunzi-crypto` 是一个面向 `uni-app x` 的多端加密工具插件,统一封装了文本编解码、摘要、HMAC、AES、DES、3DES、RC4、RSA 等常见能力。
|
|
|
|
插件当前覆盖以下平台:
|
|
|
|
- `App-Android`
|
|
- `App-iOS`
|
|
- `App-Harmony`
|
|
- `Web`
|
|
- `微信小程序`
|
|
|
|
适合以下场景:
|
|
|
|
- 业务请求签名、摘要校验、口令派生前的基础处理
|
|
- 本地敏感文本或字节数据加解密
|
|
- 公私钥生成、RSA 短文本加解密
|
|
- 需要在多端复用同一套加密接口的 `uni-app x` 项目
|
|
|
|
## 功能概览
|
|
|
|
- 支持 `utf8`、`hex`、`base64`、`base64url`、`latin1`、`utf16` 编解码
|
|
- 支持 `md5`、`sha1`、`sha256`、`sha512` 摘要
|
|
- 支持 `HMAC-SHA1`、`HMAC-SHA256`、`HMAC-SHA512`
|
|
- 支持 AES 文本加解密与 AES 字节数组加解密
|
|
- 支持 DES、3DES、RC4 文本加解密
|
|
- 支持 RSA 密钥对生成与短文本加解密
|
|
- 支持读取当前运行时的底层引擎信息
|
|
- 所有计算均在本地执行,不包含网络上传逻辑
|
|
|
|
## 版本要求
|
|
|
|
根据插件当前 `package.json` 配置,建议使用以下环境:
|
|
|
|
- `HBuilderX` `5.07` 或更高版本
|
|
- `uni-app x` `4.75` 或更高版本
|
|
|
|
## 平台支持矩阵
|
|
|
|
| 平台 | 加密能力 | RSA | 运行时引擎 |
|
|
| --- | --- | --- | --- |
|
|
| App-Android | 支持 | 支持 | `JCA` 原生桥接 |
|
|
| App-iOS | 支持 | 支持 | `CommonCrypto` 原生桥接 |
|
|
| App-Harmony | 支持 | 支持 | `@ohos/crypto-js` + 原生 RSA |
|
|
| Web | 支持 | 支持 | `crypto-es` + `jsencrypt` |
|
|
| 微信小程序 | 支持 | 支持 | `crypto-es` + `jsencrypt` |
|
|
|
|
说明:
|
|
|
|
- `describeCryptoRuntime()` 可返回当前平台名、底层引擎名、是否支持高级分组模式、是否经过原生桥接
|
|
- Web 与微信小程序端的实现基于纯脚本运行时,App 端优先走原生桥接
|
|
- 文本加密、文本解密、摘要、签名、RSA 等接口均采用统一函数签名,便于业务跨端复用
|
|
|
|
## 安装与导入
|
|
|
|
将插件放入项目 `uni_modules` 目录后,直接从插件根目录导入:
|
|
|
|
```uts
|
|
import {
|
|
aesDecryptBytes,
|
|
aesDecryptText,
|
|
aesEncryptBytes,
|
|
aesEncryptText,
|
|
createRsaPair,
|
|
decodeText,
|
|
defaultByteCipherOptions,
|
|
defaultTextCipherOptions,
|
|
describeCryptoRuntime,
|
|
digestText,
|
|
encodeText,
|
|
rsaDecryptText,
|
|
rsaEncryptText,
|
|
signText
|
|
} from "@/uni_modules/laoqianjunzi-crypto"
|
|
|
|
import type {
|
|
CryptoByteCipherOptions,
|
|
CryptoRsaPair,
|
|
CryptoRuntimeSnapshot,
|
|
CryptoTextCipherOptions
|
|
} from "@/uni_modules/laoqianjunzi-crypto"
|
|
```
|
|
|
|
请注意:
|
|
|
|
- 只从插件根目录导入,不要直接导入插件内部 `utssdk` 文件
|
|
- 业务代码建议统一使用插件根导出,便于后续维护和跨端类型识别
|
|
|
|
## 快速开始
|
|
|
|
下面示例演示最常用的四类能力:运行时信息、文本编解码、摘要/HMAC、AES 文本加解密、RSA 密钥对与短文本加解密。
|
|
|
|
```uts
|
|
import {
|
|
aesDecryptText,
|
|
aesEncryptText,
|
|
createRsaPair,
|
|
decodeText,
|
|
defaultTextCipherOptions,
|
|
describeCryptoRuntime,
|
|
digestText,
|
|
encodeText,
|
|
rsaDecryptText,
|
|
rsaEncryptText,
|
|
signText
|
|
} from "@/uni_modules/laoqianjunzi-crypto"
|
|
|
|
import type {
|
|
CryptoRsaPair,
|
|
CryptoRuntimeSnapshot,
|
|
CryptoTextCipherOptions
|
|
} from "@/uni_modules/laoqianjunzi-crypto"
|
|
|
|
function runCryptoDemo(): void {
|
|
const runtime: CryptoRuntimeSnapshot = describeCryptoRuntime()
|
|
console.log("runtime", runtime.platformName, runtime.engineName)
|
|
|
|
const plainText = "Hello uni-app x"
|
|
const secretText = "1234567890abcdef"
|
|
const ivText = "fedcba0987654321"
|
|
|
|
const base64Text = encodeText("base64", plainText)
|
|
const restoreText = decodeText("base64", base64Text)
|
|
console.log("base64", base64Text)
|
|
console.log("restore", restoreText)
|
|
|
|
const sha256Text = digestText("sha256", plainText)
|
|
const hmacText = signText("sha256", "sign-key", plainText)
|
|
console.log("sha256", sha256Text)
|
|
console.log("hmac", hmacText)
|
|
|
|
const aesOptions: CryptoTextCipherOptions = defaultTextCipherOptions()
|
|
aesOptions.mode = "CBC"
|
|
aesOptions.padding = "PKCS7"
|
|
aesOptions.ivText = ivText
|
|
aesOptions.keyLength = 16
|
|
|
|
const aesCipherText = aesEncryptText(secretText, plainText, aesOptions)
|
|
const aesPlainText = aesDecryptText(secretText, aesCipherText, aesOptions)
|
|
console.log("aes cipher", aesCipherText)
|
|
console.log("aes plain", aesPlainText)
|
|
|
|
const rsaPair: CryptoRsaPair = createRsaPair(2048)
|
|
const rsaCipherText = rsaEncryptText(rsaPair.publicKey, plainText, "base64")
|
|
const rsaPlainText = rsaDecryptText(rsaPair.privateKey, rsaCipherText, "base64")
|
|
console.log("rsa plain", rsaPlainText)
|
|
}
|
|
```
|
|
|
|
## AES 字节数组示例
|
|
|
|
如果你的业务处理的是二进制数据,而不是普通字符串,建议使用字节接口:
|
|
|
|
```uts
|
|
import {
|
|
aesDecryptBytes,
|
|
aesEncryptBytes,
|
|
defaultByteCipherOptions
|
|
} from "@/uni_modules/laoqianjunzi-crypto"
|
|
|
|
import type { CryptoByteCipherOptions } from "@/uni_modules/laoqianjunzi-crypto"
|
|
|
|
function textToBytes(input: string): Uint8Array {
|
|
const output = new Uint8Array(input.length)
|
|
let index = 0
|
|
while (index < input.length) {
|
|
const code = input.charCodeAt(index)
|
|
output[index] = code == null ? 0 : code & 0xff
|
|
index += 1
|
|
}
|
|
return output
|
|
}
|
|
|
|
function bytesToText(input: Uint8Array): string {
|
|
let output = ""
|
|
let index = 0
|
|
while (index < input.length) {
|
|
output += String.fromCharCode(input[index])
|
|
index += 1
|
|
}
|
|
return output
|
|
}
|
|
|
|
function runByteCipherDemo(): void {
|
|
const options: CryptoByteCipherOptions = defaultByteCipherOptions()
|
|
options.mode = "CTR"
|
|
options.padding = "PKCS7"
|
|
options.keyLength = 16
|
|
|
|
const secretBytes = textToBytes("1234567890abcdef")
|
|
const plainBytes = textToBytes("hello-bytes")
|
|
|
|
const cipherBytes = aesEncryptBytes(secretBytes, plainBytes, options)
|
|
const restoreBytes = aesDecryptBytes(secretBytes, cipherBytes, options)
|
|
console.log("byte plain", bytesToText(restoreBytes))
|
|
console.log("cipher length", cipherBytes.length)
|
|
}
|
|
```
|
|
|
|
## 对外类型
|
|
|
|
### CryptoDigestKind
|
|
|
|
摘要算法枚举:
|
|
|
|
- `md5`
|
|
- `sha1`
|
|
- `sha256`
|
|
- `sha512`
|
|
|
|
### CryptoMacKind
|
|
|
|
HMAC 算法枚举:
|
|
|
|
- `sha1`
|
|
- `sha256`
|
|
- `sha512`
|
|
|
|
### CryptoCodecKind
|
|
|
|
文本编解码枚举:
|
|
|
|
- `utf8`
|
|
- `hex`
|
|
- `base64`
|
|
- `base64url`
|
|
- `latin1`
|
|
- `utf16`
|
|
|
|
### CryptoBlockMode
|
|
|
|
分组模式枚举:
|
|
|
|
- `ECB`
|
|
- `CBC`
|
|
- `CFB`
|
|
- `CTR`
|
|
- `CTRGladman`
|
|
- `OFB`
|
|
|
|
### CryptoPaddingKind
|
|
|
|
填充模式枚举:
|
|
|
|
- `PKCS7`
|
|
- `ANSI_X923`
|
|
- `ISO_10126`
|
|
- `ISO_97971`
|
|
- `NONE`
|
|
- `ZERO`
|
|
|
|
### RsaOutputKind
|
|
|
|
RSA 密文输出格式:
|
|
|
|
- `base64`
|
|
- `hex`
|
|
|
|
### CryptoTextCipherOptions
|
|
|
|
AES 文本加解密参数:
|
|
|
|
| 字段 | 类型 | 必填 | 说明 |
|
|
| --- | --- | --- | --- |
|
|
| `mode` | `CryptoBlockMode` | 是 | 分组模式 |
|
|
| `padding` | `CryptoPaddingKind` | 是 | 填充模式 |
|
|
| `ivText` | `string \\| null` | 是 | 初始向量文本,`ECB` 模式可传 `null` |
|
|
| `keyLength` | `number \\| null` | 是 | AES 密钥长度,建议传 `16`、`24`、`32` |
|
|
|
|
### CryptoByteCipherOptions
|
|
|
|
AES 字节加解密参数:
|
|
|
|
| 字段 | 类型 | 必填 | 说明 |
|
|
| --- | --- | --- | --- |
|
|
| `mode` | `CryptoBlockMode` | 是 | 分组模式 |
|
|
| `padding` | `CryptoPaddingKind` | 是 | 填充模式 |
|
|
| `ivBytes` | `Uint8Array \\| null` | 是 | 初始向量字节数组,`ECB` 模式可传 `null` |
|
|
| `keyLength` | `number \\| null` | 是 | AES 密钥长度,建议传 `16`、`24`、`32` |
|
|
|
|
### CryptoTripleDesOptions
|
|
|
|
3DES 参数:
|
|
|
|
| 字段 | 类型 | 必填 | 说明 |
|
|
| --- | --- | --- | --- |
|
|
| `mode` | `"ECB" \\| "CBC"` | 是 | 3DES 当前支持的分组模式 |
|
|
| `ivText` | `string \\| null` | 是 | 初始向量文本,`ECB` 模式可传 `null` |
|
|
|
|
### CryptoDesOptions
|
|
|
|
DES 参数:
|
|
|
|
| 字段 | 类型 | 必填 | 说明 |
|
|
| --- | --- | --- | --- |
|
|
| `mode` | `CryptoBlockMode` | 是 | 分组模式 |
|
|
| `padding` | `CryptoPaddingKind` | 是 | 填充模式 |
|
|
| `ivText` | `string \\| null` | 是 | 初始向量文本,`ECB` 模式可传 `null` |
|
|
|
|
### CryptoRsaPair
|
|
|
|
RSA 密钥对对象:
|
|
|
|
| 字段 | 类型 | 必填 | 说明 |
|
|
| --- | --- | --- | --- |
|
|
| `publicKey` | `string` | 是 | 公钥 PEM 文本 |
|
|
| `privateKey` | `string` | 是 | 私钥 PEM 文本 |
|
|
|
|
### CryptoRuntimeSnapshot
|
|
|
|
运行时描述对象:
|
|
|
|
| 字段 | 类型 | 必填 | 说明 |
|
|
| --- | --- | --- | --- |
|
|
| `platformName` | `string` | 是 | 平台名称 |
|
|
| `engineName` | `string` | 是 | 当前底层实现名称 |
|
|
| `supportsAdvancedModes` | `boolean` | 是 | 是否支持高级分组模式 |
|
|
| `usesNativeBridge` | `boolean` | 是 | 是否经过原生桥接 |
|
|
|
|
## 默认参数函数
|
|
|
|
### defaultTextCipherOptions()
|
|
|
|
返回 AES 文本加解密默认参数:
|
|
|
|
| 字段 | 默认值 |
|
|
| --- | --- |
|
|
| `mode` | `CBC` |
|
|
| `padding` | `PKCS7` |
|
|
| `ivText` | `0123456789abcdef` |
|
|
| `keyLength` | `16` |
|
|
|
|
### defaultByteCipherOptions()
|
|
|
|
返回 AES 字节加解密默认参数:
|
|
|
|
| 字段 | 默认值 |
|
|
| --- | --- |
|
|
| `mode` | `CBC` |
|
|
| `padding` | `PKCS7` |
|
|
| `ivBytes` | `0123456789abcdef` 的 ASCII 字节 |
|
|
| `keyLength` | `16` |
|
|
|
|
### defaultTripleDesOptions()
|
|
|
|
返回 3DES 默认参数:
|
|
|
|
| 字段 | 默认值 |
|
|
| --- | --- |
|
|
| `mode` | `CBC` |
|
|
| `ivText` | `12345678` |
|
|
|
|
### defaultDesOptions()
|
|
|
|
返回 DES 默认参数:
|
|
|
|
| 字段 | 默认值 |
|
|
| --- | --- |
|
|
| `mode` | `CBC` |
|
|
| `padding` | `PKCS7` |
|
|
| `ivText` | `12345678` |
|
|
|
|
## 运行时信息函数
|
|
|
|
### describeCryptoRuntime()
|
|
|
|
返回当前平台的运行时信息:
|
|
|
|
```uts
|
|
const runtime = describeCryptoRuntime()
|
|
console.log(runtime.platformName)
|
|
console.log(runtime.engineName)
|
|
console.log(runtime.supportsAdvancedModes)
|
|
console.log(runtime.usesNativeBridge)
|
|
```
|
|
|
|
## API 清单
|
|
|
|
### 编解码
|
|
|
|
| 函数 | 说明 | 返回值 |
|
|
| --- | --- | --- |
|
|
| `encodeText(codec, plainText)` | 将普通文本编码为指定格式文本 | `string` |
|
|
| `decodeText(codec, encodedText)` | 将指定格式文本还原为普通文本 | `string` |
|
|
|
|
### 摘要与签名
|
|
|
|
| 函数 | 说明 | 返回值 |
|
|
| --- | --- | --- |
|
|
| `digestText(kind, plainText)` | 计算摘要,结果为十六进制字符串 | `string` |
|
|
| `signText(kind, secretText, plainText)` | 计算 HMAC,结果为十六进制字符串 | `string` |
|
|
|
|
### AES 文本加解密
|
|
|
|
| 函数 | 说明 | 返回值 |
|
|
| --- | --- | --- |
|
|
| `aesEncryptText(secretText, plainText, options)` | 使用文本密钥加密文本 | `string` |
|
|
| `aesDecryptText(secretText, cipherText, options)` | 使用文本密钥解密文本 | `string` |
|
|
|
|
### AES 字节加解密
|
|
|
|
| 函数 | 说明 | 返回值 |
|
|
| --- | --- | --- |
|
|
| `aesEncryptBytes(secretBytes, plainBytes, options)` | 使用字节密钥加密字节数组 | `Uint8Array` |
|
|
| `aesDecryptBytes(secretBytes, cipherBytes, options)` | 使用字节密钥解密字节数组 | `Uint8Array` |
|
|
|
|
### 3DES
|
|
|
|
| 函数 | 说明 | 返回值 |
|
|
| --- | --- | --- |
|
|
| `tripleDesEncryptText(secretText, plainText, options)` | 3DES 文本加密 | `string` |
|
|
| `tripleDesDecryptText(secretText, cipherText, options)` | 3DES 文本解密 | `string` |
|
|
|
|
### DES
|
|
|
|
| 函数 | 说明 | 返回值 |
|
|
| --- | --- | --- |
|
|
| `desEncryptText(secretText, plainText, options)` | DES 文本加密 | `string` |
|
|
| `desDecryptText(secretText, cipherText, options)` | DES 文本解密 | `string` |
|
|
|
|
### RC4
|
|
|
|
| 函数 | 说明 | 返回值 |
|
|
| --- | --- | --- |
|
|
| `rc4EncryptText(secretText, plainText)` | RC4 加密,返回十六进制密文 | `string` |
|
|
| `rc4DecryptText(secretText, cipherHexText)` | RC4 解密十六进制密文 | `string` |
|
|
|
|
### RSA
|
|
|
|
| 函数 | 说明 | 返回值 |
|
|
| --- | --- | --- |
|
|
| `createRsaPair(keySize)` | 生成 RSA 密钥对 | `CryptoRsaPair` |
|
|
| `rsaEncryptText(publicKey, plainText, outputKind)` | 使用公钥加密短文本 | `string` |
|
|
| `rsaDecryptText(privateKey, cipherText, outputKind)` | 使用私钥解密短文本 | `string` |
|
|
|
|
建议:
|
|
|
|
- `keySize` 推荐使用 `1024`、`2048`、`3072`、`4096`
|
|
- 一般业务默认建议使用 `2048`
|
|
|
|
## 使用建议
|
|
|
|
- 编解码、摘要、HMAC 建议直接使用字符串接口,返回值稳定、便于日志记录和接口传输
|
|
- 处理图片片段、协议报文、蓝牙包、文件块等二进制内容时,优先使用 `aesEncryptBytes` 与 `aesDecryptBytes`
|
|
- AES 跨端调用时,`keyLength` 建议固定传 `16`、`24`、`32` 之一,避免不同运行时对推断长度的理解差异
|
|
- 使用 `CBC`、`CFB`、`CTR`、`OFB` 等模式时,建议显式传入业务自定义 `ivText` 或 `ivBytes`
|
|
- `RSA` 更适合短文本、密钥交换或签名相关前置处理,不适合大体积正文直接加解密
|
|
- `RC4`、`DES`、`3DES` 更适用于兼容特定协议场景,新业务优先建议选择 `AES` 或 `RSA`
|
|
|
|
## 异常处理建议
|
|
|
|
参数不合法、密文格式不正确、密钥与向量不匹配时,接口可能抛出错误。业务代码建议统一使用 `try/catch` 包裹:
|
|
|
|
```uts
|
|
import {
|
|
aesEncryptText,
|
|
defaultTextCipherOptions
|
|
} from "@/uni_modules/laoqianjunzi-crypto"
|
|
|
|
try {
|
|
const options = defaultTextCipherOptions()
|
|
const cipherText = aesEncryptText("1234567890abcdef", "hello", options)
|
|
console.log(cipherText)
|
|
} catch (error) {
|
|
console.error("crypto error", error)
|
|
}
|
|
```
|
|
|
|
## 注意事项
|
|
|
|
- 本插件面向 `uni-app x`,不面向传统 `uni-app` 页面运行时
|
|
- 文本接口默认适合 UTF-8 文本场景;如果你的原始数据本身不是普通文本,请优先使用字节接口
|
|
- `ECB` 模式不依赖 IV,其余分组模式建议始终显式设置 IV
|
|
- RSA 密文输出格式由 `outputKind` 控制,发送方与接收方应保持一致
|
|
- 通过 `default*Options()` 获取参数对象后,可按当前业务需求覆盖默认值
|
|
|
|
## 示例页面
|
|
|
|
插件内已提供示例页面,可用于快速验证能力是否正常:
|
|
|
|
- `uni_modules/laoqianjunzi-crypto/pages/index`
|
|
|
|
如果项目已在 `pages.json` 中注册该页面,可直接运行到对应页面进行体验。
|