通信加密方案之RSA密钥交换AES加密

写在前面

通信加密的方案最终形态是HTTPS通信协议

关于密钥

RSA密钥交换+AES对等加密:

服务端:

提供接口,供客户端获取RSA公钥

获取client请求头中经RSA公钥加密过的AES密钥,并使用RSA私钥解密得到AES密钥

使用AES密钥解密请求数据

使用AES密钥加密请求数据

客户端:

生成AES密钥

使用AES密钥加密请求数据

使用RSA公钥加密AES密钥,并将结果添加到httphead

使用AES密钥解密返回数据

密钥生成策略:

  • 系统使用一套固定的RSA密钥,公钥进行存放到客户端,避免公钥通信,后期服务端密钥变更受客户端约束,公钥无过期机制,密钥泄露无法,快速更新密钥。
  • 每次请求前获取最新公钥,客户端通过上次请求公钥的过期时间确定密钥是否过期,服务端密钥对,并在监控过期前获取下次需要的密钥
    • 不同客户端获取的RSA公钥相同
    • 需要多一个http公钥请求
    • 服务端需要处理过期机制,复杂
    • 客户端登录前获取一次
    • 每次请求获取最新公钥

    单向/双向加密

    http请求头中添加的一个参数,用以标识加密方式

  • EncryptType可以修改为一个唯一约定的值,建议使用一个固定的uuid值,避免与业务处理逻辑参数冲突
  • EncryptType=req

    标识只加密请求参数,服务端返回不加密

  • EncryptType=resp

    标识请求参数不加密,服务端返回加密

  • EncryptType=both

    标识同时加密请求参数和服务端返回

  • EncryptType=none

    标识不处理请求参数和服务端返回

  • EncryptType不存在时

    如果httphead中有AES密钥加密后的值,则默认为EncryptType=both,否则为EncryptType= none

    客户端:

  • 使用密钥加密请求数据为,请求参数串为:data={encryptdata},encryptdata为请求参数串的密文
  • 在请求头中添加参数:encrypttype=req/resp/bothencrypt标识请求参数加密,供后台服务端识别并进行解密
  • 接收到服务端返回后,如果需要客户端进行解密,使用密钥进行解密,并交下游业务处理类处理。

    服务端:

  • Controller预处理器中,检查encrpt的值,对为true的请求,使用密钥对请求密文进行解密,供下游Controller进行进一步的业务处理。
  • Controller后处理器中,对Controller进行业务处理后,根据预处理请求中的encrypt加密标识,将返回结果中的实体类、Json对象、文本进行加密后返回。

     
     

    具体实现:

    RSAAES的密钥生成,加密,解密方法实现

    公共代码库

    获取公钥接口:

    Return {rsapublickey:'{content}’,period:’7200′,uuid:1234-2343-1344-2343};

    Redis整合实现密钥存储过期机制:

    存放密钥对:

    Set timeout = 7260;//两小时过期,针对可能出现的临界时间请求,多设置60秒时间,避免服务端返回时获取密钥失败

    Redsi.put(uuid‘RSAPublicKey’,rsaPublicKey,timeout);

    Redsi.put(uuid‘RSAPrivateKey’,rsaPrivatelicKey,timeout);

    SpringMVC整合实现:

    继承HandlerInterceptorAdapter实现Springmvc预处理解密和后处理加密

    预处理加密:

    Request.getHeader(“encryptKey”)

    Request.getHeader(“encryptType”)

    Uuid = Request.getHeader(“encryptUuid”);

    Request.getPrameter(“encryptData”);

    Decode aeskey = RSADecode(ecnryptkey,Redis.get(“RSAPrivateKey”)+uuid);

    Data = AESDecode(encryptData,aesKey);

    后处理解密:

    Request.getHeader(“encryptKey”)

    Request.getHeader(“encryptType”)

    Uuid = Request.getHeader(“encryptUuid”);

    Request.getPrameter(“encryptData”);

    Decode aeskey = RSADecode(ecnryptkey,Redis.get(“RSAPrivateKey”)+uuid);

    Data = AESDecode(data,aesKey);

    存在的问题:

    无法处理rest风格url中的参数



打赏

发表评论

电子邮件地址不会被公开。 必填项已用*标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据