Spring-boot如何使用RSA加密

it2023-10-30  65

RSA加密

一、什么是RSA加密?二、如何使用RSA1.生成私钥和公钥2.将生成的秘钥放到application.properties中3.前端请求公钥4.后端随机获取公钥给前端5.前端加密Ajax发送(登录为例)6.后端解密(登录为例)

一、什么是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,"账号密码错误");//回复部分,可自定义 } }

我这边打印出解密后的值 溜了溜了,小明要睡觉了,喜欢就点歌赞吧。

最新回复(0)