PS:欢迎转载,但请注明出处,谢谢配合。
前言:
JKS文件是一个java中的密钥管理库。
JKS文件就好像一个仓库,里面可以放很多的东西,这里只存放一类东西就是密钥,仓库当然会有一把锁,防范别人随便乱拿,这个就是JKS文件的密码。里面存放的密钥也各有不同,每个密钥都有一个名字(在下面叫别名),一类就密钥对,一类叫公钥,一类叫私钥,密钥对就是包含公钥和私钥的。这里的公钥只要你能进入仓库你就可以随便查看拿走,私钥则是有密码的,只允许有权限的人查看拿走。
Keytool 是一个JAVA环境下的安全钥匙与证书的管理工具,Keytool将密钥(key)和证书(certificates)存在一个称为keystore 的文件(受密码保护)中。
在keystore里,包含两种数据:
密钥实体(Key entity)——密钥(secretkey)又或者是私钥和配对公钥(采用非对称加密)
可信任的证书实体(trustedcertificate entries)——只包含公钥
一、使用工具KeyTool(JDK自带),生成JKS
1、生成JKS文件(密钥对)
keytool -genkey -keyalg RSA -keysize 1024 -validity 365 -dname "CN=test, OU=test,O=test, L=shanghai, ST=shanghai, C=CN" -alias csii_key -keypass 888888 -keystore csii.jks -storepass 123456
CN=(名字与姓氏), OU=(组织单位名称), O=(组织名称), L=(城市或区域名称),ST=(州或省份名称), C=(单位的两字母国家代码)
2、读取JKS文件信息
keytool -list -v -keystore csii.jks -storepass 123456
缺省情况下,-list 命令打印证书的 MD5 指纹。
而如果指定了 -v 选项,将以可读格式打印证书,如果指定了 -rfc 选项,将以可打印的编码格式输出证书。
3、提取公钥JKS
1)导出公钥到证书中(cer文件)
keytool -export -alias csii_key -keystore csii.jks -storepass 123456 -file csii.cer
2)将服务端证书(公钥),导入客户端密钥库中
keytool -import -alias csii_key -file csii.cer -keystore csii_pub.jks -storepass 123456
(保存时,需要设置密钥库密码,且此时不能少于6位)
至此,私钥JKS、公钥JKS文件都已经生成好了,生成文件如下:
4、Java使用JKS文件,示例代码
1)使用私钥签名
//a. 创建针对jks文件的输入流
InputStream inputStream = new FileInputStream(cafile);
//CA 文件名 如: D:/zyt/tmp/online.jks
//b. 创建KeyStore实例 (store_password密钥库密码)
KeyStore keyStore = KeyStore.getInstance("JKS");
keyStore.load(inputStream,store_password.toCharArray());
//c. 获取私钥 (alias 为私钥别名,password为私钥密码)
PrivateKey pk = keyStore.getKey(alias,password.toCharArray());
//d. 用私钥对数据签名
//获取Signature实例,指定签名算法(本例使用MD5withRSA,可自选)
Signaturedsa = Signature.getInstance("MD5withRSA");
//加载私钥
dsa.initSign(privateKey);
//更新待签名的数据
dsa.update(data.getBytes());
//进行签名
byte[] sig = dsa.sign();
//转换成十六进制字符串,作为最终的签名数据
return byteToHex(sig);
备注:上述字节数组即签名后的数据,可将该字节数组转换成十六进制字符串,此处不再赘述,直接去问谷老师吧。
2)使用公钥验签
//a. 创建针对jks文件的输入流
同上
//b. 创建KeyStore实例
同上
//c. 获取公钥 (alias 为公钥别名)
PublicKey pubKey= keyStore.getCertificate(alias).getPublicKey();
//d. 公钥进行验签
//获取Signature实例,指定签名算法(与之前一致)
Signaturedsa = Signature.getInstance("MD5withRSA");
//加载公钥
dsa.initVerify(publicKey);
//更新原数据
dsa.update(orgData.getBytes());
//将签名数据从十六进制字符串转回字节数组
byte sig[] =hexToByte(signData);
//公钥验签(true-验签通过;false-验签失败)
return dsa.verify(sig);