RSA简介,这里贴上一篇博客,讲的很详细,通俗易懂
初步理解之后,下面是关于RSA的简单使用:
这里贴上一篇优秀的前端加密,后端解密的博客,简单使用的话是可以了。
看完上面两篇博客,就够用的了,我这里记录一下目前项目中用到的加密方式:
首先是两对秘钥:前端一对,后端一对:
ejtConfig.java,下面的秘钥都是不全的,随机删除了一些内容。
在线生成秘钥:http://web.chacuo.net/netrsakeypair 或者参考这篇博客,在自己电脑上生成秘钥
public class ejtConfig {
//RSA 公钥1
public static final String PUBLIC_KEY="MIGfMA0GCSqGSIb3DQEBAQUAUuy7mKYZKFwsDGbg7EWWFo8mNGQKPM9kAvIam/p+zBrEpQCgDYZZp0kMZUgCBdp543AzxiQJTHN6+LrTYpZlyot0We0QzJHbsLJmnpvKPOmpfYANUfB63PoNV9ZFep/qpTnNquCDKVfY1QUEfJDLgQIDAQAB";
//RSA 私钥1
public static final String PRIVATE_KEY="MIICdQIBADANBgkqhkZ7RDMkduwsmaem8o84xuhvpTQbhqMM8GtyGcqCal9gA1R8Hrc+g1X1kV6n+qlOc2q4IMpV9jVBQR8kMuBAgMBAAECgYAVZloFC+fZmrCMrH/Z7uUa4yH7DmGr8NKH1wckYlHKFfZ3whBeswvvN+YetjzkeVh4i6mkwovjrW4q4wIuQZUexDqguleqbmdz5OEZ0jLItfX0xdRlWogzE3VQnxLu+9cNd3J6OBcNmvfCWaUCQQDeUfArljGsDQCGUhvZFFiifX+r5GrO1f2clW+/XaVDu9sYMmbLO2NbNAxsBqRpautAkBf3gQ0Glc2EuZMeA59f68Mxpkbo4gqMsmsQLExnSt8mi3+1LvtzF8PvHy3Ipi7JK6suFRFvGb/bm2Mdy695aNBAkANlgpMT5hngD/o9XmYMYMdIvg7Y/EXBMLD3+bdHRiOusUSe5VPCVsPcNkWkUQJOGVG55vsPbmiq+SpNK7a+bndAkBKelKXC1GmjW0CeyEXTGG/aRzUXGPmsMk8Nc0t0yQiu+FTFR/P0UfIzZaE0GaIzXA7H7/Wwk/EZ4p/eG6WALof";
//RSA 公钥2
public static final String PUBLIC_KEY2="MIGfMA0GCSqGSIbQKBgQDL07hhkiy0e3OAHnw4Uhqo82a59BhyKscIp4XaRJ5B0EchJ0qFt6qOwTRIQtm1qfQw0EOH+XhfKUy+/UKPfnEVDRGS3dwS5rrAYY6GeOngnoQ9qgzvho1S44onkYnQlKPUUYsQE9QwRC0ElMSJNWObQIDAQAB";
//RSA 私钥2
public static final String PRIVATE_KEY2="MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAMvTuGGSLLR7c4AefDhSGqjzZrn0GHIqxwinhdpGxHy7bwnkHQRyE3qo7BNEhC2bW79Qo9+zOucRUNEZA9y26ZLd3BLmusBhjoZ46eCehD2qDO+GjVLjiie5Mh1wSRidCUo9RRixAT1DBELQSUxIk1Y5tAgMBAAECgYAkY2PjZ2k7v15bXRXoKCBhmMZUe3aVAPNQiJnDeuLT7TmQ9Zx93yCVwVqEBhNi4P1IuXu1aTC+KFeqYM4rzHtNBvN6lkcm+jQaMRCoLN5/CTQjHE7g/SvBNGSX7Tyf6JUB/E7IGCbSvfT+Mgu+noqPyPjezQjGkdNKeGe+sQJBAPhbkny7rX3cwul8sMA3IgZQYxvtcqdJVeQJkUhcXCu7K5Y6JdQHf4VOfRBMCQQDWeqOQucpb7XeYdZPFuUiy1Hi3jFtH4NwNKjiIEwj6jfRKJaX+ByUSGfsb2Wp1bbfhEltiQATETN/AkBVaAgrWklVYJ/WO0lDI4sCpgy1xFbnI9WukCepy6v+QC1Cnt5AGiPFOxNW6qGn+b3o/ZHBqKot42vAkB2aSLghhJYilQa0d8RrGecg31aKJ1Eo7oZcpPfXFL6sJWUPZv0Z5kDWps5r3tnyknF2QKRrzHVWEAg+Y8mde/Pvk7hrSRco2zji4jyFY6TE4NWTgxvM0Grma91H3coqfgj/10MhIGgqtW3ePVBZFrUfcsKuNOiGdyDQ==";
}
秘钥的使用规则:
(1) 使用RSA加密;
(2) 生成两对密钥,公钥1 私钥1,公钥2 私钥2,后台存有两对密钥,客户端存有公钥1、私钥2;
(3) 请求数据:客户端使用公钥1加密后发给后台,后台使用私钥1解密;
(4) 返回数据:后台使用公钥2加密后返回给客户端,客户端使用私钥2解密;
工具类RSAUtils.java
需要添加依赖:
<dependency>
<groupId>commons-codec</groupId>
<artifactId>commons-codec</artifactId>
<version>1.9</version>
</dependency>
RSAUtils.java
package com.lin.util;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;
import javax.crypto.Cipher;
import org.apache.commons.codec.binary.Base64;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
/**
* Created by humf.需要依赖 commons-codec 包
*/
public class RSAUtils {
public static final String KEY_ALGORITHM = "RSA";
public static final String SIGNATURE_ALGORITHM = "MD5withRSA";
private static final String PUBLIC_KEY = "RSAPublicKey";
private static final String PRIVATE_KEY = "RSAPrivateKey";
public static byte[] decryptBASE64(String key) {
return Base64.decodeBase64(key);
}
public static String encryptBASE64(byte[] bytes) {
return Base64.encodeBase64String(bytes);
}
/**
* 用私钥对信息生成数字签名
*
* @param data 加密数据
* @param privateKey 私钥
* @return
* @throws Exception
*/
public static String sign(byte[] data, String privateKey) throws Exception {
// 解密由base64编码的私钥
byte[] keyBytes = decryptBASE64(privateKey);
// 构造PKCS8EncodedKeySpec对象
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
// KEY_ALGORITHM 指定的加密算法
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
// 取私钥匙对象
PrivateKey priKey = keyFactory.generatePrivate(pkcs8KeySpec);
// 用私钥对信息生成数字签名
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initSign(priKey);
signature.update(data);
return encryptBASE64(signature.sign());
}
/**
* 校验数字签名
*
* @param data 加密数据
* @param publicKey 公钥
* @param sign 数字签名
* @return 校验成功返回true 失败返回false
* @throws Exception
*/
public static boolean verify(byte[] data, String publicKey, String sign)
throws Exception {
// 解密由base64编码的公钥
byte[] keyBytes = decryptBASE64(publicKey);
// 构造X509EncodedKeySpec对象
X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
// KEY_ALGORITHM 指定的加密算法
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
// 取公钥匙对象
PublicKey pubKey = keyFactory.generatePublic(keySpec);
Signature signature = Signature.getInstance(SIGNATURE_ALGORITHM);
signature.initVerify(pubKey);
signature.update(data);
// 验证签名是否正常
return signature.verify(decryptBASE64(sign));
}
public static byte[] decryptByPrivateKey(byte[] data, String key) throws Exception{
// 对密钥解密
byte[] keyBytes = decryptBASE64(key);
// 取得私钥
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
// 对数据解密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, privateKey);
return cipher.doFinal(data);
}
/**
* 解密<br>
* 用私钥解密
*
* @param data
* @param key
* @return
* @throws Exception
*/
public static byte[] decryptByPrivateKey(String data, String key)
throws Exception {
return decryptByPrivateKey(decryptBASE64(data),key);
}
/**
* 解密<br>
* 用公钥解密
*
* @param data
* @param key
* @return
* @throws Exception
*/
public static byte[] decryptByPublicKey(byte[] data, String key)
throws Exception {
// 对密钥解密
byte[] keyBytes = decryptBASE64(key);
// 取得公钥
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key publicKey = keyFactory.generatePublic(x509KeySpec);
// 对数据解密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, publicKey);
return cipher.doFinal(data);
}
/**
* 加密<br>
* 用公钥加密
*
* @param data
* @param key
* @return
* @throws Exception
*/
public static byte[] encryptByPublicKey(String data, String key)
throws Exception {
// 对公钥解密
byte[] keyBytes = decryptBASE64(key);
// 取得公钥
X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key publicKey = keyFactory.generatePublic(x509KeySpec);
// 对数据加密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
//System.out.println(cipher.doFinal(data.getBytes()).toString());
return cipher.doFinal(data.getBytes());
}
/**
* 加密<br>
* 用私钥加密
*
* @param data
* @param key
* @return
* @throws Exception
*/
public static byte[] encryptByPrivateKey(byte[] data, String key)
throws Exception {
// 对密钥解密
byte[] keyBytes = decryptBASE64(key);
// 取得私钥
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(keyBytes);
KeyFactory keyFactory = KeyFactory.getInstance(KEY_ALGORITHM);
Key privateKey = keyFactory.generatePrivate(pkcs8KeySpec);
// 对数据加密
Cipher cipher = Cipher.getInstance(keyFactory.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
return cipher.doFinal(data);
}
/**
* 取得私钥
*
* @param keyMap
* @return
* @throws Exception
*/
public static String getPrivateKey(Map<String, Key> keyMap)
throws Exception {
Key key = (Key) keyMap.get(PRIVATE_KEY);
return encryptBASE64(key.getEncoded());
}
/**
* 取得公钥
*
* @param keyMap
* @return
* @throws Exception
*/
public static String getPublicKey(Map<String, Key> keyMap)
throws Exception {
Key key = keyMap.get(PUBLIC_KEY);
return encryptBASE64(key.getEncoded());
}
/**
* 初始化密钥
*
* @return
* @throws Exception
*/
public static Map<String, Key> initKey() throws Exception {
KeyPairGenerator keyPairGen = KeyPairGenerator
.getInstance(KEY_ALGORITHM);
keyPairGen.initialize(1024);
KeyPair keyPair = keyPairGen.generateKeyPair();
Map<String, Key> keyMap = new HashMap(2);
keyMap.put(PUBLIC_KEY, keyPair.getPublic());// 公钥
keyMap.put(PRIVATE_KEY, keyPair.getPrivate());// 私钥
return keyMap;
}
/**
* 解密参数并转换成json
* @param data
* @return
* @throws Exception
*/
public static JSONObject getContent(String data )throws Exception {
//获取参数
byte[] encryptByPrivateKey=null;
try {
encryptByPrivateKey = RSAUtils.decryptByPrivateKey(data,ejtConfig.PRIVATE_KEY );
} catch (Exception e) {
e.printStackTrace();
}
String decodedData =new String(encryptByPrivateKey,"UTF-8");
System.out.println("String:" + decodedData);
JSONObject obj=JSON.parseObject(decodedData);
System.out.println("obj:" + obj);
return obj;
}
public static void main(String[] args) throws Exception {
String aaaa="ju9oSvodOy4mCLb0c/6UP8nGIIoVO3vlJeJ0wrRkUeGjUQWWtpkBWHXW2oxClwbf0ysi2/I6/aBq80FVxUU8qhYpIFzGILYGlnmoEHJxrO1BZfPXLSCa18HorhNkNkdGiRi5SEWfIKktmxIozckwKGvEqLGHoNB8Un8/9EyuELM=";
/* Map<String, Key> keyMap = initKey();
String publicKey = getPublicKey(keyMap);
String privateKey = getPrivateKey(keyMap);
System.out.println(keyMap);
System.out.println("-----------------------------------");
System.out.println("公钥:"+publicKey);
System.out.println("-----------------------------------");
System.out.println("私钥:"+privateKey);
System.out.println("-----------------------------------");*/
JSONObject json=new JSONObject();
json.put("memberId", "16652");
json.put("accessKey", "e21b060017b4e911d14baa819905caa5");
// json.put("pageNum", "1");
// json.put("pageSize", "5");
// json.put("memberId", "1236");
// json.put("testingAreaInfo", "深圳");
/* json.put("Areaid","7");
json.put("Id","16639" );
json.put("Areainfo","8" );*/
String str =String.valueOf(json);
System.out.println("str:" + str);
byte[] aa=null;
try {
aa=RSAUtils.encryptByPublicKey(str,ejtConfig.PUBLIC_KEY);
} catch (Exception e1) {
e1.printStackTrace();
}
String base64 = Base64.encodeBase64String(aa);
System.out.println("base64:"+base64);
JSONObject obj1 = RSAUtils.getContent(aaaa);
System.out.println("obj1:" + obj1);
String name=URLEncoder.encode("测", "GBK");
String decode = URLDecoder.decode(name);
System.out.println(name);
System.out.println(decode);
}
}
后台对前台传来的加密数据data进行解密,提取参数,然后返回加密的token,这里用注册接口示例:
/**
* 注册接口
* @param request
* @param response
* @param data
* @return
*/
@RequestMapping("/memberRegister")
@ResponseBody
public JSONObject memberRegister(String data){
JSONObject json = null;
//====解密,并转为json字符串
try {
json = RSAUtils.getContent(data);
} catch (Exception e) {
e.printStackTrace();
return JsonUtil.getJson(50, null, "参数格式不对");
}
//解密结束,获取密文内容
String phoneNum = json.getString("phoneNum");
String password= json.getString("password");
//注册写入数据库之后,返回用户id和token(加密传输)
ShopMember member=shopMemberService.findByMemberPhone(phone);
//初始化用户token信息(token生成方式,参考我的另一篇博客,后续加上)
String initializeToken = appTokenRecordService.initializeToken(member.getMemberId());
JSONObject json = new JSONObject();
json.put("token", initializeToken);
json.put("memberId", member.getMemberId());
String str=String.valueOf(json);
byte[] aa = null;
try {
aa = RSAUtils.encryptByPublicKey(str,ejtConfig.PUBLIC_KEY2);
} catch (Exception e1) {
e1.printStackTrace();
}
String base64 = Base64.encodeBase64String(aa);
System.out.println(base64);
return JsonUtil.getJson(10, base64, "注册成功");
}
上面demo中要用到的一个工具类:JsonUtil.java
public class JsonUtil {
public static JSONObject getJson(int ret,Object result,String msg){
JSONObject json = new JSONObject();
json.put("ret", ret); //0失败 1成功
json.put("data", result); //返回数据
json.put("msg", msg); //返回消息
return json;
}
}
到这里,一个简单的RSA加密传输的demo就算结束了。