Spring-boot如何使用RSA加密

一、什么是RSA加密?

RSA加密算法是一种非对称加密算法。
由后端生成公钥和私钥,公钥和私钥为一对一的关系。
将公钥传给前端,前端:公钥+value生成密文。
后端拿到密文时,取出私钥:密文 - 私钥 = value
通过这样的形式将传输内容保密。

在这里插入图片描述

二、如何使用RSA

1.生成私钥和公钥

exportKeys()可以生成公钥和私钥,为了避免运行时耗时生成秘钥,毕竟算法的东西,很吃cpu的。我的做法是先生成几对秘钥,需要时,随机获取就好了。

package com.kid.test;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.io.FileUtils;
import org.junit.Test;
import com.kid.util.RSA;
import java.io.File;
import java.util.Map;
/**
 * @ClassName RSATest
 * @Description TODO
 * @Autor T_Antry
 * @Date 2020/10/20 16:44
 * @Version 1.0
 */
public class RSATest {
    
    
    @Test
    public void exportKeys() throws Exception {
    
    
        Map<String, Object> keyMap = RSA.genKeyPair();
        //公钥
        String publicKey = RSA.getPublicKey(keyMap);
        //私钥
        String privateKey = RSA.getPrivateKey(keyMap);
        System.out.println("公钥:/n" + publicKey);
        System.out.println("私钥:/n" + privateKey);
    }
    @Test
    public void testDecryptEncrypt() throws Exception {
    
    
        // 公钥 可以放指定位置
        String publicKeyStr = FileUtils.readFileToString(new File("/data3/pem/publickey.pem"),"UTF-8");
        String privateKeyStr = FileUtils.readFileToString(new File("/data3/pem/privatekey.pem"),"UTF-8");
        String sign = "abcccccc";
        byte[] encryptSign = RSA.encryptByPublicKey(sign.getBytes(),publicKeyStr);
        String base64Sign = Base64.encodeBase64String(encryptSign);
        System.out.println("加密后的sign: "+base64Sign);
        //私钥解密
        byte[] decryptStr = RSA.decryptByPrivateKey(Base64.decodeBase64(base64Sign),privateKeyStr);
        System.out.println("解密后的sign: "+new String(decryptStr));
    }
}

2.将生成的秘钥放到application.properties中

