本文转自:
数字证书简介及Java编码实现
CA认证原理以及实现
java CA证书制作和代码中使用
名词大意
秘钥库:存储了
公钥
和
私钥
信息,一个秘钥库可以存储
多对
的密钥对(密钥对可以理解为就是
数字证书
),通过alias别名来取出需要的密钥对,存放于
服务器
,
xxx.keystore
文件
数字证书:只能存储
公钥
,可以从
xxxx.keystore
中导出某个
密钥对
的
公钥证书
,存放于
客户端
,
xxx.cer
文件
java使用数字证书
Java 6提供了完善的数字证书管理实现,我们几乎无需关注,仅通过操作
密钥库
和
数字证书
就可完成相应的
加密解密
和
签名验签
过程。
密钥库
管理
私钥
,
数字证书
管理
公钥
,公钥和私钥分属消息传递双方,进行
加密消息传递
。
CertificateCoder工具类
/****
* 获得私钥,获得私钥后,通过RSA算方法实现进行"私钥加密,公钥解密"和"公钥加密,私钥解密"操作
* @param keyStorePath 密钥库路径
* @param alias 别名
* @param keystore_password 秘钥库密码
* @param ca_password 证书密码
* @return 私钥
*/
private static PrivateKey getPrivateKeyByKeyStore(String keyStorePath, String alias, String keystore_password,String ca_password)throws Exception{
//获得密钥库
KeyStore ks = getKeyStore(keyStorePath,keystore_password);
//获得私钥
return (PrivateKey)ks.getKey(alias, ca_password.toCharArray());
}
/****
* 由Certificate获得公钥,获得公钥后,通过RSA算方法实现进行"私钥加密,公钥解密"和"公钥加密,私钥解密"操作
* @param certificatePath 证书路径
* @return 公钥
*/
private static PublicKey getPublicKeyByCertificate(String certificatePath)throws Exception {
//获得证书
Certificate certificate = getCertificate(certificatePath);
//获得公钥
return certificate.getPublicKey();
}
/****
* 加载数字证书,JAVA 6仅支持x.509的数字证书
* @param certificatePath 证书路径
* @return 证书
* @throws Exception
*/
private static Certificate getCertificate(String certificatePath) throws Exception{
//实例化证书工厂
CertificateFactory certificateFactory = CertificateFactory.getInstance("x.509");
//取得证书文件流
FileInputStream in = new FileInputStream(certificatePath);
//生成证书
Certificate certificate = certificateFactory.generateCertificate(in);
//关闭证书文件流
in.close();
return certificate;
}
/****
* 获得Certificate
* @param keyStorePath 密钥库路径
* @param alias 别名
* @param keystore_password 秘钥库密码
* @return 证书
* @throws Exception
*/
private static Certificate getCertificate(String keyStorePath,String alias,String keystore_password) throws Exception{
//由密钥库获得数字证书构建数字签名对象
//获得密钥库
KeyStore ks = getKeyStore(keyStorePath,keystore_password);
//获得证书
return ks.getCertificate(alias);
}
/****
* 加载密钥库,加载了以后,我们就能通过相应的方法获得私钥,也可以获得数字证书
* @param keyStorePath 密钥库路径
* @param keystore_password 密码
* @return 密钥库
* @throws Exception
*/
private static KeyStore getKeyStore(String keyStorePath,String keystore_password) throws Exception{
//实例化密钥库
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
//获得密钥库文件流
FileInputStream is = new FileInputStream(keyStorePath);
//加载密钥库
ks.load(is,keystore_password.toCharArray());
//关闭密钥库文件流
is.close();
return ks;
}
/****
* 私钥加密
* @param data 待加密的数据
* @param keyStorePath 密钥库路径
* @param alias 别名
* @param keystore_password 秘钥库密码
* @param ca_password 证书密码
* @return 加密数据
* @throws Exception
*/
public static byte[] encryptByPriateKey(byte[] data,String keyStorePath,String alias,String keystore_password,String ca_password) throws Exception{
//获得私钥
PrivateKey privateKey = getPrivateKeyByKeyStore(keyStorePath,alias,keystore_password,ca_password);
//对数据加密
Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE,privateKey);
return cipher.doFinal(data);
}
/****
* 私钥解密
* @param data 待解密数据
* @param keyStorePath 密钥库路径
* @param alias 别名
* @param keystore_password 秘钥库密码
* @param ca_password 证书密码
* @return 解密数据
* @throws Exception
*/
public static byte[] decryptByPrivateKey(byte[] data,String keyStorePath,String alias,String keystore_password,String ca_password) throws Exception{
//取得私钥
PrivateKey privateKey = getPrivateKeyByKeyStore(keyStorePath,alias,keystore_password,ca_password);
//对数据解密
Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE,privateKey);
return cipher.doFinal(data);
}
/****
* 公钥加密
* @param data 等待加密数据
* @param certificatePath 证书路径
* @return 加密数据
* @throws Exception
*/
public static byte[] encryptByPublicKey(byte[] data,String certificatePath) throws Exception{
//取得公钥
PublicKey publicKey = getPublicKeyByCertificate(certificatePath);
//对数据加密
Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE,publicKey);
return cipher.doFinal(data);
}
/****
* 公钥解密
* @param data 等待解密的数据
* @param certificatePath 证书路径
* @return 解密数据
* @throws Exception
*/
public static byte[] decryptByPublicKey(byte[] data,String certificatePath)throws Exception{
//取得公钥
PublicKey publicKey = getPublicKeyByCertificate(certificatePath);
//对数据解密
Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, publicKey);
return cipher.doFinal(data);
}
/****
* @param sign 签名
* @param keyStorePath 密钥库路径
* @param alias 别名
* @param keystore_password 秘钥库密码
* @param ca_password 证书密码
* @return 签名
* @throws Exception
*/
public static byte[] sign(byte[] sign,String keyStorePath,String alias,String keystore_password,String ca_password)throws Exception{
//获得证书
X509Certificate x509Certificate = (X509Certificate) getCertificate(keyStorePath,alias,keystore_password);
//构建签名,由证书指定签名算法
Signature signature = Signature.getInstance(x509Certificate.getSigAlgName());
//获取私钥
PrivateKey privateKey = getPrivateKeyByKeyStore(keyStorePath,alias,keystore_password,ca_password);
//初始化签名,由私钥构建
signature.initSign(privateKey);
signature.update(sign);
return signature.sign();
}
/****
* 验证签名
* @param data 数据
* @param sign 签名
* @param certificatePath 证书路径
* @return 验证通过为真
* @throws Exception
*/
public static boolean verify(byte[] data,byte[] sign,String certificatePath) throws Exception{
//获得证书
X509Certificate x509Certificate = (X509Certificate)getCertificate(certificatePath);
//由证书构建签名
Signature signature = Signature.getInstance(x509Certificate.getSigAlgName());
//由证书初始化签名,实际上是使用了证书中的公钥
signature.initVerify(x509Certificate);
signature.update(data);
return signature.verify(sign);
}
CertificateCoderTest测试类
/** 秘钥库密码. */
private static final String keystore_password = "123456";
/** 证书密码. */
private static final String ca_password = "111111";
/** 证书别名. */
private static final String alias = "ljw";
/** 密钥库文件. */
private static final String keyStorePath = "F:\\Certifacate\\ljw.keystore";
/** 数字证书文件. */
private static final String certificatePath = "F:\\Certifacate\\ljw.cer";
//我们假定密钥库文件yale.keystore存储在D盘根目录,数字证书文件yale.cer也存储在D盘根目录
/****
* 公钥加密---私钥解密
* @throws Exception
*/
@Test
public void test1() throws Exception{
System.err.println("公钥加密---私钥解密");
String inputStr = "数字证书";
byte[] data = inputStr.getBytes();
//公钥加密
byte[] encrypt = CertificateCoder.encryptByPublicKey(data, certificatePath);
//私钥解密
byte[] decrypt = CertificateCoder.decryptByPrivateKey(encrypt, keyStorePath, alias, keystore_password, ca_password);
String outputStr = new String(decrypt);
System.err.println("加密前:\n" + inputStr);
System.err.println("解密后:\n" + outputStr);
}
/****
* 私钥加密---公钥解密
* @throws Exception
*/
@Test
public void test2()throws Exception{
System.err.println("私钥加密---公钥解密");
String inputStr = "数字签名";
byte[] data = inputStr.getBytes();
//私钥加密
byte[] encodedData = CertificateCoder.encryptByPriateKey(data, keyStorePath, alias, keystore_password, ca_password);
//公钥解密
byte[] decodeData = CertificateCoder.decryptByPublicKey(encodedData, certificatePath);
String outputStr = new String (decodeData);
System.err.println("加密前:\n" + inputStr);
System.err.println("解密后:\n" + outputStr);
}
@Test
public void testSign()throws Exception{
String inputStr = "签名";
byte[] data = inputStr.getBytes();
System.err.println("私钥签名---公钥验证");
//产生签名
byte[] sign = CertificateCoder.sign(data, keyStorePath, alias, keystore_password, ca_password);
System.err.println("签名:\n" + sign);
//验证签名
boolean status = CertificateCoder.verify(data, sign, certificatePath);
System.err.println("状态:\n " + status);
}