字符非对称加密传输-Java版
Posted richard-tang
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了字符非对称加密传输-Java版相关的知识,希望对你有一定的参考价值。
随着互联网的发展,安全方面也显得格外的重要。
那么我们做的应用的安全性也在受到各种挑战。
这里的话讲解的是使用“非对称加密”的方式来对前台提交过来的账号和密码进行一个加密,在使用Java搭建的后台程序来进行一个解密的操作。
那么在这里我们需要先去了解一下 "非对称加密" 是什么东西,这里直接参照百度百科即可 。
那么我们在使用这种非对称加密之前,我们需要先去准备一对 公钥 和 秘钥,公钥我们可以公开放到前端页面可以访问的地方即可,秘钥的话我们需要存放在服务器端。
那么这里我以登录为案例对账号和密码进行加密传输
那么我这里使用的秘钥生成是使用开源项目 Hutool,本文需要对该开源项目有一个基本的了解和使用(https://gitee.com/loolly/hutool),可以参考Hutool的中文文档中的加密解密Crypto。
那么我们使用Hutool生成一队秘钥对,参考Hutool的帮助文档可以找到以下的生成秘钥的代码。
KeyPair pair = SecureUtil.generateKeyPair("RSA");
PrivateKey private1 = pair.getPrivate(); //获取到一个私钥对象
PublicKey public1 = pair.getPublic(); //获取到公钥对象
System.out.println(Base64.encode(private1.getEncoded()).toString()); //转换成字符打印在控制台上
System.out.println(Base64.encode(public1.getEncoded()).toString()); //和上面一样
我们将公钥和私钥分别存储起来,因为我写文章时项目是已经做好的!那么我这里用的是Springboot构建的项目,我只需要将秘钥文件存放在resource目录下即可。注意服务端存放私钥
那么我这里文件命名为 privateKey.txt 里面的内容就是刚刚生成的私钥
那么私钥存放在服务端即可,然后我们需要将公钥存放在页面上,并且在传输的同时使用公钥进行加密后再提交账号和密码。
因为项目当初使用的是Angularjs来构建前端MVC所以下面的代码是Angularjs的形式,但是不影响,因为加密和Angularjs并没有什么关系
new JSEncrypt() 使用的是前端的一个非对称的加密工具
http://travistidwell.com/jsencrypt/
下载下来后,引入js文件,然后创建JSEncrypt对象即可
那么我们只需要在提交表单时候调用加密字符窜的方法即可
$scope.baseController = function(){ //初始化加密对象 $scope.encrypt = new JSEncrypt(); //这里是后端生成的公钥 $scope.publicKey = ‘MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCz4wRz7ZzOHN62n24inY0Zd3YCPVBNR0ZYgme5JAdzfxFq+4ce+7Qt+pCs0F2yBL0Dwc7p28Jd0b5ZQdpMa/hE9N+AHJDvRLfE2dMm2nGgBCDOZ/jMNmi4VxrJyvZ4vvQ3q5N5nam1XxeEIvtlDjyOUHrDcf7PDbNhRHSmBWjmQQIDAQAB‘; } /** * 使用公钥对字符进行加密 */ $scope.encryptStr = function(str){ var encrypt = $scope.encrypt; encrypt.setPublicKey($scope.publicKey); return encrypt.encrypt(str); }
那么前端在提交过来的表单或者异步请求时,携带过来的数据就是经过非对称加密过的数据,那么我们需要在后端对这些数据进行解密才行。
因为我这里使用的是Spring的项目,那么我们解密的时候需要使用到RSA对象,该对象是Hutool中的,所以在项目初始化的时候就需要将该对象实例化到容器中。
/** * 加密操作配置 * @author RichardTang * 2018年10月6日22:18:04 */ @Configuration @ConfigurationProperties(prefix = "crypt") public class CryptConfig { /** * 秘钥文件路径 */ private String privateKeyFilePath; @Bean public RSA getPublicKeyCryptRSA() throws FileNotFoundException, UnsupportedEncodingException {
//通过流去读取 privateKey.txt 文件的秘钥值,这里是privateKeyFilePath是使用Springboot的参数注入的方式传递的
//实际就是privateKey.txt文件的地址 InputStream stream = getClass().getClassLoader().getResourceAsStream(privateKeyFilePath); BufferedReader br = new BufferedReader(new InputStreamReader(stream, "UTF-8")); String privateKey = IoUtil.read(br).toString(); //构建一个RSA对象 交给Spring容器
return new RSA(privateKey,null); } public String getPrivateKeyFilePath() { return privateKeyFilePath; } public void setPrivateKeyFilePath(String privateKeyFilePath) { this.privateKeyFilePath = privateKeyFilePath; } }
然后我们使用自动注入的方式来获取到RSA对象,@Autowired
@Autowired private RSA decryptRSA; @PostMapping("/login") public ResponseEntity<Map<String,String>> login(@RequestBody User user) {
//这个时候获取到的 user,getUsername 是加密过的密文
//KeyType.PrivateKey 是固定的写法,意思是使用私钥进行转换成Base64 byte[] decryptUsername = decryptRSA.decryptFromBase64(user.getUsername(), KeyType.PrivateKey);
byte[] decryptPassword = decryptRSA.decryptFromBase64(user.getPassword(), KeyType.PrivateKey);
//拿到转换成byte的数组然后在使用StrUtil工具转换为明文
StrUtil.str(decryptUsername, CharsetUtil.CHARSET_UTF_8); //输出的及是没有加密过的明文
}
那么通过以上的步骤就可以实现加密和解密的过程,但是需要注意的是,秘钥要存放在服务端,一但秘钥泄露那么你的前端加密传输也就意味着被破解了。
以上是关于字符非对称加密传输-Java版的主要内容,如果未能解决你的问题,请参考以下文章
java编写非对称加密,解密,公钥加密,私钥解密,RSA,rsa
[svc]对称加密/非对称加密细枝末节-如何做到数据传输的authentication/data integrity/confidentiality(私密)