在基于B/S 的业务系统中,如果要设计开发加密解密机制。有几种设计选型:
- 可以使用现成的HTTPS 架构,后端部署用知名签名机构生成的证书。
- 可以使用现成的HTTPS 架构,后端部署自签名的证书,但是用户需要在浏览器中导入自签名证书。
- 基于HTTP 传输加密的数据。也就是说,虽然使用非加密的传输协议,但是数据本身是加密的。
本文说明的加密系统是基于第三个技术选型进行设计,即在使用HTTP 协议进行传输,并对传输数据加密。
系统架构
在该架构中存在一个加密服务,对外提供RESTful的HTTP GET API: /crypto/key, 该API的响应体中包含AES对称加密算法的配置信息,同时包含RSA公钥。AES算法的配置信息在加密服务中使用RSA的私钥进行了加密。加密服务的使用者需要从加密服务/crypto/key获取算法配置信息。该加密系统支持的场景为:
- 在同一业务系统的前端和后端之间进行加密。
- 在不同业务系统之间进行加密。
其架构图如下所示:

其主要步骤有:
1)业务系统A 的前端通过HTTP 请求,从加密服务获取加密算法相关信息,并通过封装的驱动文件
解析加密算法信息。
2)业务系统A 的后端通过HTTP 请求,从加密服务获取加密算法相关信息,并通过封装的驱动文件
解析加密算法信息。
3)业务系统A 前端使用AES 加密业务数据,通过HTTP 请求发送到后端。后端接收到前端的加密数据后,使用AES 解密数据,并进行后续的处理。相反的方向是类似的,后端使用AES 加密业务数据,通过HTTP 传输到前端,前端使用AES 解密接收到的后端加密数据,并进行后续的处理。
4)业务系统B 的前端和后端与加密服务进行的交互以及业务系统B 的前后端间的加密传输,和步骤1,2,3 的说明一样,不再重复阐述。
5)业务系统A 和业务系统B 进行交互时,业务系统A 的后端使用AES 加密数据,通过HTTP 传输到业务系统B 后端,业务系统B 后端使用AES 解密数据,并进行后续处理。反方向的流程是类似的处理。
加密服务
加密服务是个web服务,其设计不限于某种程序语言。既可以使用基于Spring boot的java程序设计语言开发也可以使用Node.js平台或其他任何程序设计语言开发。本文使用Spring boot进行设计开发。
加密服务Spring boot的入口程序如下:
@SpringBootApplication
public class CryptoApplication {
public static void main(String[] args) {
SpringApplication.run(CryptoApplication .class, args);
}
@Bean
public CommandLineRunner init(final CryptoController cryptoController) {
CommandLineRunner commandLineRunner = (String ...strings) -> {
cryptoController.init();
};
return commandLineRunner;
}
}
加密服务controller:
@RestController
public class CryptoController {
@Value("${crypto.pubFile}")
private String publicKeyFile;
@Value("${crypto.prvFile}")
private String privateKeyFile;
@Value("${crypto.aes.mode}")
private String aesMode;
@Value("${crypto.aes.key}")
private String aesKey;
@Value("${crypto.aes.iv}")
private String aesIv;
private String publicKey;
private RSAPrivateKey privateKey;
private byte[] aesKeyBytes;
private byte[] aesIvBytes;
@GetMapping(value = "/crypto/key", produces = "application/json")
public ResponseEntity<CryptoKey> getCryptoKey(@RequestHeader String referer) throws Exception {
Assert.isTrue (StringUtils.hasText(aesMode));
Assert.isTrue (StringUtils.hasText(aesKey));
Assert.isTrue (StringUtils.hasText(aesIv));
Assert.isTrue (StringUtils.hasText(publicKey));
Assert.isTrue (privateKey != null);
boolean refererOk = checkReferer(referer)
if (!refererOk) {
return ResponseEntity.badRequest().build();
}
Cipher cipher = Cipher.getInstance("RSA");
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
cipher.update("aes".getBytes(StandardCharsets.UTF_8));
byte[] algBytes = cipher.doFinal


2652

被折叠的 条评论
为什么被折叠?



