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
;
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
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
;
@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
;
@Component
public class GetKey {
private static Map
<Integer
,String
> publicMap
;
private static Map
<Integer
,String
> privateMap
;
@
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
;
@
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
;
public String
getPublicKey(Integer i
) {
if(publicMap
==null)
{
initPublic();
}
return publicMap
.get(i
);
}
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
;
public class JsonMsg {
private Boolean success
;
private Long errorCode
;
private String errorMsg
;
private Long id
;
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.后端解密(登录为例)
@
PostMapping("login.do")
private void teaLogin(HttpServletRequest req
, HttpServletResponse resp
,Integer index
) {
String userName
= req
.getParameter("account");
String userPswd
= req
.getParameter("pswd");
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
);
if(teacherInfo
!= null) {
req
.getSession().setAttribute("teacher", teacherInfo
);
Ajax
.success(resp
);
}else{
Ajax
.error(resp
,"账号密码错误");
}
}
我这边打印出解密后的值 溜了溜了,小明要睡觉了,喜欢就点歌赞吧。