js前台和java后台非对称加密交互

 

前几天有个需求,两个管理平台可以互相一键登录,所以需要用RSA来进行用户名和密码的传递。

1.RSA工具类

  1 package com.dp.plat.util;
  2 
  3 import java.security.Key;
  4 import java.security.KeyFactory;
  5 import java.security.KeyPair;
  6 import java.security.KeyPairGenerator;
  7 import java.security.PrivateKey;
  8 import java.security.PublicKey;
  9 import java.security.interfaces.RSAPrivateKey;
 10 import java.security.interfaces.RSAPublicKey;
 11 import java.security.spec.PKCS8EncodedKeySpec;
 12 import java.security.spec.X509EncodedKeySpec;
 13 import java.util.HashMap;
 14 
 15 import javax.crypto.Cipher;
 16 
 17 import org.apache.commons.codec.binary.Base64;
 18 
 19 
 20 /**
 21  * RSA非对称加密
 22  *
 23  */
 24 public class RSAEncryptor 
 25 {
 26     //非对称密钥算法
 27     private static final String KEY = "RSA";
 28     
 29     //密钥长度(64的倍数512-65536之间)
 30     private static final Integer KEY_SIZE = 512;
 31     
 32     //公钥
 33     private static final String PUBLIC_KEY = "PIBLIC";
 34     
 35     //私钥
 36     private static final String PRIVATE_KEY = "PRIVATE";
 37     
 38     public static HashMap<String,Object> initKeyMap() throws Exception
 39     {
 40         //实例化密钥生成器
 41         KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(KEY);
 42         //初始化密钥生成器
 43         keyPairGenerator.initialize(KEY_SIZE);
 44         //生成密钥对
 45         KeyPair keyPair = keyPairGenerator.generateKeyPair();
 46         //公钥
 47         RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
 48         //私钥
 49         RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
 50         
 51         //将密钥存储在map中
 52         HashMap<String,Object> keyMap = new HashMap<String, Object>();
 53         keyMap.put(PUBLIC_KEY, publicKey);
 54         keyMap.put(PRIVATE_KEY, privateKey);
 55         
 56         return keyMap;
 57     }
 58     
 59     /**
 60      * 私钥加密
 61      * @param data 待加密数据
 62      * @param key 密钥
 63      * @return byte[] 加密数据
 64      * @throws Exception
 65      */
 66     public static byte[] encryptByPrivateKey(byte[] data,byte[] key) throws Exception
 67     {
 68         //私钥材料转换
 69         PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(key);
 70         //实例化工厂
 71         KeyFactory keyFactory = KeyFactory.getInstance(KEY);
 72         //生成私钥
 73         PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
 74         //数据加密
 75         Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
 76         cipher.init(Cipher.ENCRYPT_MODE, privateKey);
 77         
 78         return cipher.doFinal(data);
 79     }
 80     
 81     /**
 82      * 公钥加密
 83      * @param data 待加密数据
 84      * @param key 密钥
 85      * @return byte[] 加密数据
 86      * @throws Exception
 87      */
 88     public static byte[] encryptByPublicKey(byte[] data,byte[] key) throws Exception
 89     {
 90         //公钥材料转换
 91         X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(key);
 92         KeyFactory keyFactory = KeyFactory.getInstance(KEY);
 93         //生成公钥
 94         PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
 95         //数据加密
 96         Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
 97         cipher.init(Cipher.ENCRYPT_MODE, publicKey);
 98         
 99         return cipher.doFinal(data);
100     }
101     
102     /**
103      * 私钥解密
104      * @param data 待加密数据
105      * @param key 密钥
106      * @return byte[] 解密数据
107      * @throws Exception
108      */
109     public static byte[] decryptByPrivateKey(byte[] data,byte[] key) throws Exception
110     {
111         //私钥材料转换
112         PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(key);
113         //实例化工厂
114         KeyFactory keyFactory = KeyFactory.getInstance(KEY);
115         //生成私钥
116         PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
117         //数据加密
118         Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
119         cipher.init(Cipher.DECRYPT_MODE, privateKey);
120         
121         return cipher.doFinal(data);
122     }
123     
124     /**
125      * 公钥解密
126      * @param data 待加密数据
127      * @param key 密钥
128      * @return byte[] 解密数据
129      * @throws Exception
130      */
131     public static byte[] decryptByPublicKey(byte[] data,byte[] key) throws Exception
132     {
133         //公钥材料转换
134         X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(key);
135         KeyFactory keyFactory = KeyFactory.getInstance(KEY);
136         //生成公钥
137         PublicKey publicKey = keyFactory.generatePublic(x509EncodedKeySpec);
138         //数据加密
139         Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
140         cipher.init(Cipher.DECRYPT_MODE, publicKey);
141         
142         return cipher.doFinal(data);
143     }
144     
145     /**
146      * 获取私钥
147      * @param keyMap
148      * @return
149      * @throws Exception
150      */
151     public static byte[] getPrivateKey(HashMap<String, Object> keyMap) throws Exception
152     {
153         Key key = (Key) keyMap.get(PRIVATE_KEY);
154         return key.getEncoded();
155     }
156     public static String getPrivateKeyStr(HashMap<String, Object> keyMap) throws Exception
157     {
158         Key key = (Key) keyMap.get(PRIVATE_KEY);
159         return new String(Base64.encodeBase64(key.getEncoded()));
160     }
161     
162     /**
163      * 获取密钥
164      * @param keyMap
165      * @return
166      * @throws Exception
167      */
168     public static byte[] getPublicKey(HashMap<String, Object> keyMap) throws Exception
169     {
170         Key key = (Key) keyMap.get(PUBLIC_KEY);
171         return key.getEncoded();
172     }
173 
174     public static String getPublicKeyStr(HashMap<String, Object> keyMap) throws Exception
175     {
176         Key key = (Key) keyMap.get(PUBLIC_KEY);
177         return new String(Base64.encodeBase64(key.getEncoded()));
178     }
179 }
RSA工具类

