安全不是可选项:理解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 权限模型:如何设计一个灵活的权限系统


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

相关推荐
西柚小萌新3 小时前
【人工智能:Agent】--OpenClaw设计架构解析
运维·服务器·架构
小程故事多_803 小时前
AI Coding 工程化革命,Superpowers 管流程,ui-ux-pro-max 管质感
人工智能·ui·架构·aigc·ai编程·ux·claude code
好运的阿财3 小时前
“锟斤拷”问题——程序中用powershell执行命令出现中文乱码的解决办法
linux·前端·人工智能·机器学习·架构·编辑器·vim
提子拌饭1334 小时前
开源鸿蒙跨平台Flutter开发:AR太空探索应用
flutter·华为·架构·开源·harmonyos·鸿蒙
小陈工4 小时前
Python Web开发入门(十八):跨域问题解决方案——从“为什么我的请求被拦了“到“我让浏览器乖乖听话“
开发语言·python·机器学习·架构·数据挖掘·回归·状态模式
墨雪遗痕4 小时前
工程架构认知(二):从 CDN 到 Keep-Alive,理解流量如何被“消化”在系统之外
java·spring·架构
霸道流氓气质4 小时前
微服务架构开发模式-接口定义契约(路由+API规范),Controller实现业务,Feign复用接口远程调用,附详细示例
微服务·云原生·架构
天天进步20154 小时前
[架构篇] 解构项目蓝图:Toonflow 的模块化设计与 AI 管道流转
人工智能·架构
架构师老Y4 小时前
007、微服务架构设计与服务拆分策略
python·微服务·架构