实现数据加密传输,成功调试登录接口

This commit is contained in:
2026-06-07 17:01:41 +08:00
parent aebd264d91
commit 895363305e
9 changed files with 596 additions and 56 deletions
+3 -2
View File
@@ -18,6 +18,7 @@ export class LoginApi {
clientId: Config.VITE_APP_CLIENT_ID,
grantType: 'password'
}
// 请求参数处理
const Requestconfig = new RequestConfig()
Requestconfig.url = "/auth/login"
Requestconfig.headers!.isToken = false
@@ -25,14 +26,14 @@ export class LoginApi {
Requestconfig.headers!.repeatSubmit = false
Requestconfig.method = HttpMethod.POST
Requestconfig.data = configData
//发起请求
const res = await this.http.request<UTSJSONObject>(Requestconfig)
const data = res.data
console.log(data);
if (data == null) {
throw new Error("登陆失败")
}
// 手动转换 UTSJSONObject 到 VerifyCodeResult
// 格式化返回数据 手动转换 UTSJSONObject 到 VerifyCodeResult
const result : LoginResult = {
access_token: data["access_token"] as string
}
+3 -3
View File
@@ -9,10 +9,10 @@ export class Config {
// 接口加密功能开关(如需关闭 后端也必须对应关闭)
static readonly VITE_APP_ENCRYPT = false
// 接口加密传输 RSA 公钥与后端解密私钥对应 如更换需前后端一同更换
static readonly VITE_APP_ENCRYPT = true
// 接口加密传输 RSA 公钥与后端解密私钥对应 如更换需前后端一同更换 公钥
static readonly VITE_APP_RSA_PUBLIC_KEY = 'MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDvEDuRIOM3oZPWj9Ukoc5pQklR4PFH6/clnjeFqjDLIgDyQvjxhgqAZQA+E9eD6qu6FsXPmK8djcL+nh3cFHz4pX473jDvO3Sve+8yL3VRQ0n2pRgQ2a01MJsy+WwTZCBYWf0VnLRIvANUoWQgy9vz94q7Va44dg7A1/3ICf+xAwIDAQAB'
// 接口响应解密 RSA 私钥与后端加密公钥对应 如更换需前后端一同更换
// 接口响应解密 RSA 私钥与后端加密公钥对应 如更换需前后端一同更换 私钥
static readonly VITE_APP_RSA_PRIVATE_KEY = 'MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAObq7yrxfvyieZtTjAYyrdvi59tYTXxjO5ajmPCRSXBY9M9wQ1tli297JN6mnY53UJMNyOFNSZVi8WSFoIXjpR87FmvChJlzeN/dZdd3SEs48Ee66XKeSePYqxa8oO5GKDsnajgpsOHKXSeeVSIysiIPS2/WsEqk0In9P4w3RsRFAgMBAAECgYBiMEWwce24SPICnRzuScBpvmsudrbEDIH7BOd0a6LZlcnLJwZNJ7mJlshPsHNQb+WgEf135+BBGEhioPtn0yuTdEuKP4kB9UdYUKiayWCoWhJpesv7sAD4RDClV7dhuV+gcd1AXD+YzyRIPbGm0VC2U+4q8/+UPRpVjqskbLVTgQJBAPRpou7g3S8n4XB527kq0D8I3+ZYwMxZhszwhrCDpJU319+ucmpLVwYIzDmZVeID2QQdUaDfIEViFHu95xDrGiUCQQDx3YOKn3yaEctk/ERVn7hDAyAXUbd8/pv2b24/M/l1ZevlsFem8U4Jk5Mu64t3z3YGJoymEjQmbucwT01iKhehAkEAxlnccsRmfFh/KkqauKE4M4++NTAd9zlInpUsmZ+cN8UEGnF2RTEzRKBrLOt1uWCqBB7PGiE6DVTVjr7FAQPrSQJAT5yeY87DcONSk9cFlzmPqV8p/QME5rvYEnHzVBKDlkUKNPyqnWToTvaoh9U4fyNmsfeWbEOprszqhFhWHG3GgQJAK8+ynmyFhaw63+Hx2KU5zR4hVuQso2IzrEurGxCxybV6mR7VBerb4502+EPx3PmOgxQL+niUFhcMWxcvBFP9+A=='
+6
View File
@@ -11,6 +11,12 @@
"style": {
"navigationBarTitleText": "登录"
}
},
{
"path": "pages/test/index",
"style": {
"navigationBarTitleText": "加解密测试"
}
}
],
"globalStyle": {
+1 -1
View File
@@ -79,7 +79,7 @@
})
}
} catch (e) {
console.error('登录失败:', e)
console.error('登录失败:'+ e.message)
loadCode()
}
}
+9
View File
@@ -3,6 +3,7 @@
<image class="logo" src="/static/logo.png"></image>
<text class="title">{{title}}</text>
<button @click="goLogin()">去登陆</button>
<button @click="goLogin1()">加解密测试</button>
需要一个导航栏
</view>
</template>
@@ -18,6 +19,14 @@
})
}
function goLogin1() {
uni.navigateTo({
url: '/pages/test/index'
})
}
</script>
<style>
+522
View File
@@ -0,0 +1,522 @@
<template>
<!-- #ifdef APP -->
<scroll-view class="crypto-scroll">
<!-- #endif -->
<view class="crypto-page">
<view class="hero-panel">
<text class="hero-kicker">LAOQIANJUNZI-CRYPTO</text>
<text class="hero-title">统一加密能力演示</text>
<text class="hero-desc">这一页直接调用插件导出的新接口,集中演示编码、摘要、HMAC、AES、3DES、RC4、RSA 与字节数组加解密。</text>
</view>
<view class="card-block runtime-card">
<text class="card-title">运行时概览</text>
<view class="status-row">
<text class="status-label">平台</text>
<text class="status-value">{{ runtimeInfo.platformName }}</text>
</view>
<view class="status-row">
<text class="status-label">引擎</text>
<text class="status-value">{{ runtimeInfo.engineName }}</text>
</view>
<view class="status-row">
<text class="status-label">高级模式</text>
<text class="status-value">{{ runtimeInfo.supportsAdvancedModes ? '已启用' : '受限' }}</text>
</view>
<view class="status-row">
<text class="status-label">原生桥接</text>
<text class="status-value">{{ runtimeInfo.usesNativeBridge ? '是' : '否' }}</text>
</view>
</view>
<view class="card-block form-card">
<text class="card-title">输入参数</text>
<view class="field-group">
<text class="field-label">明文</text>
<input class="field-input" v-model="plainText" />
</view>
<view class="field-group">
<text class="field-label">主密钥</text>
<input class="field-input" v-model="secretText" />
</view>
<view class="field-group">
<text class="field-label">向量</text>
<input class="field-input" v-model="ivText" />
</view>
<view class="field-group">
<text class="field-label">HMAC 密钥</text>
<input class="field-input" v-model="macSecretText" />
</view>
<view class="field-group">
<text class="field-label">3DES 密钥</text>
<input class="field-input" v-model="legacySecretText" />
</view>
<view class="field-group">
<text class="field-label">RSA 位数</text>
<input class="field-input" type="number" v-model="rsaBitsText" />
</view>
</view>
<view class="action-grid">
<button class="action-button action-strong" @click="runAllDemos">运行全部示例</button>
<button class="action-button" @click="runCodecDemo">编码</button>
<button class="action-button" @click="runDigestDemo">摘要/HMAC</button>
<button class="action-button" @click="runAesDemo">AES 文本</button>
<button class="action-button" @click="runByteDemo">AES 字节</button>
<button class="action-button" @click="runLegacyDemo">3DES/RC4</button>
<button class="action-button" @click="runRsaDemo">RSA</button>
<button class="action-button" @click="runCompatDemo">兼容 API</button>
<button class="action-button action-warn" @click="clearResults">清空结果</button>
</view>
<view class="result-grid">
<view class="card-block result-card">
<text class="card-title">编码</text>
<text class="result-line">Base64: {{ codecBase64 }}</text>
<text class="result-line">Hex: {{ codecHex }}</text>
<text class="result-line">Base64url: {{ codecBase64url }}</text>
<text class="result-line">反解: {{ codecBackText }}</text>
</view>
<view class="card-block result-card">
<text class="card-title">摘要与签名</text>
<text class="result-line">MD5: {{ md5Text }}</text>
<text class="result-line">SHA256: {{ sha256Text }}</text>
<text class="result-line">SHA512: {{ sha512Text }}</text>
<text class="result-line">HMAC-SHA256: {{ hmacText }}</text>
</view>
<view class="card-block result-card">
<text class="card-title">AES 文本</text>
<text class="result-line">密文: {{ aesCipherText }}</text>
<text class="result-line">解密: {{ aesPlainText }}</text>
</view>
<view class="card-block result-card">
<text class="card-title">AES 字节</text>
<text class="result-line">字节密文: {{ aesByteCipherHex }}</text>
<text class="result-line">字节解密: {{ aesBytePlainText }}</text>
</view>
<view class="card-block result-card">
<text class="card-title">3DES 与 RC4</text>
<text class="result-line">3DES 密文: {{ tripleCipherText }}</text>
<text class="result-line">3DES 解密: {{ triplePlainText }}</text>
<text class="result-line">RC4 密文: {{ rc4CipherHex }}</text>
<text class="result-line">RC4 解密: {{ rc4PlainText }}</text>
</view>
<view class="card-block result-card">
<text class="card-title">RSA</text>
<text class="result-line">公钥长度: {{ rsaPublicBrief }}</text>
<text class="result-line">私钥长度: {{ rsaPrivateBrief }}</text>
<text class="result-line">RSA 密文: {{ rsaCipherText }}</text>
<text class="result-line">RSA 解密: {{ rsaPlainText }}</text>
</view>
</view>
<view class="card-block log-card">
<text class="card-title">执行日志</text>
<view class="log-list">
<text class="log-line" v-for="(item,index) in logLines" :key="index">{{ item }}</text>
</view>
</view>
</view>
<!-- #ifdef APP -->
</scroll-view>
<!-- #endif -->
</template>
<script setup lang="uts">
import { aesDecrypt, aesDecryptBytes, aesDecryptText, aesEncrypt, aesEncryptBytes, aesEncryptText, base64Decode, base64Encode, createRsaPair, defaultByteCipherOptions, defaultTextCipherOptions, defaultTripleDesOptions, decodeText, describeCryptoRuntime, digestText, encodeText, generateRSAKeyPair, md5, rc4DecryptText, rc4EncryptText, rsaDecrypt, rsaDecryptText, rsaEncrypt, rsaEncryptText, signText, tripleDesDecryptText, tripleDesEncryptText, useCrypto } from '@/uni_modules/laoqianjunzi-crypto'
import type { CryptoRuntimeSnapshot } from '@/uni_modules/laoqianjunzi-crypto'
const runtimeInfo = ref(describeCryptoRuntime() as CryptoRuntimeSnapshot)
const plainText = ref('Hello laoqianjunzi-crypto')
const secretText = ref('1234567890abcdef')
const ivText = ref('fedcba0987654321')
const macSecretText = ref('signing-key')
const legacySecretText = ref('1234567890abcdef12345678')
const rsaBitsText = ref('2048')
const codecBase64 = ref('')
const codecHex = ref('')
const codecBase64url = ref('')
const codecBackText = ref('')
const md5Text = ref('')
const sha256Text = ref('')
const sha512Text = ref('')
const hmacText = ref('')
const aesCipherText = ref('')
const aesPlainText = ref('')
const aesByteCipherHex = ref('')
const aesBytePlainText = ref('')
const tripleCipherText = ref('')
const triplePlainText = ref('')
const rc4CipherHex = ref('')
const rc4PlainText = ref('')
const rsaCipherText = ref('')
const rsaPlainText = ref('')
const rsaPublicBrief = ref('')
const rsaPrivateBrief = ref('')
const logLines = ref(['等待执行示例'] as string[])
function appendLog(message : string) : void {
const stamp = new Date().toISOString()
logLines.value.unshift(stamp + ' ' + message)
if (logLines.value.length > 20) {
logLines.value.splice(20)
}
}
function bytesToHex(input : Uint8Array) : string {
let output = ''
let index = 0
while (index < input.length) {
let part = input[index].toString(16)
if (part.length < 2) {
part = '0' + part
}
output += part
index += 1
}
return output
}
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 currentRsaBits() : number {
const parsed = parseInt(rsaBitsText.value)
if (parsed == 1024 || parsed == 2048 || parsed == 3072 || parsed == 4096) {
return parsed
}
return 2048
}
function runCodecDemo() : void {
codecBase64.value = encodeText('base64', plainText.value)
codecHex.value = encodeText('hex', plainText.value)
codecBase64url.value = encodeText('base64url', plainText.value)
codecBackText.value = decodeText('base64', codecBase64.value)
appendLog('编码能力已完成')
}
function runDigestDemo() : void {
md5Text.value = digestText('md5', plainText.value)
sha256Text.value = digestText('sha256', plainText.value)
sha512Text.value = digestText('sha512', plainText.value)
hmacText.value = signText('sha256', macSecretText.value, plainText.value)
appendLog('摘要与 HMAC 已完成')
}
function runAesDemo() : void {
const options = defaultTextCipherOptions()
options.mode = 'CBC'
options.padding = 'PKCS7'
options.ivText = ivText.value
options.keyLength = 128
aesCipherText.value = aesEncryptText(secretText.value, plainText.value, options)
aesPlainText.value = aesDecryptText(secretText.value, aesCipherText.value, options)
appendLog('AES 文本加解密已完成')
}
function runByteDemo() : void {
const options = defaultByteCipherOptions()
options.mode = 'CTR'
options.padding = 'PKCS7'
options.keyLength = 128
const secretBytes = textToBytes(secretText.value)
const plainBytes = textToBytes(plainText.value)
const cipherBytes = aesEncryptBytes(secretBytes, plainBytes, options)
const restoreBytes = aesDecryptBytes(secretBytes, cipherBytes, options)
aesByteCipherHex.value = bytesToHex(cipherBytes)
aesBytePlainText.value = bytesToText(restoreBytes)
appendLog('AES 字节加解密已完成')
}
function runLegacyDemo() : void {
const options = defaultTripleDesOptions()
options.mode = 'CBC'
options.ivText = '12345678'
tripleCipherText.value = tripleDesEncryptText(legacySecretText.value, plainText.value, options)
triplePlainText.value = tripleDesDecryptText(legacySecretText.value, tripleCipherText.value, options)
rc4CipherHex.value = rc4EncryptText(macSecretText.value, plainText.value)
rc4PlainText.value = rc4DecryptText(macSecretText.value, rc4CipherHex.value)
appendLog('3DES 与 RC4 已完成')
}
function runRsaDemo() : void {
const pair = createRsaPair(currentRsaBits())
rsaPublicBrief.value = pair.publicKey.length + ' chars'
rsaPrivateBrief.value = pair.privateKey.length + ' chars'
rsaCipherText.value = rsaEncryptText(pair.publicKey, plainText.value, 'base64')
rsaPlainText.value = rsaDecryptText(pair.privateKey, rsaCipherText.value, 'base64')
console.log("ggggggggggggggggg"+pair.publicKey);
console.log("sssssssssssssssss"+pair.publicKey);
appendLog('RSA 生成与加解密已完成')
}
function runCompatDemo() : void {
const xBase64 = base64Encode(plainText.value)
const xPlain = base64Decode(xBase64)
const xMd5 = md5(plainText.value)
const xCipher = aesEncrypt(secretText.value, plainText.value, 'CBC', ivText.value, 16)
const xRestore = aesDecrypt(secretText.value, xCipher, 'CBC', ivText.value, 16)
const xPair = generateRSAKeyPair(currentRsaBits())
const xRsaText = rsaDecrypt(xPair.privateKey, rsaEncrypt(xPair.publicKey, plainText.value))
const crypto = useCrypto()
const limeIv = crypto.enc.Utf8.parse(ivText.value)
const limeCipher = crypto.AES.encrypt(plainText.value, secretText.value, {
iv: limeIv,
mode: crypto.mode.CBC,
padding: crypto.pad.Pkcs7
} as UTSJSONObject)
const limePlain = crypto.AES.decrypt(limeCipher.toString(), secretText.value, {
iv: limeIv,
mode: crypto.mode.CBC,
padding: crypto.pad.Pkcs7
} as UTSJSONObject).toString(crypto.enc.Utf8)
const limeRsa = crypto.RSA
const limePair = limeRsa.generateKeyPair()
limeRsa.setPublicKey(limePair.publicKey)
const limeCipherText = limeRsa.encrypt(plainText.value)
limeRsa.setPrivateKey(limePair.privateKey)
const limeRsaText = limeRsa.decrypt(limeCipherText)
appendLog('兼容 API 已完成:x-base64=' + xPlain.length + ' x-md5=' + xMd5.substring(0, 8) + ' x-aes=' + xRestore.length + ' x-rsa=' + xRsaText.length + ' lime-aes=' + limePlain.length + ' lime-rsa=' + limeRsaText.length)
}
function runAllDemos() : void {
try {
runCodecDemo()
runDigestDemo()
runAesDemo()
runByteDemo()
runLegacyDemo()
runRsaDemo()
runCompatDemo()
appendLog('全部能力演示执行结束')
} catch (error) {
appendLog('执行失败:' + (error as Error).message)
}
}
function clearResults() : void {
codecBase64.value = ''
codecHex.value = ''
codecBase64url.value = ''
codecBackText.value = ''
md5Text.value = ''
sha256Text.value = ''
sha512Text.value = ''
hmacText.value = ''
aesCipherText.value = ''
aesPlainText.value = ''
aesByteCipherHex.value = ''
aesBytePlainText.value = ''
tripleCipherText.value = ''
triplePlainText.value = ''
rc4CipherHex.value = ''
rc4PlainText.value = ''
rsaCipherText.value = ''
rsaPlainText.value = ''
rsaPublicBrief.value = ''
rsaPrivateBrief.value = ''
logLines.value = ['结果已清空'] as string[]
}
onMounted(() => {
appendLog('示例页已就绪,点击按钮即可执行')
})
</script>
<style>
.crypto-scroll {
flex: 1;
}
.crypto-page {
display: flex;
flex-direction: column;
padding: 48rpx;
background-color: #efe8dc;
}
.hero-panel {
display: flex;
flex-direction: column;
padding: 40rpx;
border-radius: 48rpx;
background-color: #11231c;
margin-bottom: 36rpx;
}
.hero-kicker {
color: #f2c169;
font-size: 26rpx;
letter-spacing: 4rpx;
margin-bottom: 12rpx;
}
.hero-title {
color: #fff8ea;
font-size: 56rpx;
font-weight: 700;
margin-bottom: 12rpx;
}
.hero-desc {
color: #c9d6cc;
font-size: 28rpx;
line-height: 40rpx;
}
.card-block {
display: flex;
flex-direction: column;
padding: 36rpx;
border-radius: 40rpx;
background-color: #fffaf1;
margin-bottom: 28rpx;
}
.card-title {
color: #24352e;
font-size: 36rpx;
font-weight: 700;
margin-bottom: 18rpx;
}
.runtime-card {
background-color: #f7f1e3;
}
.status-row {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
padding: 20rpx 0;
border-bottom-width: 2rpx;
border-bottom-style: solid;
border-bottom-color: #e7dbc8;
}
.status-label {
color: #6b6d66;
font-size: 26rpx;
}
.status-value {
color: #1c2b25;
font-size: 28rpx;
font-weight: 600;
}
.form-card {
background-color: #fff7ee;
}
.field-group {
display: flex;
flex-direction: column;
margin-bottom: 16rpx;
}
.field-label {
color: #6f6258;
font-size: 26rpx;
}
.field-input {
height: 84rpx;
padding: 0 24rpx;
border-radius: 24rpx;
background-color: #f1e7da;
color: #1d2823;
font-size: 28rpx;
}
.action-grid {
display: flex;
flex-direction: row;
flex-wrap: wrap;
margin-bottom: 28rpx;
}
.action-button {
min-width: 208rpx;
border-radius: 999rpx;
background-color: #d8e5db;
color: #20312a;
font-size: 26rpx;
margin-right: 20rpx;
margin-bottom: 20rpx;
}
.action-strong {
background-color: #17392d;
color: #fff8ef;
}
.action-warn {
background-color: #ead4b9;
color: #5d3722;
}
.result-grid {
display: flex;
flex-direction: column;
}
.result-card {
background-color: #fffdf8;
}
.result-line {
color: #25322c;
font-size: 26rpx;
line-height: 38rpx;
}
.log-card {
background-color: #15261f;
}
.log-list {
display: flex;
flex-direction: column;
}
.log-line {
color: #d6e7dc;
font-size: 24rpx;
line-height: 36rpx;
margin-bottom: 16rpx;
}
</style>
+26 -10
View File
@@ -3,6 +3,9 @@ import { Config } from "@/config.uts"
import { HttpMethod } from "@/enum/HttpMethod"
import { Auth } from "@/utils/Auth.uts"
import { XiaoZhi } from "@/utils/XiaoZhi"
import { Crypto } from "@/utils/crypto.uts"
import { base64Encode, createRsaPair, rsaEncryptText } from "@/uni_modules/laoqianjunzi-crypto"
/**
* HTTP请求客户端
@@ -19,6 +22,11 @@ export class HttpClient {
private static instance : HttpClient | null = null
private static encryptHeader = 'encrypt-key';
private static publicKey = '-----BEGIN PUBLIC KEY-----\n' +
Config.VITE_APP_RSA_PUBLIC_KEY +
'\n-----END PUBLIC KEY-----';
/**
* 获取单例实例
*/
@@ -38,7 +46,7 @@ export class HttpClient {
* @returns 标准响应对象
*/
async request<T>(config : RequestConfig) : Promise<ApiResponse<T>> {
console.log("请求拦截")
console.log("请求拦截,请求地址:" + config.url)
let url : string = Config.BASE_URL + config.url
let data = config.data ?? null
@@ -96,14 +104,28 @@ export class HttpClient {
*/
if (Config.VITE_APP_ENCRYPT) {
if (isEncrypt && (config.method === HttpMethod.POST || config.method === HttpMethod.PUT)) {
console.log("加密")
// AES密钥
const aesKey = Crypto.generateAesKey();
// Base64(AES_KEY)
const aesKeyBase64 = base64Encode(aesKey)
// RSA加密后的Header值
header[HttpClient.encryptHeader] = rsaEncryptText(HttpClient.publicKey, aesKeyBase64, 'base64')
console.log(header[HttpClient.encryptHeader]);
const requestData = config.data
if (requestData != null) {
data = Crypto.encryptWithAes(requestData, aesKey)
}
}
}
if (config.loading == true) {
LoadingManager.show()
}
console.log("请求拦截,请求地址:" + url)
try {
return await new Promise<ApiResponse<T>>((resolve, reject) => {
uni.request({
@@ -118,19 +140,13 @@ export class HttpClient {
enableChunked,
success: (res) => {
const responseData = res["data"] as UTSJSONObject
console.log(
"响应拦截-响应状态码:" +
JSON.stringify(responseData["code"])
)
const apiResponse = new ApiResponse<T>()
if (responseData != null) {
apiResponse.code = (responseData["code"] as number) ?? 0
apiResponse.msg = (responseData["msg"] as string) ?? ""
apiResponse.data = responseData["data"] as T
}
console.log("响应拦截-响应状态码:" + apiResponse.code)
resolve(apiResponse)
},
+21 -35
View File
@@ -1,55 +1,34 @@
import { createRsaPair, base64Decode, base64Encode, } from "@/uni_modules/laoqianjunzi-crypto";
// 在插件中,h5不会导出CryptoRsaPair,需要自定义,等待后续作者处理
// #ifdef H5
type CryptoRsaPair = {
publicKey : string;
privateKey : string;
}
// #endif
// #ifdef APP-ANDROID
import { CryptoRsaPair } from "@/uni_modules/laoqianjunzi-crypto";
// #endif
import { createRsaPair, base64Decode, base64Encode, defaultTextCipherOptions, aesEncryptText, } from "@/uni_modules/laoqianjunzi-crypto";
export class Crypto {
/**
* 随机生成32位的字符串
* @returns {string}
*/
static generateRandomString() : string {
const chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
let result = ""
for (let i = 0; i < 32; i++) {
result += chars.charAt(
Math.floor(
Math.random() * chars.length
)
)
}
return result;
static generateRandomString(length = 16) : string {
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
let result = ''
for (let i = 0; i < length; i++) {
result += chars.charAt(Math.floor(Math.random() * chars.length))
}
private static readonly rsaBitsText = ref('2048')
static currentRsaBits() : number {
const parsed = parseInt(Crypto.rsaBitsText.value)
if (parsed == 1024 || parsed == 2048 || parsed == 3072 || parsed == 4096) {
return parsed
}
return 2048
return result
}
/**
* 随机生成aes 密钥
* @returns {string}
*/
static generateAesKey() : CryptoRsaPair {
return createRsaPair(Crypto.currentRsaBits());
static generateAesKey() : string {
return Crypto.generateRandomString(16);
}
/**
* 加密base64
* @returns {string}
*/
static encryptBase64(str : CryptoRsaPair) : string {
return base64Encode(str.privateKey + str.publicKey);
static encryptBase64(str : string) : string {
return base64Encode(str);
}
/**
@@ -65,8 +44,15 @@ export class Crypto {
* @param aesKey
* @returns {string}
*/
static encryptWithAes() : string {
return '';
static encryptWithAes(data : any, aesKey : string) : string {
// AES配置
const options = defaultTextCipherOptions()
options.mode = 'ECB'
options.padding = 'PKCS7'
options.keyLength = 128
// 请求体JSON
const json = JSON.stringify(data)
return aesEncryptText(aesKey, json, options);
}
/**
+2 -2
View File
@@ -21,7 +21,7 @@ export class JSEncrypt {
* @returns Base64密文
*/
static encrypt(text : string) : string {
if (!text) {
if (text == "") {
return "";
}
return rsaEncryptText(JSEncrypt.PUBLIC_KEY, text, "base64");
@@ -34,7 +34,7 @@ export class JSEncrypt {
* @returns 明文
*/
static decrypt(cipherText : string) : string {
if (!cipherText) {
if (cipherText=="") {
return "";
}
return rsaDecryptText(JSEncrypt.PRIVATE_KEY, cipherText, "base64");