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 }
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 }
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));
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 }
5.引入的js:
jsencrypt.min.js
https://pan.baidu.com/s/16m4riNBBHCcmPiKo-JBq4Q 提取码:cvdz
6.备注:
开始弄这个的时候,主要的问题是js和action的交互上,主要有两个问题:
第一个是URL传输的时候加号(+)会变成空格( ),导致解析的时候长度出错。这个问题卡了我好久,发现后页面进行了转义,将+变成%2B,再在action中转换回来,问题解决
第二个是后台action解密一直出错,后来发现是因为在解密的时候重新执行了initKeyMap(),导致密钥不正确。将action中的keyMap提取出来后就可以正常的解密了。

浙公网安备 33010602011771号