public.key1=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCUbrAGx2GtC8VMD+i/4FVjZn8d3eoonKPO0f33OENe06cK/rjMNqIgul2R4NvOiRqHY6WvBlv9nKj3WoU/LTZMxcPs4tdpP57ACQw135oe9afgvDs7iC7nJLbMI01FOz1Zr1ttrBy4VEnemfZiXXWs/wEZ00Nnjv4dMNfIVeXGBQIDAQAB
private.key1=MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAJRusAbHYa0LxUwP6L/gVWNmfx3d6iico87R/fc4Q17Tpwr+uMw2oiC6XZHg286JGodjpa8GW/2cqPdahT8tNkzFw+zi12k/nsAJDDXfmh71p+C8OzuILucktswjTUU7PVmvW22sHLhUSd6Z9mJddaz/ARnTQ2eO/h0w18hV5cYFAgMBAAECgYBf/56VI8qGcsBtyzRLNLnFCftYw7e4AGbpUmMgyyC3acf1knzOht8gr6fouzcuQvoHamkz47cHNZUKNV9MVt9wlX7kELiAJjRb7JDgCNW5BPyujpoKmvmDbtoJ5a0d9CLDiw9s0G1x/uL/qQwEUx9WR5ZosYvA25SYGf111PQ9WQJBAN42gZbEB4I8DjJzLcYlRaxSP/m9IriMkLE+NmlBfKQrQqvN/lTF6pNMIOISyo1w3NZHIBmHRk3qes8ImwwqeI8CQQCrAFJUzkUbcflzqYQ3t4pUsOQbZ+ZQEwZHCK0dQrYKY5FbD/RJ4YilMLmlswZ6Svx/SKHZBJquU58CJIHdqxorAkBU+fcYlqJgdWLgfBdXHM3GFjYM5P0wIeD7RtU77yUhCsIWPVIzTPRlm8k/avw2lqB8+PoXiRmjljWckqfoQR2VAkEAnDRNAP7zjeCNOCSPjL3ydO6pUIeWkWrvfw/j4yi/VboiW4a1Zo/I3O0niL+CmU/KWxMkFTPpgHkOdUyX/L+BxQJAd/Z+4uyiJdsjWEUJHbrq/3UF/BBAzqsprtn/B6aZQYlSueBArTjPiLfMt8SQpp+JPAOw8F8vAw0vkT/Jt7YN1Q==
public.key2=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCK2aleN1psUoT71tOn1FubyJzXz+1MQOo8xWlsKFwGfZXAZ2iIsq2B2F7UQgDMkzQOqh95J2qacIPU87uL6pCYJOnyG+VT+XldbW5y1h3zOg/dub/pZnmUM1azcvlH1m5XcGdWbEeCL2nZ2lM2152Qhwo0F2YxTX21IKK8aoAtfwIDAQAB
private.key2=MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAIrZqV43WmxShPvW06fUW5vInNfP7UxA6jzFaWwoXAZ9lcBnaIiyrYHYXtRCAMyTNA6qH3knappwg9Tzu4vqkJgk6fIb5VP5eV1tbnLWHfM6D925v+lmeZQzVrNy+UfWbldwZ1ZsR4IvadnaUzbXnZCHCjQXZjFNfbUgorxqgC1/AgMBAAECgYAjPD8duKBKstoqaobFpT8mFk+u+IX4ftSyXUp2dvt7bi0taVB+uBENzVGrPaCkSYrBWeyouxbzYDAkP0HNrNXKU8tU2dxHQSxxHEqLeWnxZcmCqlAsggu5q/UXOQ0wIWfBmOA6Ub4CEB4mM9qJxGs3s40CdoUS73w4mtBhgYCcwQJBAO97KiwhrXbg0X+7HFN72Pd06WDszjeHaC7f2mp1ywNkMEyT3cr5JM/FXEGEsRopF3YFJWcSSF0zvfk738FZjWECQQCUbYY0rSzKjBLtwISU/ZXyVSAI7B9Z+yZ/CrmZQzQw/AmbRylbXvYZtYqC8+b+Sk9PGpt252H295DOQvH/RcbfAkAGQJHuSwbLVr1Bd3Ia393fQAcjx6rumjNnHeMG6oJdWU1FgorE1NJYNk/dSgiRpUb+hs3eLgUDoekwy5Zg5uShAkEAklLm20ddwNAWWQxRqA/WovAIhMNCpRJTASsxjUYTTbcqQUoGG22ib/XodvC76DSZuwIgAThZ+35T4wNcTqwbQQJAKXZCBUU8oB408hMOPe80ny1YKMSDG/EvXW0L6Wuf2Xa0oBn+602wGHc+nw6gYmKXEHzxvOqDPBwCRI+Klq48Yg==
public.key3=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCXD1CH6Lbw85cPp78PM/LkDrLZbjlwPkhd/9ZdzUq/3TSPykEoaElO8rN5KFp0vKl2dt+XQURAyDOvpwNfAYRQwKHRc2o4ozqPng6yTnliASU92KX0Yx6HXlmf2PimQyiLFSzyRBUv4Do/4Ef1TRH1pxFf6L5sl6u84F5Yz9HvMwIDAQAB
private.key3=MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAJcPUIfotvDzlw+nvw8z8uQOstluOXA+SF3/1l3NSr/dNI/KQShoSU7ys3koWnS8qXZ235dBREDIM6+nA18BhFDAodFzajijOo+eDrJOeWIBJT3YpfRjHodeWZ/Y+KZDKIsVLPJEFS/gOj/gR/VNEfWnEV/ovmyXq7zgXljP0e8zAgMBAAECgYBxDa0fijMgMa4ksU50elSWCcogoDWso3BVqVst6K7A2TS1SJFrRGFZDJr1WhYYt/m8B0tfUCFcuni0RTJosCHth2NglQlH3BYpiKQJF7twjzklfGSw5V/oATNNn2Jc7Ovr8zIQZgFEafctj8yD93TfE4zywyrcP7+B+LRxjLbCAQJBAMUyG7ppUvbyB5/lVI4JGS/YQCqsmpykYjVS05PQq/CdcG0I1WFUt+bcE4/uNU4PQxRr6HMHonHGi2l2AKi7gBMCQQDEGzKmyeFYHZPmNPcOdIALqlSgWbxDvOzTtCu/9S5lCVMynG6Zlp4UXVco7EpZ/YcP2UBtFUjHAh7XM/Nu/PhhAkBAnE9rf5D4aorHABv5Qc/n1kIH+W/bPR0UfaPnParodp1cjFVlw51R3e/m69S5U9TVvxl1fx3hi30oO8qxfmXTAkBzHFfmCVhqBaqcFXjzljTXJBtaqHHW/R2ywu5vVfbuvcOFUMenBf8yivuvfMvD+Qp/phGoNjcrAbaisc7x1jHhAkEAsHe5ZyypPoj08wp+xEQKBiU11784wOyBwZ6XWqmYOqzatEmFiHrTXKW7mQyaPQUokzxrAtDbXESzV1H4EUzjfQ==
public.key4=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCuaZUCzzTqXCFnHsuoKzZRcbXgwMNo0PNScJmGpZn+o6oLa6hDnYkusn+gDEDd2QTTIUZZHyqz575kQXWM+Ttkk7yj6c/r4FnfVW1hFtgOx/UGTWMbJt+waMEF/jIiVNF/EoR4IL1X2PldmfJXJJ/9FMouP10N3MZjs6kpb+9J3QIDAQAB
private.key4=MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAK5plQLPNOpcIWcey6grNlFxteDAw2jQ81JwmYalmf6jqgtrqEOdiS6yf6AMQN3ZBNMhRlkfKrPnvmRBdYz5O2STvKPpz+vgWd9VbWEW2A7H9QZNYxsm37BowQX+MiJU0X8ShHggvVfY+V2Z8lckn/0Uyi4/XQ3cxmOzqSlv70ndAgMBAAECgYEAn2GqoyuZDoVsnOB+eUor1BdWfnGI4NL5WB+/nFTeudzz+oXB+TAP+ZVynV41NMYp64of0Ddz/X1L9i//bPkgtNCyZVn1lL+2h92hWU/doLEaonLfCzwZxc0OZYFfVH7P62wdSSXR0TL02ibuF2HizN7rOf7Wa3eqxKi7VNfkx2ECQQDe40mJvJIubE+5lq6rY5+gm/d61/YN0VRwwLK+JR01Ycp/cBT+2nvxJjxpfKZDbJ9HndJLpnqxxQzXBluo761lAkEAyFK2V1wqK0cVzu6GD8LcmMbPPGjp5g91TyVr/PdlP7L15OeghfrRYwWjNthLpSEX+SQhiQ+OsS/5OIxC83W/GQJAUCkKP6E0KcIGgkaxFy7DMC4nuWSGN737UnnbTwtmD9bVzzNuOaI2RSptO7r6yPD97/HQuihrpBesYIEG4iEhCQJAQetl8W10uvUTahr3pqwa53NUsq5becdQdRD9bisC+GktnXvTSQN2b71lLiETE23Gc8e9+VpTPF9rBX6ycWcn0QJBANuSsJeG7nQGnhit3w3Q3uhdxUHCnChluOQeVS2gHJd4oGY4hapFtRLBBIQFVheJXRqAnKXXiMLZjhLGnlz8uBA=
public.key5=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDF3SXMCRMfO4rsqWnDANZ6ibW9EjmksnVA3mR2kh02BOwvZV5Y5DThPckbFiYKvOO/Q715BNRfKYwcL3TQFaYYp4PO5nDDQQzQfgLSiVOC4dUTALw3p8jtg2KcE2efarzevEQcTbOGC+2TrdxvZfl1G3teM03Kbh6dfIIdSUUNwwIDAQAB
private.key5=MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMXdJcwJEx87iuypacMA1nqJtb0SOaSydUDeZHaSHTYE7C9lXljkNOE9yRsWJgq8479DvXkE1F8pjBwvdNAVphing87mcMNBDNB+AtKJU4Lh1RMAvDenyO2DYpwTZ59qvN68RBxNs4YL7ZOt3G9l+XUbe14zTcpuHp18gh1JRQ3DAgMBAAECgYBXyKnAQDZvoOcd4Hu/vFtrujUbUT6px1MmGITR5jl3ge+Xh424OmcLl3HlxonSMcOJU/B4BKCEJ9a1mohk2XX6qaSOZcN/KNQVuytQb5vZCCJrTY+eVX8q09QpWWKVB1X+ILInTf5qzOK3Gt1/9+U51EqZ5oQej6EGfGRdVViIYQJBAPcPPhj3I2f35/lzKJu1+bnr0eiiTj8f4Ai86TpQLwiySwt5tg/U+HFifJ8TBbyrP8EPaD5IbvePgE9ZpolBJ5UCQQDNBigdOjBGOqO1VDgc6SSt0KRNtmvzyy0UGehmqzFTZjOOjmNINVLLscJzOSt9PLmebIpJI5mgDK7TZbpjjSn3AkEAjvA9sDoEPRncF6G94+D0G9JJPvvwo2rwtn19vqQ3oiNtcbU4VY6VMxyVF3/s+MxndW5RlH9Z3FclGEO5K34LxQJAMwOsKZGX/3GJ2I2rJK5yXPmEWH3ioJfWkKDdreY88MaGX5tYYtg50MtbWfZItvHMMfpJ8mb0S9m8CofOeAThAwJBAKX0siSZIOninSiKxWf8i8LNMjhHJe6o/vp5qTOneOieibv0RYbHP/HFI0NXKoQhhSeU02JI7je9N1PRO0wdSbE=

