数字证书
程序员文章站
2022-07-12 21:59:23
...
消息摘要算法用于验证数据完整性服务,对称加密算法和非对称加密算法用于保证数据保密性服务,数字签名算法用于抗否认服务。
数字证书集合了多种密码学算法:自身带有公钥信息,可完成相应的加密/解密操作,同时,还带有数字签名,可鉴别消息来源;且自身带有消息摘由信息,可验证证书的完整性;由于证书本身含有用户身份信息,因而具有认证性。
数字证书有多种文件编码格式,主要包含CER编码(变长模式)、DER编码(定长模式)和PKCS系列等
数字证书的颁发
- 由数字证书需求方产生自己的**对
- 由数字证书需求方将算法、公钥和证书申请者身份信息传送给认证机构
- 由认证机构核实用户的身份,执行必要的步骤,确保请求确实由用户发送而来
- 由认证机构将数字证书颁发给用户
这里的认证机构如果是证书申请者本身,将获得自签名证书
加密交互
- 由客户端使用公钥对数据加密
- 由客户端向服务端发送加密数据
- 由服务器端使用私钥对数据解密
keytool–证书生成工具
环境变量的配置: 将keytool.exe所在目录添加到path下,然后就可以全局访问keytool命令
命令:
-certreq 生成证书请求
-changealias 更改条目的别名
-delete 删除条目
-exportcert 导出证书
-genkeypair 生成**对
-genseckey 生成**
-gencert 根据证书请求生成证书
-importcert 导入证书或证书链
-importpass 导入口令
-importkeystore 从其他**库导入一个或所有条目
-keypasswd 更改条目的**口令
-list 列出**库中的条目
-printcert 打印证书内容
-printcertreq 打印证书请求的内容
-printcrl 打印 CRL 文件的内容
-storepasswd 更改**库的存储口令
//如果不知道命令的用法或者想知道这些命令下有哪些参数,可以使用一下命令
keytool -command_name -help
//比如keytool certreq -help
选项:
-alias <alias> 要处理的条目的别名
-sigalg <sigalg> 签名算法名称
-file <filename> 输出文件名
-keypass <arg> **口令
-keystore <keystore> **库名称
-dname <dname> 唯一判别名
-storepass <arg> **库口令
-storetype <storetype> **库类型
-providername <providername> 提供方名称
-providerclass <providerclass> 提供方类名
-providerarg <arg> 提供方参数
-providerpath <pathlist> 提供方类路径
-v 详细输出
-protected 通过受保护的机制的口令
生成本地的证书和keystore
- 生成本地证书
keytool -genkeypair -keyalg RSA -keysize 2048 -sigalg SHAwithRSA -validity 3600 -alias www.zlex.org -keystore zlex.keystore -dname "CN=www.zlex,org,OU=zlex,O=zlex,L=zlex,L=BJ,ST=BJ,C=CN"
- 导出数字证书
keytool -exportcert -alias www.zlex.org -keystore zlex.keystore -file zlex.cer -rfc
- 打印证书
keytool -printcert -file zlex.cer
- 导出数字证书签发申请
keytool -certreq -alias www.zlex.org -keystore zlex.keystore -file zlex.csr -v
证书的使用
import javax.crypto.Cipher;
import java.io.FileInputStream;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
public class CertCoder {
//证书类型x509
public static final String CERT_TYPE = "x.509";
/**
* 由keyStore获得私钥
* @param keyStorePath **库路径
* @param alias 别名
* @param pwd 密码
* @return 私钥
* @throws Exception
*/
private static PrivateKey getPrivateKeyByKeyStore(String keyStorePath,String alias,String pwd) throws Exception {
//获取**库
KeyStore ks = getKeyStore(keyStorePath,pwd);
//获得私钥
return (PrivateKey)ks.getKey(alias,pwd.toCharArray());
}
/**
* 由证书获得公钥
* @param certPath 证书路径
* @return 公钥
* @throws Exception
*/
private static PublicKey getPublicKeyByKeyStore(String certPath) throws Exception {
//获得证书
Certificate certificate = getCertificate(certPath);
//获得公钥
return certificate.getPublicKey();
}
/**
* 获得证书
* @param certPath 证书路径
* @return 证书
*/
private static Certificate getCertificate(String certPath) throws Exception {
//实例化证书工厂
CertificateFactory factory = CertificateFactory.getInstance(CERT_TYPE);
//获取证书文件流
FileInputStream fis = new FileInputStream(certPath);
//生成证书
Certificate certificate = factory.generateCertificate(fis);
//关闭文件流
fis.close();
return certificate;
}
/**
* 获得证书
* @param keyStorePath **库路径
* @param alias 别名
* @param password 密码
* @return 证书
* @throws Exception
*/
private static Certificate getCertificate(String keyStorePath,String alias,String password) throws Exception {
//获得**库
KeyStore keyStore = getKeyStore(keyStorePath,password);
//获得证书
return keyStore.getCertificate(alias);
}
/**
* 获取KeyStore
* @param keyStorePath 路径
* @param pwd 密码
* @return KeyStore
* @throws Exception
*/
private static KeyStore getKeyStore(String keyStorePath, String pwd) throws Exception {
//实例化**库
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
//获得**库文件流
FileInputStream is = new FileInputStream(keyStorePath);
//加载**库
keyStore.load(is,pwd.toCharArray());
//关闭文件流
is.close();
return keyStore;
}
/**
* 私钥加密
* @param data 待加密数据
* @param keyStorePath **库路径
* @param alias 别名
* @param pwd 密码
* @return 加密数据
* @throws Exception
*/
public static byte[] encryptByPrivateKey(byte[] data,String keyStorePath,String alias,String pwd) throws Exception {
//获取私钥
PrivateKey privateKey = getPrivateKeyByKeyStore(keyStorePath,alias,pwd);
//对数据加密
Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE,privateKey);
return cipher.doFinal(data);
}
/**
* 私钥解密
* @param data 待解密数据
* @param keyStorePath **库路径
* @param alias 别名
* @param pwd 密码
* @return 解密后的数据
* @throws Exception
*/
public static byte[] decryptByPrivateKey(byte[] data,String keyStorePath,String alias,String pwd) throws Exception {
//获取私钥
PrivateKey privateKey = getPrivateKeyByKeyStore(keyStorePath,alias,pwd);
//解密操作
Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE,privateKey);
return cipher.doFinal(data);
}
/**
* 公钥加密
* @param data 代加密数据
* @param certPath 证书路径
* @return 密文
* @throws Exception
*/
public static byte[] encryptByPublicKey(byte[] data,String certPath) throws Exception {
PublicKey publicKey = getPublicKeyByKeyStore(certPath);
Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE,publicKey);
return cipher.doFinal(data);
}
/**
* 公钥解密
* @param data 待解密数据
* @param cerPath 证书路径
* @return 明文
* @throws Exception
*/
public static byte[] decryptByOublicKey(byte[] data,String cerPath) throws Exception {
PublicKey publicKey = getPublicKeyByKeyStore(cerPath);
Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE,publicKey);
return cipher.doFinal(data);
}
/**
* 由证书构建签名
* @param sign 待签名数据
* @param keyStorePath **库路径
* @param alias 别名
* @param pwd 密码
* @return
* @throws Exception
*/
public static byte[] sign(byte[] sign,String keyStorePath,String alias,String pwd) throws Exception {
//获取证书
X509Certificate certificate = (X509Certificate) getCertificate(keyStorePath,alias,pwd);
//构建签名
Signature signature = Signature.getInstance(certificate.getSigAlgName());
//获取私钥
PrivateKey privateKey = getPrivateKeyByKeyStore(keyStorePath,alias,pwd);
//初始化签名,有私钥构建
signature.initSign(privateKey);
signature.update(sign);
return signature.sign();
}
/**
* 认证
* @param data 数据
* @param sign 签名
* @param cerPath 证书路径
* @return 数据是否有改变
* @throws Exception
*/
public static boolean vertify(byte[] data,byte[] sign,String cerPath) throws Exception {
//获取证书
X509Certificate certificate = (X509Certificate) getCertificate(cerPath);
//获取公钥
PublicKey publicKey = certificate.getPublicKey();
Signature signature = Signature.getInstance(certificate.getSigAlgName());
signature.initVerify(publicKey);
signature.update(data);
return signature.verify(sign);
}
public static void main(String[] args) throws Exception {
String pwd = "Lu3jianL6";
String alias = "www.zlex.org";
String cerPath = "D:\\Program Files\\Java\\jdk1.8.0_201\\bin\\zlex.cer";
String keyStorePath = "D:\\Program Files\\Java\\jdk1.8.0_201\\bin\\zlex.keystore";
byte[] data = "心里有思念的人就不会孤独".getBytes("utf-8");
System.err.println("公钥加密,私钥解密");
byte[] bytes = encryptByPublicKey(data, cerPath);
System.out.println("公钥加密:" + new String(bytes,"utf-8"));
byte[] result = decryptByPrivateKey(bytes, keyStorePath, alias, pwd);
System.out.println("私钥解密:"+new String(result,"utf-8"));
System.err.println("私钥加密,公钥解密");
byte[] result1 = encryptByPrivateKey(data, keyStorePath, alias, pwd);
System.out.println("私钥加密:" + new String(result1,"utf-8"));
byte[] bytes1 = decryptByOublicKey(result1, cerPath);
System.out.println("公钥解密:" + new String(bytes1,"utf-8"));
System.err.println("数字签名");
byte[] sign = sign(data,keyStorePath,alias,pwd);
System.out.println("签名:" + new String(sign,"utf-8"));
System.out.println(vertify(data,sign,cerPath));
}
}
//执行结果
公钥加密,私钥解密
???H[:A??D`U???J?*??..7?S??D?v8??O????D?*????x? o? "H*#H??`T?v???\rf???a?H??*a?Av?c?0'?MN?PQ?O???1.VR?at:hV?zY?==?/?ī,???????`???$(?^?s 7/??2?'??5??Tu0??Js|9K*E%?A??C?ea?29
?{?SM????^ ????????lf)???+???k??I?$?8?
私钥加密,公钥解密
私钥解密:心里有思念的人就不会孤独
私钥加密:u?)???
-l?x?n???EQ?N/??*????x?9?\w?i}ZZ??K??v?k???????$??j?z?h?/f`???8L?$<s#??<??8se?ы ē?*J???R??^??IZz{????A??2I4???%? P????????!?o??XjRBryMj?Z?X
w& ?h???R?????WR???>>??.\G?q????a?A??$???#
%????????v??L`)?????
公钥解密:心里有思念的人就不会孤独
数字签名
签名:^???<C??WqN:A[?WM?t??+?RP?X??7?_<???Z?R,?i8%qЬa??!?>G-6U??|??6?1r9|??hQ????h? z?5???O* H9??N
v?F2~s6I???DX??R^?@)A?NY/g?*??oQU?I@w=??
??hDv? h-?????lO???#?O?3?`?c?P??X?u5TaO??Cz4??p?1???@6KS???5?!<
y<?34?x$?R3n?G
true
应用场景
主要应用于电子商务活动和电子政务活动