Browse Source

前端加密修改为sm2和sm4

ai_dev
zhouhaibin 5 months ago
parent
commit
e94375a587
  1. 9
      .env.development
  2. 6
      .env.production
  3. 3
      package.json
  4. 91
      src/utils/encryption/crypto.ts
  5. 66
      src/utils/encryption/jsencrypt.ts
  6. 14
      src/utils/http/axios/index.ts

9
.env.development

@ -8,9 +8,14 @@ VITE_GLOB_API_URL=/basic-api
VITE_GLOB_ENABLE_ENCRYPT=true
# VITE_APP_ENCRYPT=true
# RSA公钥 请求加密使用 注意这两个是两对RSA公私钥 请求加密-后端解密是一对 响应解密-后端加密是一对
VITE_GLOB_RSA_PUBLIC_KEY=MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdHnzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ==
# VITE_GLOB_RSA_PUBLIC_KEY=MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdHnzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ==
VITE_GLOB_RSA_PUBLIC_KEY=04236db2b9ce493053523b486590c435da3a957a7b25adde32f1bb42a5e7c4675c28ca3cf556b4e9014e220cb5faaf5f309950c9e172f0886674df23cc70bd4d76
# RSA私钥 响应解密使用 注意这两个是两对RSA公私钥 请求加密-后端解密是一对 响应解密-后端加密是一对
VITE_GLOB_RSA_PRIVATE_KEY=MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAmc3CuPiGL/LcIIm7zryCEIbl1SPzBkr75E2VMtxegyZ1lYRD+7TZGAPkvIsBcaMs6Nsy0L78n2qh+lIZMpLH8wIDAQABAkEAk82Mhz0tlv6IVCyIcw/s3f0E+WLmtPFyR9/WtV3Y5aaejUkU60JpX4m5xNR2VaqOLTZAYjW8Wy0aXr3zYIhhQQIhAMfqR9oFdYw1J9SsNc+CrhugAvKTi0+BF6VoL6psWhvbAiEAxPPNTmrkmrXwdm/pQQu3UOQmc2vCZ5tiKpW10CgJi8kCIFGkL6utxw93Ncj4exE/gPLvKcT+1Emnoox+O9kRXss5AiAMtYLJDaLEzPrAWcZeeSgSIzbL+ecokmFKSDDcRske6QIgSMkHedwND1olF8vlKsJUGK3BcdtM8w4Xq7BpSBwsloE=
# VITE_GLOB_RSA_PRIVATE_KEY=MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAmc3CuPiGL/LcIIm7zryCEIbl1SPzBkr75E2VMtxegyZ1lYRD+7TZGAPkvIsBcaMs6Nsy0L78n2qh+lIZMpLH8wIDAQABAkEAk82Mhz0tlv6IVCyIcw/s3f0E+WLmtPFyR9/WtV3Y5aaejUkU60JpX4m5xNR2VaqOLTZAYjW8Wy0aXr3zYIhhQQIhAMfqR9oFdYw1J9SsNc+CrhugAvKTi0+BF6VoL6psWhvbAiEAxPPNTmrkmrXwdm/pQQu3UOQmc2vCZ5tiKpW10CgJi8kCIFGkL6utxw93Ncj4exE/gPLvKcT+1Emnoox+O9kRXss5AiAMtYLJDaLEzPrAWcZeeSgSIzbL+ecokmFKSDDcRske6QIgSMkHedwND1olF8vlKsJUGK3BcdtM8w4Xq7BpSBwsloE=
VITE_GLOB_RSA_PRIVATE_KEY=00ac220685ceb41f06153a459c43248695f9f81188f5835c1e6f40abb1a748ab2c
# 客户端id
VITE_GLOB_APP_CLIENT_ID=e5cd7e4891bf95d1d19206ce24a7b32e

6
.env.production