3.前端请求公钥

//--------------加密
var publicKey;
var ind;
var encrypt = new JSEncrypt()
getPublcKey();
function getPublcKey() {
    
    
    $.ajax({
    
    
        url:'./getPublicKey.do',
        type:'post',
        data:{
    
    
        },
        dataType:'json',
        success:function(resp){
    
    
            if(resp.success){
    
    
                publicKey = resp.map.key;
                ind = resp.map.index;
                encrypt.setPublicKey(publicKey)
            }
            else
                layer.msg("获取公钥失败");
        }
    })
}

4.后端随机获取公钥给前端

package com.kid.handler;
import com.kid.dto.JsonMsg;
import com.kid.util.GetKey;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Random;
/**
 * @ClassName GetPublicKeyHandler
 * @Description 获取公钥
 * @Autor T_Antry
 * @Date 2020/10/20 21:52
 * @Version 1.0
 */
@RestController
public class GetPublicKeyHandler {
    
    
    @Autowired
    private GetKey getKey;
    @PostMapping("getPublicKey.do")
    public JsonMsg getPublicKey(){
    
    
        JsonMsg jm = new JsonMsg();
        Random rd = new Random();
        Integer index = rd.nextInt(5)+1;
        String key = getKey.getPublicKey(index);
        if(null==key)
        {
    
    
            jm.setSuccess(false);
            jm.setErrorCode(999999L);
        }
        else
        {
    
    
            jm.setSuccess(true);
            jm.getMap().put("key",key);
            jm.getMap().put("index",index);
        }
        return jm;
    }
}

