mirror of
http://112.124.100.131/ebiz-ai/ebiz-ai-knowledge-manage.git
synced 2025-12-12 12:26:52 +08:00
feat(encrypt): 实现 SM2 加密并集成到请求中-重写 encrypt.js为 sm2-utils.js,实现 SM2 加密功能- 添加 extractSm2RawPublicKey
This commit is contained in:
@@ -1,52 +1,107 @@
|
|||||||
//encrypt.js
|
// sm2-utils.js
|
||||||
|
import { sm2 } from 'sm-crypto'
|
||||||
|
|
||||||
|
// DER 编码的 SM2 公钥(hex)
|
||||||
|
const derPublicKeyHex =
|
||||||
|
'3059301306072a8648ce3d020106082a811ccf5501822d0342000463c7ed894e2e4a1c2de4adb8b71c2fa15409356e6851d2f965ddd0e09283044fabb3457bad5a0cbb689d2668309cdb96f987716f0f83125d6f7fa6b295ac0e1f'
|
||||||
|
|
||||||
|
// 缓存提取后的原始公钥
|
||||||
|
let cachedPublicKeyHex = null
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通过crypto-js实现 加解密工具
|
* 从 DER 编码的 SM2 公钥(hex)中提取原始未压缩公钥(04 开头)
|
||||||
* AES
|
* @param {string} derHex - DER 格式的公钥(十六进制字符串)
|
||||||
* @author: wmz
|
* @returns {string} 原始公钥 hex 字符串(04 开头,130位)
|
||||||
*/
|
*/
|
||||||
import CryptoJS from 'crypto-js'
|
function extractSm2RawPublicKey(derHex) {
|
||||||
const KP = {
|
if (cachedPublicKeyHex) {
|
||||||
key: 'AJDBW8D2zdDq3b5U', // 秘钥 16*n:
|
return cachedPublicKeyHex
|
||||||
iv: '' // 偏移量
|
}
|
||||||
|
|
||||||
|
let derBuffer
|
||||||
|
try {
|
||||||
|
derBuffer =
|
||||||
|
typeof Buffer !== 'undefined'
|
||||||
|
? Buffer.from(derHex, 'hex')
|
||||||
|
: new Uint8Array(derHex.match(/[\da-f]{2}/gi).map(h => parseInt(h, 16)))
|
||||||
|
} catch (error) {
|
||||||
|
throw new Error('公钥 hex 格式无效')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 查找 03 42 00 04 模式
|
||||||
|
const pattern = [0x03, 0x42, 0x00, 0x04]
|
||||||
|
let offset = -1
|
||||||
|
|
||||||
|
for (let i = 0; i < derBuffer.length - pattern.length; i++) {
|
||||||
|
if (
|
||||||
|
derBuffer[i] === pattern[0] &&
|
||||||
|
derBuffer[i + 1] === pattern[1] &&
|
||||||
|
derBuffer[i + 2] === pattern[2] &&
|
||||||
|
derBuffer[i + 3] === pattern[3]
|
||||||
|
) {
|
||||||
|
offset = i + 3 // 跳过 03 42 00 04
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (offset === -1) {
|
||||||
|
throw new Error('无法在 DER 中找到 SM2 公钥数据')
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提取 65 字节(04 + X + Y)
|
||||||
|
const publicKeyRaw = derBuffer.slice(offset, offset + 65)
|
||||||
|
|
||||||
|
// 转为 hex 字符串
|
||||||
|
const hex =
|
||||||
|
typeof Buffer !== 'undefined'
|
||||||
|
? publicKeyRaw.toString('hex')
|
||||||
|
: Array.from(publicKeyRaw)
|
||||||
|
.map(b => b.toString(16).padStart(2, '0'))
|
||||||
|
.join('')
|
||||||
|
|
||||||
|
cachedPublicKeyHex = hex
|
||||||
|
return hex
|
||||||
}
|
}
|
||||||
function getAesString(data, key, iv) {
|
|
||||||
// 加密
|
/**
|
||||||
key = CryptoJS.enc.Utf8.parse(key)
|
* SM2 加密函数(支持选择性加密)
|
||||||
iv = CryptoJS.enc.Utf8.parse(iv)
|
* @param {any} data - 待加密的数据(对象、数组、字符串等)
|
||||||
let encrypted = CryptoJS.AES.encrypt(data, key, {
|
* @param {string} url - 请求 URL,用于判断是否加密
|
||||||
// iv: iv,
|
* @returns {any|string} 加密后的 hex 字符串,或原数据(白名单路径)
|
||||||
mode: CryptoJS.mode.ECB,
|
*/
|
||||||
padding: CryptoJS.pad.Pkcs7
|
export function encrypt(data, url) {
|
||||||
})
|
// 白名单:/bpic/ta/* 路径不加密
|
||||||
return encrypted.toString() // 返回的是base64格式的密文
|
if (/^\/bpic\/ta\//.test(url)) {
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 准备明文(避免重复 stringify)
|
||||||
|
const plaintext = typeof data === 'string' ? data : JSON.stringify(data)
|
||||||
|
|
||||||
|
// 提取并缓存公钥
|
||||||
|
const publicKeyHex = extractSm2RawPublicKey(derPublicKeyHex)
|
||||||
|
|
||||||
|
// 执行加密
|
||||||
|
const ciphertext = sm2.doEncrypt(plaintext, publicKeyHex, {
|
||||||
|
cipherMode: 1 // 标准模式
|
||||||
|
})
|
||||||
|
|
||||||
|
console.log('[SM2加密] 明文:', plaintext)
|
||||||
|
console.log('[SM2密钥] 明文:', publicKeyHex)
|
||||||
|
console.log('[SM2加密] 密文:', ciphertext)
|
||||||
|
|
||||||
|
return ciphertext
|
||||||
|
} catch (error) {
|
||||||
|
console.error('[SM2加密失败]', error)
|
||||||
|
// 生产环境可选择抛出,或返回原数据 + 日志
|
||||||
|
throw new Error(`SM2加密失败: ${error.message}`)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
function getDAesString(encrypted, key, iv) {
|
|
||||||
// 解密
|
/**
|
||||||
key = CryptoJS.enc.Utf8.parse(key)
|
* 可选:导出公钥(用于调试)
|
||||||
iv = CryptoJS.enc.Utf8.parse(iv)
|
*/
|
||||||
let decrypted = CryptoJS.AES.decrypt(encrypted, key, {
|
export function getPublicKey() {
|
||||||
// iv: iv,
|
return extractSm2RawPublicKey(derPublicKeyHex)
|
||||||
mode: CryptoJS.mode.ECB,
|
|
||||||
padding: CryptoJS.pad.Pkcs7
|
|
||||||
})
|
|
||||||
return decrypted.toString(CryptoJS.enc.Utf8) //
|
|
||||||
}
|
}
|
||||||
// AES 对称秘钥加密
|
|
||||||
const aes = {
|
|
||||||
en: data => getAesString(data, KP.key, KP.iv),
|
|
||||||
de: data => getDAesString(data, KP.key, KP.iv)
|
|
||||||
}
|
|
||||||
// BASE64
|
|
||||||
const base64 = {
|
|
||||||
en: data => CryptoJS.enc.Base64.stringify(CryptoJS.enc.Utf8.parse(data)),
|
|
||||||
de: data => CryptoJS.enc.Base64.parse(data).toString(CryptoJS.enc.Utf8)
|
|
||||||
}
|
|
||||||
// SHA256
|
|
||||||
const sha256 = data => {
|
|
||||||
return CryptoJS.SHA256(data).toString()
|
|
||||||
}
|
|
||||||
// MD5
|
|
||||||
const md5 = data => {
|
|
||||||
return CryptoJS.MD5(data).toString()
|
|
||||||
}
|
|
||||||
export { aes, md5, sha256, base64 }
|
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import router from '@/router'
|
|||||||
import { sm2 } from 'sm-crypto'
|
import { sm2 } from 'sm-crypto'
|
||||||
import { logger } from 'runjs/lib/common'
|
import { logger } from 'runjs/lib/common'
|
||||||
|
|
||||||
|
import { encrypt } from '@/assets/js/utils/encrypt'
|
||||||
|
|
||||||
// create an axios instance
|
// create an axios instance
|
||||||
const service = axios.create({
|
const service = axios.create({
|
||||||
baseURL: '', // url = base url + request url
|
baseURL: '', // url = base url + request url
|
||||||
@@ -97,7 +99,9 @@ service.interceptors.request.use(
|
|||||||
if (config.data) {
|
if (config.data) {
|
||||||
// 保存原始数据用于调试
|
// 保存原始数据用于调试
|
||||||
config.originalData = config.data
|
config.originalData = config.data
|
||||||
config.data = encryptData(config.data)
|
// config.data = encryptData(config.data)
|
||||||
|
config.data = encrypt(config.data, config.url)
|
||||||
|
|
||||||
console.log('config', config)
|
console.log('config', config)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user