PS:第一次这么投入的搞个东西搞到这么晚
记录一下:
背景:因为工作中涉及到这样的一个场景,A方希望调用B方的页面,并且传递一些参数过来,如果直接在url后面添加的话,显得不安全,因此希望通过一个加密协议来进行互相认证,于是提到了RSA非对称加密及证书认证
我大改理解思路: 首先是A生成一个公钥和私钥,自己保留私钥,将公钥给对方系统B,而证书里面正是这个公钥
不知道对不对 。。。。
然后我查了下资料,最简单的生成这样的一对公钥和私钥的方法,使用JDK生成SSL证书
步骤:
CMD 进入jdk目录
1.使用keytool命令生成证书:
输入命令 :
keytool -genkey -alias test -keypass 123456 -keyalg RSA -keysize 1024 -validity 365 -keystore E:/dongjinlong/笔记/test.keystore -storepass 123456
填写内容:这个貌似没啥要求
参数解析:
keytool bin下的keytool.exe
-genkey
-alias test(别名)
-keypass 123456(别名密码)
-keyalg RSA(算法)
-keysize 1024(密钥长度)
-validity 365(有效期,天单位)
-keystore E:/dongjinlong/笔记/test.keystore(指定生成证书的位置和证书名称)
-storepass 123456(获取keystore信息的密码)
2.在目录下可以找到test.keystore 文件
cmd中输入 keytool -list -v -keystore E:/dongjinlong/笔记/test.keystore -storepass 123456 可以查看
3.由keystore 生成一个证书cer文件
keytool -keystore E:/dongjinlong/笔记/test.keystore -export -alias test -file E:/dongjinlong/笔记/server.cer
重点:怎么在java代码中使用这两个文件进行加密解密呢
1. 将生成的文件放入到config目录下
2.引入commons-codec-1.10.jar 包
3.测试代码
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.codec.binary.Base64;
/**
* 1.先使用CMD 命令使用jdk 的keytool 生成 .keystore文件
* 2.再由.keystore 文件生成对应的.cer文件
* 3.将这两个文件导入的config目录下
* @author 瓜宝
*
*/
public class Cer {
/**
* 私钥加密的数据与证书解密的数据对比
*
* @param requestParam 签名的数据
* 格式String requestParam = "name1=value1&name2=value2&name3=value3";
*
* @param signParam已签名的数据
* @param cer 证书名称
* @return
*/
public static boolean verifyRSAMessageByPublic(String requestParam, String signParam, String cer) {
if (requestParam == null)
return false;
PublicKey pk = null;
InputStream in = null;
try {
/* 得到X.509证书的工厂类 */
CertificateFactory certificatefactory = CertificateFactory.getInstance("X.509");
/* 加载源文件夹下的.cer证书 参数 cer 为文件名称 server.cer */
in = Thread.currentThread().getContextClassLoader().getResourceAsStream(cer);
X509Certificate Cert = (X509Certificate) certificatefactory.generateCertificate(in);
pk = Cert.getPublicKey();
in.close();
} catch (Exception e) {
e.printStackTrace();
return false;
} finally {
try {
if (null != in) {
in.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
boolean bln = false;
try {
/*RSA解密*/
Signature dsa = Signature.getInstance("SHA1withRSA");
dsa.initVerify(pk);
dsa.update(requestParam.getBytes());
Base64 base64Decoder = new Base64();
//替换回不能通过GET方式传递的字符
signParam = replaceFromUrl(signParam);
bln = dsa.verify(base64Decoder.decode(signParam.getBytes()));
} catch (Exception e) {
e.printStackTrace();
}
return bln;
}
/**
* 测试的main方法
* @param args
*/
public static void main(String[] args) {
// 加密数据
Map<String, String> map = new HashMap<String, String>();
map.put("clientNo", "000938873761");
map.put("type", "XT");
map.put("url", "/res/index.html?_viewType=2&#orderManager/index/membership");
map.put("timestamp", "2017-09-01 13:50:16");
map.put("signdata",
"aSk4FOLpEzZdHEQaL5Se7MH%2F6MMWI5Dv2APU6LuexWgZJMpFTbLpYYpBTahGTq3ZB1RNvDEQ1mlCjYC%2F0yvfVgls3ElXyL44aQdiPKKscpQdn%2FUbBDJbVMaWllekmoTvldzscV%2BNrD3wi9IAao2NnDp9K%2BzOWGHHYVjcPlSCvnw%3D");
StringBuffer sb = new StringBuffer();
sb.append("clientNo=").append(map.get("clientNo"));
sb.append("&type=").append(map.get("type")).append("×tamp=").append(map.get("timestamp"));
System.out.println("加密前的数据:"+sb.toString());
// 本地能配对的keystore 和 cer 文件
String keystore = "test.keystore";
String password ="123456";
String alias = "test";
String sig = signData(sb.toString(),keystore,password,alias);
System.out.println(sig);
map.put("signdata", sig);
String cer = "server.cer";
boolean bln = verifyRSAMessageByPublic(sb.toString(), map.get("signdata"), cer);
System.out.println(bln);
}
/**
* 用私钥签名数据
* @param signparam 加密的参数
* 格式String requestParam = "name1=value1&name2=value2&name3=value3";
*
* @param keystore 源文件夹下私钥.keystore文件的文件名
* @param passwordjdk的keytool 工具生成文件时候设置的密码
* @param aliasjdk的keytool 工具生成文件时候设置的别名
* @return
*/
public static String signData(String signparam, String keystore,String password,String alias) {
InputStream in = null;
try {
KeyStore ks = KeyStore.getInstance("JKS");
in = Thread.currentThread().getContextClassLoader().getResourceAsStream(keystore);
/* jdk的keytool 工具生成文件时候设置的密码 */
char[] storePwd = password.toCharArray();
ks.load(in, storePwd);
in.close();
// jdk的keytool 工具生成文件时候设置的别名
PrivateKey privateKey = (PrivateKey) ks.getKey(alias, storePwd);
Signature dsa = Signature.getInstance("SHA1withRSA");
dsa.initSign(privateKey);
dsa.update(signparam.getBytes());
Base64 base64Encoder = new Base64();
String signDate = new String(base64Encoder.encode(dsa.sign()));
return replaceNoneUrl(signDate);
} catch (Exception gse) {
System.out.println(gse);
return null;
} finally {
if (null != in) {
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 替换回不能通过GET方式传递的字符
*
* @return
*/
public static String replaceFromUrl(String str) {
str = str.replaceAll("%2B", "\\+");
str = str.replaceAll("%2F", "\\/");
return str.replaceAll("%3D", "\\=");
}
/**
* 替换不能通过GET方式传递的字符
*
* @return
*/
public static String replaceNoneUrl(String str) {
str = str.replaceAll("\\+", "%2B");
str = str.replaceAll("\\/", "%2F");
return str.replaceAll("\\=", "%3D");
}
}
X7yy1TegOvUYgAfK5a7e4e0b8FFNx4BXUYZZoQkxssfgURf%2FrU%2FEmS0GKnbZUeoo%2BYV5rTOhmlBhLSC%2BinLcyQCVRlEcXYEYeZ%2BmCgwcaL0PR1BSa5Ritr%2BvU92l4zXYbk2a9OHM2Y0Ge19gKPQBtatBbmiqrboacaKmz4YeJWY%3D
true