一个封装好的,根据随机值index获取对应公钥和私钥的类,所以传公钥给前端时,把随机值一起传给前端。后面还需要这个随机的index获取私钥。

package com.kid.util;


import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;

/**
 * @ClassName GetKey
 * @Description 获取秘钥
 * @Autor T_Antry
 * @Date 2020/10/20 21:14
 * @Version 1.0
 */
@Component
public class GetKey {
    
    
    /**
     * 公租坡手中的一串公钥
     */
    private static Map<Integer,String> publicMap ;
    /**
     * 公租婆手中的一串私钥
     */
    private static Map<Integer,String> privateMap ;
    /**
     * 从properties中获取公钥
     */
    @Value("${public.key1}")
    private  String publicKey1;
    @Value("${public.key2}")
    private  String publicKey2;
    @Value("${public.key3}")
    private  String publicKey3;
    @Value("${public.key4}")
    private  String publicKey4;
    @Value("${public.key5}")
    private  String publicKey5;
    /**
     * 从properties中获取私钥
     */
    @Value("${private.key1}")
    private  String privateKey1;
    @Value("${private.key2}")
    private  String privateKey2;
    @Value("${private.key3}")
    private  String privateKey3;
    @Value("${private.key4}")
    private  String privateKey4;
    @Value("${private.key5}")
    private  String privateKey5;

    /**
     * 通过编号获取公钥
     * @param i
     * @return
     */
    public  String getPublicKey(Integer i) {
    
    
        if(publicMap==null)
        {
    
    
            initPublic();
        }
        return publicMap.get(i);
    }

    /**
     * 通过编号获取私钥
     * @param i
     * @return
     */
    public  String getPrivateKey(Integer i) {
    
    
        if(privateMap==null)
        {
    
    
            initPrivate();
        }
        return privateMap.get(i);
    }

    /**
     * 初始化公钥
     */
    private void initPublic(){
    
    
        publicMap = new HashMap<>();
        publicMap.put(1,publicKey1);
        publicMap.put(2,publicKey2);
        publicMap.put(3,publicKey3);
        publicMap.put(4,publicKey4);
        publicMap.put(5,publicKey5);
    }

    /**
     * 初始化私钥
     */
    private void initPrivate(){
    
    
        privateMap = new HashMap<>();
        privateMap.put(1,privateKey1);
        privateMap.put(2,privateKey2);
        privateMap.put(3,privateKey3);
        privateMap.put(4,privateKey4);
        privateMap.put(5,privateKey5);
    }

}

没有JsonMsg,有的人可能看不懂

package com.kid.dto;

import com.kid.util.ErrorMsg;

import java.util.HashMap;
import java.util.Map;

/**
 * @ClassName JsonMsg
 * @Description TODO
 * @Autor TT
 * @Date 2020/9/7 23:48
 * @Version 1.0
 */
