目录
- 简介
- 什么是 SM4 加密算法
- SM4 与其他对称加密算法的区别
- 项目背景与需求分析
- 项目的技术栈与依赖
- 实现步骤
-
- 设置 Axios 实例
-
- 编写加密函数
loginTo
- 编写加密函数
-
- 编写解密函数
decrypt
- 编写解密函数
-
- 配置 Axios 请求和响应拦截器
-
- 前端与后端的交互与安全性设计
- 常见问题与解决方法
- 项目完整代码示例
- 总结与未来发展方向
1. 简介
在前端开发中,保护用户的敏感信息尤为重要,特别是在处理用户的认证、交易等敏感操作时。在日常开发中,我们常使用 HTTPS 保证传输的安全性,但对于部分数据还需进一步加密,确保在传输过程中的安全。本文将详细介绍如何在前端项目中使用 SM4 加密算法保护敏感数据,并结合 Axios 实现数据在传输中的加密与解密。
2. 什么是 SM4 加密算法
SM4 是中国国家密码管理局设计的一种对称加密算法。作为国密算法之一,它具有较高的安全性,主要用于保障敏感数据的传输安全。SM4 加密算法采用 128 位的密钥长度和分组加密模式,其核心特点如下:
- 对称加密:即加密和解密使用相同的密钥,密钥需要在通信双方之间安全地共享。
- 分组加密:SM4 使用 128 位的分组大小,即每次加密 128 位的数据。
- 支持多种模式:SM4 支持 ECB、CBC、CFB 等多种加密模式,允许在不同应用场景下选择适合的加密模式。
3. SM4 与其他对称加密算法的区别
SM4 类似于 AES、DES 等对称加密算法,但在具体实现和应用上存在差异:
- 密钥长度:AES 可支持 128、192、256 位的密钥长度,而 SM4 只支持 128 位密钥。
- 加密模式:SM4 也支持 ECB、CBC 等分组加密模式,符合对称加密的标准。
- 安全性:SM4 是中国国家密码管理局定义的加密标准,在国内多种应用中有广泛使用,其安全性符合国家级应用需求。
4. 项目背景与需求分析
在本项目中,我们的目标是加密一个字符串 ticket
,并将加密数据通过 Axios 传输给服务器。服务器收到加密数据后解密并进行相应处理。我们的需求包括以下几点:
- 数据加密:前端需要对特定敏感数据进行加密,确保传输过程中的数据安全。
- 加密模式选择:为了简化实现,我们采用 ECB(Electronic Codebook)模式,该模式适合小数据的加密。
- 加密算法选择:SM4 作为对称加密算法,为我们提供了符合国密标准的加密方案。
- 与后端交互:在前端和后端之间传输加密数据,并在响应拦截器中对返回的数据进行解密。
5. 项目的技术栈与依赖
本项目主要使用了以下技术和依赖:
- Axios:用于处理 HTTP 请求和响应。
- sm-crypto:一个 JavaScript 实现的 SM 加密库,支持 SM2、SM3 和 SM4 加密算法。
- React:作为前端 UI 框架。
- TypeScript:增强代码的类型安全性。
6. 实现步骤
1. 设置 Axios 实例
首先,我们创建 Axios 实例,并在实例上设置请求和响应拦截器,以便在每次请求前加密数据,接收到响应后解密数据。
import axios from "axios";
import * as sm from 'sm-crypto';
// 创建 Axios 实例
const instance = axios.create({
baseURL: "/",
timeout: 20000
});
2. 编写加密函数 loginTo
loginTo
函数用于将字符串 ticket
使用 SM4 算法加密,并返回加密后的 Base64 字符串。我们选择 ECB 模式,并应用 PKCS7 填充。
const loginTo = () => {
const ticket = "gly"; // 要加密的字符串
const key = '5e3gggggg1yd2h'; // SM4 密钥,16 字节
const keyBytes = Array.from(new TextEncoder().encode(key));
try {
const encryptedData = sm.sm4.encrypt(ticket, keyBytes, {
mode: 'ecb', padding: 'pkcs7' });
const base64Data = btoa(String.fromCharCode(...new Uint8Array(encryptedData)));
console.log("Encrypted Base64 Data:", base64Data);
return base64Data;
} catch (error) {
console.error("Encryption error:", error);
throw new Error("Encryption process failed.");
}
};
3. 编写解密函数 decrypt
解密函数 decrypt
用于对加密的 Base64 数据进行解密,还原为原始的字符串 ticket
。
const decrypt = (base64Data) => {
if (!base64Data) {
throw new Error("Base64 data is null or undefined.");
}
const data = Uint8Array.from(atob(base64Data), c => c.charCodeAt(0));
const key = '5e3gggggg1yd2h'; // SM4 密钥,16 字节
const keyBytes = Array.from(new TextEncoder().encode(key));
try {
const decryptedData = sm.sm4.decrypt(data, keyBytes, {
mode: 'ecb', padding: 'pkcs7' });
const result = new TextDecoder().decode(decryptedData);
return result;
} catch (error) {
console.error("Decryption error:", error);
throw new Error("Decryption process failed.");
}
};
4. 配置 Axios 请求和响应拦截器
在 Axios 实例上配置请求和响应拦截器,以便在每次请求前加密 ticket
,并在接收到响应后对返回的数据解密。
instance.interceptors.request.use(
config => {
const encryptedTicket = loginTo(); // 获取加密后的 `ticket`
config.headers['ticket'] = encryptedTicket; // 将加密后的数据放入请求头
return config;
},
err => {
return Promise.reject(err);
}
);
instance.interceptors.response.use(
res => {
if (res.data && res.data.encryptedData) {
const decryptedData = decrypt(res.data.encryptedData); // 解密返回的数据
console.log("Decrypted Response Data:", decryptedData);
}
return res.data;
},
err => {
return Promise.reject(err);
}
);
7. 前端与后端的交互与安全性设计
在实际项目中,前端和后端的安全性设计尤为重要。通过 SM4 加密,我们可以在前端将敏感数据加密传输,同时在后端使用相同密钥解密。在生产环境中,前后端需要通过 HTTPS 保证传输的安全性,同时在密钥管理方面,应确保密钥不会被暴露。
8. 常见问题与解决方法
- 加密后的数据为空:可能是因为加密参数不正确,或密钥长度不符合 SM4 标准。请确保密钥长度为 16 字节。
- 解密失败:检查解密模式和填充方式,确保与加密时一致。
9. 项目完整代码示例
// index.ts
import axios from "axios";
import * as sm from 'sm-crypto';
const instance = axios.create({
baseURL: "/",
timeout: 20000
});
const loginTo = () => {
const ticket = "gly";
const key = '5e3gggggg1yd2h';
const keyBytes = Array.from(new TextEncoder().encode(key));
try {
const encryptedData = sm.sm4.encrypt(ticket, keyBytes, {
mode: 'ecb', padding: 'pkcs7' });
const base64Data = btoa(String.fromCharCode(...new Uint8Array(encryptedData)));
return base64Data;
} catch (error) {
console.error("Encryption error:", error);
throw new Error("Encryption process failed.");
}
};
const decrypt = (base64Data) => {
if (!base64Data) throw new Error("Base64 data is null or undefined.");
const data = Uint8
Array.from(atob(base64Data), c => c.charCodeAt(0));
const key = '5e3gggggg1yd2h';
const keyBytes = Array.from(new TextEncoder().encode(key));
try {
const decryptedData = sm.sm4.decrypt(data, keyBytes, {
mode: 'ecb', padding: 'pkcs7' });
const result = new TextDecoder().decode(decryptedData);
return result;
} catch (error) {
console.error("Decryption error:", error);
throw new Error("Decryption process failed.");
}
};
instance.interceptors.request.use(
config => {
const encryptedTicket = loginTo();
config.headers['ticket'] = encryptedTicket;
return config;
},
err => {
return Promise.reject(err);
}
);
instance.interceptors.response.use(
res => {
if (res.data && res.data.encryptedData) {
const decryptedData = decrypt(res.data.encryptedData);
console.log("Decrypted Response Data:", decryptedData);
}
return res.data;
},
err => {
return Promise.reject(err);
}
);
export default instance;
10. 总结与未来发展方向
通过本文的介绍,我们实现了在前端使用 SM4 加密算法对敏感数据的加密传输。通过合理配置 Axios 拦截器,我们实现了加密数据的传输与解密。在实际项目中,还可以进一步完善,比如使用 HTTPS、实现更复杂的数据安全策略以及合理的密钥管理等。希望这篇文章为你在前端安全性设计方面提供了参考。