@ -15,10 +15,12 @@ VITE_GLOB_API_URL=/prod-api
VITE_GLOB_ENABLE_ENCRYPT=true
# RSA公钥 请求加密使用 注意这两个是两对RSA公私钥 请求加密-后端解密是一对 响应解密-后端加密是一对
VITE_GLOB_RSA_PUBLIC_KEY=MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdHnzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ==
# VITE_GLOB_RSA_PUBLIC_KEY=MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKoR8mX0rGKLqzcWmOzbfj64K8ZIgOdHnzkXSOVOZbFu/TJhZ7rFAN+eaGkl3C4buccQd/EjEsj9ir7ijT7h96MCAwEAAQ==
VITE_GLOB_RSA_PUBLIC_KEY=VITE_GLOB_RSA_PUBLIC_KEY=04236db2b9ce493053523b486590c435da3a957a7b25adde32f1bb42a5e7c4675c28ca3cf556b4e9014e220cb5faaf5f309950c9e172f0886674df23cc70bd4d76
# RSA私钥 响应解密使用 注意这两个是两对RSA公私钥 请求加密-后端解密是一对 响应解密-后端加密是一对
VITE_GLOB_RSA_PRIVATE_KEY=MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAmc3CuPiGL/LcIIm7zryCEIbl1SPzBkr75E2VMtxegyZ1lYRD+7TZGAPkvIsBcaMs6Nsy0L78n2qh+lIZMpLH8wIDAQABAkEAk82Mhz0tlv6IVCyIcw/s3f0E+WLmtPFyR9/WtV3Y5aaejUkU60JpX4m5xNR2VaqOLTZAYjW8Wy0aXr3zYIhhQQIhAMfqR9oFdYw1J9SsNc+CrhugAvKTi0+BF6VoL6psWhvbAiEAxPPNTmrkmrXwdm/pQQu3UOQmc2vCZ5tiKpW10CgJi8kCIFGkL6utxw93Ncj4exE/gPLvKcT+1Emnoox+O9kRXss5AiAMtYLJDaLEzPrAWcZeeSgSIzbL+ecokmFKSDDcRske6QIgSMkHedwND1olF8vlKsJUGK3BcdtM8w4Xq7BpSBwsloE=
# VITE_GLOB_RSA_PRIVATE_KEY=MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEAmc3CuPiGL/LcIIm7zryCEIbl1SPzBkr75E2VMtxegyZ1lYRD+7TZGAPkvIsBcaMs6Nsy0L78n2qh+lIZMpLH8wIDAQABAkEAk82Mhz0tlv6IVCyIcw/s3f0E+WLmtPFyR9/WtV3Y5aaejUkU60JpX4m5xNR2VaqOLTZAYjW8Wy0aXr3zYIhhQQIhAMfqR9oFdYw1J9SsNc+CrhugAvKTi0+BF6VoL6psWhvbAiEAxPPNTmrkmrXwdm/pQQu3UOQmc2vCZ5tiKpW10CgJi8kCIFGkL6utxw93Ncj4exE/gPLvKcT+1Emnoox+O9kRXss5AiAMtYLJDaLEzPrAWcZeeSgSIzbL+ecokmFKSDDcRske6QIgSMkHedwND1olF8vlKsJUGK3BcdtM8w4Xq7BpSBwsloE=
VITE_GLOB_RSA_PRIVATE_KEY=00ac220685ceb41f06153a459c43248695f9f81188f5835c1e6f40abb1a748ab2c
# 客户端id
VITE_GLOB_APP_CLIENT_ID=e5cd7e4891bf95d1d19206ce24a7b32e

3
package.json

