中国联通智慧云的前端数据 RSA4096 加密传输完整方案
以下是完整的实现方案:(代码已脱敏)
一、RSA加密基础原理
RSA 是一种非对称加密算法,由 Ron Rivest、Adi Shamir 和 Leonard Adleman 于 1977 年提出。其核心特点包括:
密钥对机制:使用公钥加密、私钥解密
数学基础:基于大数分解难题,4096 位密钥提供更高安全性
适用场景:密码传输、敏感数据保护、API 请求参数加密等
二、前端实现方案
1. 技术选型
前端实现 RSA4096 加密主要有以下方案:
Web Crypto API:现代浏览器原生支持,无需第三方库
jsencrypt:流行的 RSA 库,简单易用
Node-RSA:Node.js 环境专用
forge:功能全面的加密库
2. 完整实现流程
(1) 密钥生成与管理
// 使用Web Crypto API生成4096位密钥对
async function generateKeyPair() {
return await window.crypto.subtle.generateKey(
{
name: "RSA-OAEP",
modulusLength: 4096, // 使用4096位密钥
publicExponent: new Uint8Array([0x01, 0x00, 0x01]), // 65537
hash: "SHA-256",
},
true,
["encrypt", "decrypt"]
);
}最佳实践:
前端不应存储私钥,私钥必须保存在安全的服务器端
公钥动态获取,避免硬编码
定期更换密钥对增强安全性
(2) 数据加密实现
// 使用jsencrypt库加密数据
const encryptData = (publicKey, data) => {
const encryptor = new JSEncrypt();
encryptor.setPublicKey(publicKey);
return encryptor.encrypt(data);
};
// 使用Web Crypto API加密
async function encryptWithCryptoAPI(publicKey, data) {
const encoded = new TextEncoder().encode(data);
const encrypted = await window.crypto.subtle.encrypt(
{ name: "RSA-OAEP" },
publicKey,
encoded
);
return arrayBufferToBase64(encrypted);
}(3) 分段加密处理
由于 RSA4096 对数据长度有限制,需实现分段加密:
function chunkEncrypt(publicKey, data, chunkSize = 200) {
const encryptor = new JSEncrypt();
encryptor.setPublicKey(publicKey);
let result = [];
for(let i = 0; i < data.length; i += chunkSize) {
const chunk = data.substring(i, i + chunkSize);
result.push(encryptor.encrypt(chunk));
}
return result.join('|');
}三、前后端协同方案
1. 完整传输流程
前端向服务器申请 RSA 公钥
服务器生成 RSA4096 密钥对并将公钥返回前端
前端使用公钥加密敏感数据
前端对公钥进行 MD5 加密生成指纹码
前端提交指纹码和加密数据到服务器
服务器验证指纹码后使用私钥解密
服务器处理完成后立即销毁密钥对
2. 后端解密实现(Java-已脱敏)
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import javax.crypto.Cipher;
import java.security.Security;
import java.security.PrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.KeyFactory;
import java.util.Base64;
public class RSADecryptor {
static {
Security.addProvider(new BouncyCastleProvider());
}
public static String decrypt(String encryptedData, String privateKeyStr) throws Exception {
byte[] privateKeyBytes = Base64.getDecoder().decode(privateKeyStr);
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyBytes);
PrivateKey privateKey = KeyFactory.getInstance("RSA").generatePrivate(keySpec);
Cipher cipher = Cipher.getInstance("RSA/ECB/OAEPWithSHA-256AndMGF1Padding");
cipher.init(Cipher.DECRYPT_MODE, privateKey);
byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(encryptedData));
return new String(decrypted);
}
}四、安全增强措施
混合加密体系:
大数据使用 AES 加密
用 RSA4096 加密 AES 密钥
安全传输:
必须结合 HTTPS 使用
公钥传输使用数字签名验证
性能优化:
合理控制加密数据大小
考虑使用 Web Workers 处理加密运算
防御措施:
使用 OAEP 填充模式 (PKCS#1 v1.5 有已知漏洞)
防范时序攻击
五、特殊场景处理
中文加密:
先进行 Base64 编码再加密
或使用混合加密方案
密钥轮换:
// 定期请求新公钥 async function refreshPublicKey() { const response = await fetch('/api/public-key'); const { key, expiry } = await response.json(); localStorage.setItem('currentPublicKey', JSON.stringify({ key, expiry })); }移动端适配:
使用 React Native 的 Native 模块处理加密
或选择性能优化的轻量级库
六、完整示例(Vue+SpringBoot-已脱敏)
前端(Vue)实现:
import JSEncrypt from 'jsencrypt';
export default {
methods: {
async getPublicKey() {
const res = await axios.get('/api/public-key');
return res.data.publicKey;
},
async encryptData(data) {
const publicKey = await this.getPublicKey();
const encryptor = new JSEncrypt();
encryptor.setPublicKey(publicKey);
// 分段加密处理
const chunkSize = 200;
let encryptedParts = [];
for(let i = 0; i < data.length; i += chunkSize) {
const chunk = data.substring(i, i + chunkSize);
encryptedParts.push(encryptor.encrypt(chunk));
}
return encryptedParts.join('|');
},
async submitSecureData(formData) {
const encrypted = await this.encryptData(JSON.stringify(formData));
await axios.post('/api/secure-endpoint', { data: encrypted });
}
}
}后端(Spring Boot)实现:
@RestController
public class CryptoController {
@GetMapping("/api/public-key")
public ResponseEntity<Map<String, String>> getPublicKey() {
KeyPair keyPair = KeyGenerator.generateKeyPair(); // 生成4096位密钥对
String publicKey = Base64.getEncoder().encodeToString(keyPair.getPublic().getEncoded());
// 将私钥临时存储,设置过期时间
String keyId = UUID.randomUUID().toString();
KeyStorage.storePrivateKey(keyId, keyPair.getPrivate());
return ResponseEntity.ok(Map.of(
"publicKey", publicKey,
"keyId", keyId,
"expiry", Instant.now().plus(5, ChronoUnit.MINUTES).toString()
));
}
@PostMapping("/api/secure-endpoint")
public ResponseEntity<?> handleSecureData(@RequestBody EncryptedData data) {
// 验证密钥有效性
PrivateKey privateKey = KeyStorage.getPrivateKey(data.getKeyId());
if(privateKey == null || KeyStorage.isExpired(data.getKeyId())) {
throw new SecurityException("Invalid or expired key");
}
// 分段解密
String decryptedData = RSADecryptor.decrypt(data.getContent(), privateKey);
// 立即清除私钥
KeyStorage.removeKey(data.getKeyId());
// 处理业务逻辑
return processDecryptedData(decryptedData);
}
}七、性能与安全权衡
密钥长度选择:
2048 位:平衡安全性和性能
4096 位:更高安全性但性能下降 30-40%
加密数据限制:
RSA4096 最大加密数据约 490 字节
超出部分需使用分段加密或混合加密
浏览器兼容性:
Web Crypto API 兼容现代浏览器
老旧浏览器需使用 jsencrypt 等 polyfill
通过以上方案,可以实现前端数据的安全加密传输,确保即使数据被截获也无法被解密,有效保护用户敏感信息。实际实施时应根据具体业务需求调整密钥管理策略和加密粒度。