字符非对称加密传输-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

非对称加密和对称加密

对称加密+非对称加密,实现数据安全传输

安卓客户端与服务端对称加密传输demo

[svc]对称加密/非对称加密细枝末节-如何做到数据传输的authentication/data integrity/confidentiality(私密)

密码学基础(对称加密和非对称加密)