@ -118,7 +118,8 @@
"vxe-table": "4.6.17",
"vxe-table-plugin-export-xlsx": "4.0.1",
"xe-utils": "3.5.25",
"xlsx": "0.18.5"
"xlsx": "0.18.5",
"sm-crypto":"0.3.13"
},
"devDependencies": {
"@commitlint/cli": "19.3.0",

91
src/utils/encryption/crypto.ts

@ -1,8 +1,9 @@
import CryptoJS from 'crypto-js';
import {sm4} from 'sm-crypto'
function randomUUID() {
const chars = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'.split('');
const uuid = new Array(36);
const uuid = new Array(32);
let rnd = 0;
let r: number;
for (let i = 0; i < 36; i++) {
@ -20,12 +21,68 @@ function randomUUID() {
return uuid.join('').replace(/-/gm, '').toLowerCase();
}
// /**
// * 随机生成aes 密钥
// * @returns
// */
// export function generateAesKey() {
// return CryptoJS.enc.Utf8.parse(randomUUID());
// }
// /**
// * base64编码
// * @param str
// * @returns
// */
// export function encryptBase64(str: CryptoJS.lib.WordArray) {
// return CryptoJS.enc.Base64.stringify(str);
// }
// /**
// * 使用公钥加密
// * @param message 加密内容
// * @param aesKey aesKey
// * @returns
// */
// export function encryptWithAes(message: string, aesKey: CryptoJS.lib.WordArray) {
// const encrypted = CryptoJS.AES.encrypt(message, aesKey, {
// mode: CryptoJS.mode.ECB,
// padding: CryptoJS.pad.Pkcs7,
// });
// return encrypted.toString();
// }
// /**
// * 解密base64
// */
// export function decryptBase64(str: string) {
// return CryptoJS.enc.Base64.parse(str);
// }
// /**
// * 使用密钥对数据进行解密
// */
// export function decryptWithAes(message: string, aesKey: CryptoJS.lib.WordArray) {
// const decrypted = CryptoJS.AES.decrypt(message, aesKey, {
// mode: CryptoJS.mode.ECB,
// padding: CryptoJS.pad.Pkcs7,
// });
// return decrypted.toString(CryptoJS.enc.Utf8);
// }
/**
* aes
* @returns
*/
export function generateAesKey() {
return CryptoJS.enc.Utf8.parse(randomUUID());
export function generateSM4Key() {
// return CryptoJS.enc.Utf8.parse(randomUUID());
//获取前16位作为密钥
return randomUUID();
}
/**
@ -33,7 +90,7 @@ export function generateAesKey() {
* @param str
* @returns
*/
export function encryptBase64(str: CryptoJS.lib.WordArray) {
export function encryptBase64(str) {
return CryptoJS.enc.Base64.stringify(str);
}
@ -43,12 +100,13 @@ export function encryptBase64(str: CryptoJS.lib.WordArray) {
* @param aesKey aesKey
* @returns
*/
export function encryptWithAes(message: string, aesKey: CryptoJS.lib.WordArray) {
const encrypted = CryptoJS.AES.encrypt(message, aesKey, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7,
});
return encrypted.toString();
export function encryptWithAes(message: string, aesKey) {
// const encrypted = CryptoJS.AES.encrypt(message, aesKey, {
// mode: CryptoJS.mode.ECB,
// padding: CryptoJS.pad.Pkcs7,
// });
// return encrypted.toString();
return sm4.encrypt(message, aesKey)
}
/**
@ -61,10 +119,11 @@ export function decryptBase64(str: string) {
/**
* 使
*/
export function decryptWithAes(message: string, aesKey: CryptoJS.lib.WordArray) {
const decrypted = CryptoJS.AES.decrypt(message, aesKey, {
mode: CryptoJS.mode.ECB,
padding: CryptoJS.pad.Pkcs7,
});
return decrypted.toString(CryptoJS.enc.Utf8);
export function decryptWithAes(message: string, aesKey) {
// const decrypted = CryptoJS.AES.decrypt(message, aesKey, {
// mode: CryptoJS.mode.ECB,
// padding: CryptoJS.pad.Pkcs7,
// });
// return decrypted.toString(CryptoJS.enc.Utf8);
return sm4.decrypt(message, aesKey)
}

66
src/utils/encryption/jsencrypt.ts

@ -2,6 +2,7 @@ import JSEncrypt from 'jsencrypt';
// 密钥对生成 http://web.chacuo.net/netrsakeypair
import { useGlobSetting } from '@/hooks/setting';
import {sm2} from 'sm-crypto'
const globSetting = useGlobSetting();
const publicKey = globSetting.rsaPublicKey;
@ -9,24 +10,59 @@ const publicKey = globSetting.rsaPublicKey;
/** ??? 意义何在 */
const privateKey = globSetting.rsaPrivateKey;
// /**
// * RSA加密
// * @param txt 需要加密的数据
// * @returns
// */
// export function encrypt(txt: string) {
// const instance = new JSEncrypt();
// instance.setPublicKey(publicKey);
// return instance.encrypt(txt);
// }
// /**
// * RSA解密
// * @param txt 需要解密的数据
// * @returns
// */
// export function decrypt(txt: string) {
// const instance = new JSEncrypt();
// instance.setPrivateKey(privateKey);
// return instance.decrypt(txt);
// }
/**
*
* @param txt
* @returns
* SM2公钥加密
* @param message
* @param publicKey (04)
* @returns
*/
export function encrypt(txt: string) {
const instance = new JSEncrypt();
instance.setPublicKey(publicKey);
return instance.encrypt(txt);
export function encrypt(message: string) {
try {
const cipherData = sm2.doEncrypt(message, publicKey,1);
return cipherData;
} catch (error) {
throw new Error('SM2加密失败: ' + error.message);
}
}
/**
*
* @param txt
* @returns
* SM2私钥解密
* @param ciphertext
* @param privateKey
* @returns
*/
export function decrypt(txt: string) {
const instance = new JSEncrypt();
instance.setPrivateKey(privateKey);
return instance.decrypt(txt);
}
export function decrypt(ciphertext: string) {
try {
//去掉密文的开头的04
const ciphertextHex = ciphertext.slice(2);
const decrypted = sm2.doDecrypt(ciphertextHex, privateKey,1);
return decrypted;
} catch (error) {
throw new Error('SM2解密失败: ' + error.message);
}
}

14
src/utils/http/axios/index.ts

@ -20,7 +20,7 @@ import { useUserStoreWithOut } from '@/store/modules/user';
import { AxiosRetry } from '@/utils/http/axios/axiosRetry';
import axios from 'axios';
import {
generateAesKey,
generateSM4Key,
encryptBase64,
encryptWithAes,
decryptBase64,
@ -29,6 +29,7 @@ import {
import * as encryptUtil from '@/utils/encryption/jsencrypt';
import { axiosCanceler } from './axiosCancel';
import { useLocaleStoreWithOut } from '@/store/modules/locale';
import CryptoJS from 'crypto-js';
const globSetting = useGlobSetting();
const localeStore = useLocaleStoreWithOut();
@ -50,8 +51,10 @@ const transform: AxiosTransform = {
const base64Str = encryptUtil.decrypt(encryptKey);
/** base64 解码 得到请求头的 AES 秘钥 */
const aesSecret = decryptBase64(base64Str.toString());
// aesSecret此时为数组,需要变成字符串
const asciiStr=CryptoJS.enc.Utf8.stringify(aesSecret)
/** 使用aesKey解密 responseData */
const decryptData = decryptWithAes(res.data as unknown as string, aesSecret);
const decryptData = decryptWithAes(res.data as unknown as string, asciiStr);
/** 赋值 需要转为对象 */
res.data = JSON.parse(decryptData);
}
@ -206,8 +209,11 @@ const transform: AxiosTransform = {
encrypt &&
['POST', 'PUT'].includes(config.method?.toUpperCase() || '')
) {
const aesKey = generateAesKey();
config.headers['encrypt-key'] = encryptUtil.encrypt(encryptBase64(aesKey));
const aesKey = generateSM4Key();
// askey此时为字符串需要变成数组,去base64编码。与后端对应
const asciiStr=CryptoJS.enc.Utf8.parse(aesKey)
// config.headers['encrypt-key'] = encryptUtil.encrypt(encryptBase64(aesKey));
config.headers['encrypt-key'] = encryptUtil.encrypt(encryptBase64(asciiStr));
if (typeof config.data === 'object') {
config.data = encryptWithAes(JSON.stringify(config.data), aesKey);

Loading…
Cancel
Save