RSA非对称加密实现

1. 基本原理

1.1 对称加密

基本概念

加密解密都使用同一个密钥。

缺点

  • 安全问题:一旦密钥泄露,传输数据将不会安全
  • 保管问题:每一类的数据加密需要重新生成一个密钥,一旦需要传输的数据类型多了,密钥管理就成了一个负担

1.2 非对称加密

基本概念

数据传输方和接收方都拥有自己的公钥和私钥,他们将公钥暴露出来提供给对方加密/解密数据,自己使用自己的私钥对数据进行加密/解密。保证加密和解密使用的是不同的密钥,所以叫做非对称加密

数据传输过程

  • 传输双方AB都需要生成自己的一对私钥和公钥
  • A将数据用B提供的公钥将数据进行加密,传输给B
  • B将数据拿到,用自己的私钥对数据进行解密。反过来B传数据给A也是一样
这个过程保证了解密使用的私钥是自己私有的,对数据解密只能使用自己知道的私钥进行解密,这个过程就避免了密钥泄露的问题。

1.3 非对称加密实例(RSA算法)

这里用登录校验功能展开。

  • 前端通过调用后端提供的接口获取公钥,在前端对密码进行加密后传输给后端
  • 后端通过自己的私钥对数据进行解密,在数据库进行校验后保存登录用户信息

需要引用的包

      
          org.bouncycastle
          bcprov-jdk16
          1.46
      
      
          commons-codec
          commons-codec
          1.10
      

前端JS

$('#loginButton').click(function(e){
       //调用后端接口获取公钥
    $.ajax({
        type:'post',
        url:'/getPublicKey.do',
        data:{},
        success:function(publicKey){
            //对密码进行加密
            var encrypt = new JSEncrypt();
            encrypt.setPublicKey(publicKey);
            that.val(encrypt.encrypt(password));
            $('#passwd').submit();
        }
    })
})

RSA工具类

public class RSAUtils {

    private static final KeyPair keyPair = initKey();

    /**
     * 初始化key pair
     *
     * @return KeyPair
     */
    private static KeyPair initKey() {
        try {
            // 添加provider
            Provider provider = new BouncyCastleProvider();
            Security.addProvider(provider);
            // 随机数用于安全加密
            SecureRandom random = new SecureRandom();
            KeyPairGenerator generator = KeyPairGenerator.getInstance("RSA", provider);
            generator.initialize(1024, random);
            return generator.generateKeyPair();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 产生公钥
     *
     * @return 公钥字符串
     */
    public static String generateBase64PublicKey() {
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        // 使用base64算法对二进制数据进行编码,返回key的原始编码形式
        return new String(Base64.encodeBase64(publicKey.getEncoded()));
    }

    /**
     * 解密数据
     *
     * @param arg 需要解密的字符串
     * @return 解密后的字符串
     */
    public static String decryptBase64(String arg) {
        try {
            Provider provider = new BouncyCastleProvider();
            Security.addProvider(provider);
            // Cipher 提供加密和解密功能
            Cipher cipher = Cipher.getInstance("RSA/None/PKCS1Padding", provider);
            PrivateKey privateKey = keyPair.getPrivate();
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            // doFinal(): 加密或者解密数据
            byte[] plainText = cipher.doFinal(Base64.decodeBase64(arg));
            return new String(plainText);
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

获取公钥

@RequestMapping("/getPublicKey.do")
    public String getPublicKey(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) {
        try {
            PrintWriter writer = httpServletResponse.getWriter();
            String publicKey = RSAUtils.generateBase64PublicKey();
            writer.write(publicKey);
            return publicKey;
        } catch (Exception e) {
            return null;
        }
    }

解密处理

@RequestMapping("/login.do")
    public String login(HttpServletRequest request, HttpServletResponse response) {
        String account = request.getParameter("usename");
        String passwd = request.getParameter("passwd");
        try {
            //解密
            passwd = RSAUtils.decryptBase64(passwd);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (account != "" && passwd != "") {
            //校验账号密码,成功则保存到session
            User user = UserDao.check(account, passwd);
            if (user != null) {
                session.setAttribute("loginUser", user);
            }
        }
        return "";
    }

你可能感兴趣的:(java,rsa)