安全不是可选项:理解AES+RSA双重加密

F06 | 安全不是可选项:理解 AES+RSA 双重加密

🆓 免费文章 | 安全篇


为什么需要加密通信?

很多新手开发者的 API 是这样的:

复制代码
POST /api/user/login
{"username": "admin", "password": "111111"}

如果你的 App 在公共 WiFi 环境下运行,中间人可以直接抓包看到明文密码。即使用了 HTTPS,也存在证书伪造、中间人攻击等风险。

生产级别的应用,必须在 HTTPS 的基础上,再加一层应用层加密。


两种加密算法的特点

AES:对称加密,速度快

  • 同一个密钥,既能加密也能解密

  • 速度极快,适合加密大量数据(如整个请求体)

  • 问题:如何安全地传递这个密钥?

    AES 密钥:一把锁,既能锁也能开
    问题:怎么把这把锁安全地给对方?

RSA:非对称加密,安全传递密钥

  • 公钥加密,私钥解密

  • 服务器公开公钥,自己保留私钥

  • 速度慢,只适合加密少量数据(如 AES 密钥)

    RSA 公钥:一个只能锁不能开的锁
    RSA 私钥:只有服务器有的开锁钥匙
    用法:把 AES 密钥放进 RSA 锁里,发给服务器


本项目的双重加密方案

复制代码
前端                              后端
 │                                 │
 │ 1. 生成随机 AES 密钥 (16字节)    │
 │                                 │
 │ 2. 获取服务器 RSA 公钥 ──────────┤ 返回 RSA 公钥
 │                                 │
 │ 3. RSA公钥加密(AES密钥) = encryptKey
 │                                 │
 │ 4. AES加密(请求体) = encryptData │
 │                                 │
 │ 5. 发送 { encryptKey, encryptData, sign }
 │                                 │
 │                   ┌─────────────┘
 │                   │ 6. RSA私钥解密 encryptKey → AES密钥
 │                   │ 7. AES解密 encryptData → 原始请求体
 │                   │ 8. 验证 sign 签名
 │                   │ 9. 处理业务逻辑
 │                   │ 10. AES加密响应体
 │ ←─────────────────┘
 │ 11. AES解密响应体 → 原始数据

关键代码剖析

前端(以 JavaScript 版为例)

复制代码
// pikachuNetwork.js 核心逻辑

// 1. 生成随机 AES 密钥
function generateAESKey() {
  const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
  let key = ''
  for (let i = 0; i < 16; i++) {
    key += chars.charAt(Math.floor(Math.random() * chars.length))
  }
  return key
}

// 2. RSA 加密 AES 密钥
function rsaEncrypt(data, publicKey) {
  const encrypt = new JSEncrypt()
  encrypt.setPublicKey(publicKey)
  return encrypt.encrypt(data)
}

// 3. AES 加密请求体
function aesEncrypt(data, key) {
  return CryptoJS.AES.encrypt(
    JSON.stringify(data),
    CryptoJS.enc.Utf8.parse(key),
    { mode: CryptoJS.mode.ECB, padding: CryptoJS.pad.Pkcs7 }
  ).toString()
}

// 发送请求
async function post(url, params) {
  const aesKey = generateAESKey()
  const encryptKey = rsaEncrypt(aesKey, store.serverPublicKey)
  const encryptData = aesEncrypt(params, aesKey)
  
  const response = await axios.post(url, {
    encryptKey,
    encryptData,
    sign: md5(sha1(JSON.stringify(params)))
  })
  
  // 解密响应
  return aesDecrypt(response.data.encryptData, aesKey)
}

后端(Kotlin 版)

复制代码
// RequestBodyAdvice:全局解密拦截器
@RestControllerAdvice
class DecryptRequestBodyAdvice : RequestBodyAdviceAdapter() {
    
    override fun beforeBodyRead(
        inputMessage: HttpInputMessage,
        parameter: MethodParameter,
        targetType: Type,
        converterType: Class<out HttpMessageConverter<*>>
    ): HttpInputMessage {
        // 读取请求体
        val body = inputMessage.body.readBytes().toString(Charsets.UTF_8)
        val request = objectMapper.readValue(body, EncryptRequest::class.java)
        
        // RSA 解密 AES 密钥
        val aesKey = rsaDecrypt(request.encryptKey, privateKey)
        
        // AES 解密请求体
        val decryptedBody = aesDecrypt(request.encryptData, aesKey)
        
        return DecryptedHttpInputMessage(inputMessage, decryptedBody)
    }
}

签名验证:防篡改

除了加密,还需要防止请求被篡改:

复制代码
// 前端生成签名
function signature(pwd) {
  return md5(sha1(pwd).toUpperCase())
}

// 后端验证签名
fun verifySign(params: Map<String, Any>, sign: String): Boolean {
    val calculated = md5(sha1(params.toSortedString()).toUpperCase())
    return calculated == sign
}

给初学者的建议

你不需要现在就完全理解每一行加密代码。在付费课程里,我们会:

  1. 直接给你完整的加密工具类代码
  2. 解释每个步骤的用途
  3. 手把手接入到你的项目里

现在只需要记住:生产级的 API 必须加密,本课程提供了完整的可复用实现。


下一篇

F07 → RBAC 权限模型:如何设计一个灵活的权限系统


本文为免费文章,转载请注明出处。

相关推荐
是温不嗜温1 小时前
QR 准谐振反激架构:当下中小功率快充的主流选择
架构·电源管理·电源芯片·ac-dc
AI焦点1 小时前
2026年AI应用架构:如何避坑并选对API聚合中转服务?
大数据·人工智能·架构
TOPGO智能1 小时前
AI PC 端侧 AI 实战:知易智能知识管家的全栈架构与踩坑实录
人工智能·架构·高通开发
JGDT_6 小时前
ERP重塑与未来趋势:SAP的实践及大一统格局(上)
大数据·人工智能·安全·架构·开源
小短腿的代码世界6 小时前
Qt对象树析构链与智能指针协同:零泄漏内存管理架构
开发语言·qt·架构
AI科技星7 小时前
数术江湖·全卷合集 - 硬核江湖・数理史诗
android·人工智能·架构·概率论·学习方法
John_ToDebug7 小时前
Chromium 132→148 升级实战:Legacy IPC 消息丢失问题深度解析
c++·chrome·ai·架构
恼书:-(空寄7 小时前
接口乱改直接炸线上!微服务接口版本控制全方案:URL_请求头版本+接口兼容原则,老旧系统无痛迭代
微服务·架构
happyprince7 小时前
08_verl-Workers模块详解
人工智能·架构·强化学习
丷丩8 小时前
错误处理与容错机制:GeoAI-UP的降级策略设计
架构·gis·容错设计