2.获取key的方法

1 HashMap<String,Object> keyMap = new HashMap<String,Object>();
2 public void getPrivateKey() throws Exception
3 {
4     keyMap = RSAEncryptor.initKeyMap();
5     String publicKey = RSAEncryptor.getPublicKeyStr(keyMap);
6     ServletActionContext.getResponse().setCharacterEncoding("utf-8");
7     ServletActionContext.getResponse().getWriter().print("{\"key\":\""+publicKey+"\"}"); 
8 }
获取KEY值

3.Action接收

1 DESEncryptor dese = new DESEncryptor();
2     q = q.replaceAll("%2B", "+");
3     w = w.replaceAll("%2B", "+");
4     byte[] privateKey = RSAEncryptor.getPrivateKey(keyMap);
5     q = new String(RSAEncryptor.decryptByPrivateKey(Base64.decodeBase64(q.getBytes()), privateKey));
6     w = new String(RSAEncryptor.decryptByPrivateKey(Base64.decodeBase64(w.getBytes()), privateKey));
Action接受

4.jsp测试页面

获取key的URL:accessKey.action

登录URL:access.action?q=&w=

 1 function login()
 2 {
 3     $.ajax({
 4         url:"accessKey.action",
 5         dataType:"json",
 6         type:"POST",
 7         success:function(data)
 8         {
 9                        //获取publiuc key
10             var key = data.key;
11             var encrypt = new JSEncrypt();
12             encrypt.setPublicKey(key);
13                       //加密用户名和密码
14             var encryptUser = encrypt.encrypt('test');
15             var encryptPassword = encrypt.encrypt('12345678');
16                 //转义空格
17                 encryptUser = encodeURI(encryptUser).replace(/\+/g,"%2B");
18             encryptPassword = encodeURI(encryptPassword).replace(/\+/g,"%2B");                            
19                         //跳转
20                         top.window.location="access.action?q="+encryptUser+"&w="+encryptPassword;
21         }
22     })
23 }    
测试JS

5.引入的js:

jsencrypt.min.js

https://pan.baidu.com/s/16m4riNBBHCcmPiKo-JBq4Q 提取码:cvdz

6.备注:

开始弄这个的时候,主要的问题是js和action的交互上,主要有两个问题:

第一个是URL传输的时候加号(+)会变成空格( ),导致解析的时候长度出错。这个问题卡了我好久,发现后页面进行了转义,将+变成%2B,再在action中转换回来,问题解决

第二个是后台action解密一直出错,后来发现是因为在解密的时候重新执行了initKeyMap(),导致密钥不正确。将action中的keyMap提取出来后就可以正常的解密了。

 

posted @ 2020-06-08 10:33  淼焱之森  阅读(722)  评论(0)    收藏  举报