public class JsonMsg {
    
    
    /**
     * 是否正确
     */
    private Boolean success;
    /**
     * 错误代码
     */
    private Long errorCode;
    /**
     * 错误信息
     */
    private String errorMsg;

    private Long id;//判断成功还是失败,1代表成功,0代表失败
    private String message;//返回信息
    private String location;//返回路径(如果成功了跳转到什么路径上)
    private Map<String,Object> map = new HashMap<>();//如果需要分页携带什么数据下去

    public JsonMsg() {
    
    
    }

    public JsonMsg(Long id, String message, String location, Map<String, Object> map) {
    
    
        this.id = id;
        this.message = message;
        this.location = location;
        this.map = map;
    }

    public JsonMsg(Boolean success, Long errorCode, String errorMsg, Long id, String message, String location, Map<String, Object> map) {
    
    
        this.success = success;
        this.errorCode = errorCode;
        this.errorMsg = errorMsg;
        this.id = id;
        this.message = message;
        this.location = location;
        this.map = map;
    }

    public Long getId() {
    
    
        return id;
    }

    public void setId(Long id) {
    
    
        this.id = id;
    }

    public String getMessage() {
    
    
        return message;
    }

    public void setMessage(String message) {
    
    
        this.message = message;
    }

    public String getLocation() {
    
    
        return location;
    }

    public void setLocation(String location) {
    
    
        this.location = location;
    }

    public Map<String, Object> getMap() {
    
    
        return map;
    }

    public void setMap(Map<String, Object> map) {
    
    
        this.map = map;
    }

    public Boolean getSuccess() {
    
    
        return success;
    }

    public void setSuccess(Boolean success) {
    
    
        this.success = success;
    }

    public Long getErrorCode() {
    
    
        return errorCode;
    }

    public void setErrorCode(Long errorCode) {
    
    
        this.errorCode = errorCode;
        errorMsg = ErrorMsg.getMsg(errorCode);//根据错误代码获取错误内容,可不要!
    }

    public String getErrorMsg() {
    
    
        return errorMsg;
    }

    public void setErrorMsg(String errorMsg) {
    
    
        this.errorMsg = errorMsg;
    }
}

5.前端加密Ajax发送(登录为例)

注意要配合上面获取公钥后
var ind;
var encrypt = new JSEncrypt(); //new一个encrypt对象
var publicKey = resp.map.key;
encrypt.setPublicKey(publicKey)//且讲公钥设置到encrypt对象中
ind = resp.map.index;//存下对应的index,后端需要index找到对应的私钥

$.ajax({
    
    
        url:'./login.do',
        type:'post',
        data:{
    
    
            type:type,//登录类型随意,看需求
            account:JsonData.login,//这个是账号,随意
            pswd:encrypt.encrypt(JsonData.pwd),//加密
            index:ind,//一定要有才
            code:JsonData.code,
        },
        dataType:'json',
        success:function(resp){
    
    
            if(resp.success){
    
    
                    console.log('登录成功');
                    return;
            }
        }
    })

6.后端解密(登录为例)

    /**
     * 教师登录
     * @param req
     * @param resp
     */
     @PostMapping("login.do")
    private void teaLogin(HttpServletRequest req, HttpServletResponse resp,Integer index) {
    
    
        String userName = req.getParameter("account");//账号
        String userPswd = req.getParameter("pswd");//密码
        /**
         * 加密rsa
         */
        try {
    
    
            userPswd = new String(RSA.decryptByPrivateKey(Base64.decodeBase64(userPswd),getKey.getPrivateKey(index)));
            System.err.println(userPswd);//这个可以打印看到前段传来的密码
        } catch (Exception e) {
    
    
            e.printStackTrace();
        }
        String userCode = req.getParameter("code");//验证码
        String url = req.getRequestURI();
        System.out.println("url:"+url);
        System.out.println("教师登录");
        TTeacherInfo teacherInfo = teacherInfoService.login(userName,userPswd,url);//查询登录账号是否存在
        //验证验证码是否正确
        //如果查询到对应账号,生成session。否则,返回错误信息
        if(teacherInfo != null) {
    
    
            req.getSession().setAttribute("teacher", teacherInfo);
            Ajax.success(resp);//回复部分,可自定义
        }else{
    
    
            Ajax.error(resp,"账号密码错误");//回复部分,可自定义
        }
    }

我这边打印出解密后的值
在这里插入图片描述
溜了溜了,小明要睡觉了,喜欢就点歌赞吧。

猜你喜欢

转载自blog.csdn.net/qq_39150049/article/details/109191120