证书的版本信息;
证书的序列号,每个证书都有一个唯一的证书序列号;
证书所使用的签名算法;
证书的发行机构名称,命名规则一般采用X.500格式;
证书的有效期,通用的证书一般采用UTC时间格式,它的计时范围为1950-2049;
证书所有人的名称,命名规则一般采用X.500格式;
证书所有人的公开密钥;
证书发行者对证书的签名。
证书的序列号,每个证书都有一个唯一的证书序列号;
证书所使用的签名算法;
证书的发行机构名称,命名规则一般采用X.500格式;
证书的有效期,通用的证书一般采用UTC时间格式,它的计时范围为1950-2049;
证书所有人的名称,命名规则一般采用X.500格式;
证书所有人的公开密钥;
证书发行者对证书的签名。
就是说主要包含签发机构的签名和证书所有人的公钥
数据交互时,证书所有人将自己的数字证书授权给一些人,这些人可以通过签发机构的公钥确认签发机构,证书所有人的公钥认证数据
一、数字证书:
一个字,太麻烦了
消息摘要算法----完整性
对称非对称加密-保密性
数字签名----------抗否认性
数字证书----------集合多种密码学算法:
自带:
①公钥信息-----------------完成加解密
②数字签名-----------------鉴别消息来源
③摘要信息-----------------完整性
④用户身份信息-----------认证性
为发布公钥提供了一种途径,成为加密算法及公钥载体
数字证书采用了公钥基础设施:
非对称加密算法:数据加密/解密->数据机密性
数字签名算法:数据签名、验证->数据完整性、抗否认性
消息摘要算法:数字证书摘要->数字证书完整性
二、现在我们用keytool产生的密钥库和证书为例:
注意几个点:
1、keytool最后产生了zlex.cer和zlex.keystore两个东西
2、数字证书(certificate)直接能得到公钥;
3、要得到私钥要用密钥库及密码;
private static PublicKey getPublicKeyByCertificate(String certificatePath) throws CertificateException, IOException{
Certificate certificate = getCertificate(certificatePath);
return certificate.getPublicKey();
}
private static PrivateKey getPrivateKeyByKeyStore(String keyStorePath,String alias,String password) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, UnrecoverableKeyException{
KeyStore ks = getKeyStore(keyStorePath,password);
return (PrivateKey)ks.getKey(alias, password.toCharArray());
}
private static Certificate getCertificate(String certificatePath) throws CertificateException, IOException{
CertificateFactory certificateFactory = CertificateFactory.getInstance(CERT_TYPE);
FileInputStream is = new FileInputStream(certificatePath);
Certificate certificate = certificateFactory.generateCertificate(is);
is.close();
return certificate;
}
加载密钥库:ks.load(文件流,密码)
private static KeyStore getKeyStore(String keyStorePath, String password) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());//!!!
FileInputStream is = new FileInputStream(keyStorePath);
ks.load(is, password.toCharArray());
is.close();
return ks;
}
注意getInstance后面是默认参数!!别傻到习惯性的来个定义好的常量
密钥库获得数字证书构建数字签名对象:
public static byte[] sign(byte[] data,String keyStorePath,String alias,String password) throws NoSuchAlgorithmException, KeyStoreException, CertificateException, IOException, UnrecoverableKeyException, InvalidKeyException, SignatureException{
X509Certificate x509Certificate = (X509Certificate) getCertificate(keyStorePath,alias,password);
Signature signature = Signature.getInstance(x509Certificate.getSigAlgName());
PrivateKey privateKey = getPrivateKeyByKeyStore(keyStorePath,alias,password);
signature.initSign(privateKey);
signature.update(data);
return signature.sign();
}
Signature signature = Signature.getInstance(x509Certificate.getSigAlgName());
总的来说,我们能从密钥库拿到私钥、数字证书;数字证书带有公钥,能产生数字签名
三、实现:
1.Junit测试用例:
public class CertificateCoderTest extends TestCase {
private String password = "123456";
private String alias="www.zlex.org";
private String certificatePath="F:/Java/jdk1.8.0/bin/zlex.cer";
private String keyStorePath="F:\\Java\\jdk1.8.0\\bin\\zlex.keystore";
@Test
public void test1() throws InvalidKeyException, CertificateException, NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, IOException, UnrecoverableKeyException, KeyStoreException{
System.err.println("公钥加密,私钥解密");
String inputStr = "数字证书";
byte[] data = inputStr.getBytes();
byte[] encrypt = CertificateCoder.encryptByPublicKey(data, certificatePath);
System.err.println("加密前:\n"+inputStr);
byte[] decrypt = CertificateCoder.decryptByPrivateKey(encrypt, keyStorePath, alias, password);
String outputStr = new String(decrypt);
System.err.println("解密后:\n"+outputStr);
assertEquals(data,decrypt);
}
}
我们能看到实现简单了很多,却同时保证了数据机密性,完整性,不可否认性。这些都是数字证书的功劳;
再有就是路径的输入方法:斜杠/斜杠/
或 反斜杠\\反斜杠\\ 第一个为转义字符
除号为斜杠
2.数字证书实现类:
public abstract class CertificateCoder {
public static final String CERT_TYPE="X.509";
private static PrivateKey getPrivateKeyByKeyStore(String keyStorePath,String alias,String password) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, UnrecoverableKeyException{
KeyStore ks = getKeyStore(keyStorePath,password);
return (PrivateKey)ks.getKey(alias, password.toCharArray());
}
private static KeyStore getKeyStore(String keyStorePath, String password) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException {
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());//!!!
FileInputStream is = new FileInputStream(keyStorePath);
ks.load(is, password.toCharArray());
is.close();
return ks;
}
private static Certificate getCertificate(String certificatePath) throws CertificateException, IOException{
CertificateFactory certificateFactory = CertificateFactory.getInstance(CERT_TYPE);
FileInputStream is = new FileInputStream(certificatePath);
Certificate certificate = certificateFactory.generateCertificate(is);
is.close();
return certificate;
}
private static Certificate getCertificate(String keyStorePath,String alias,String password) throws KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException{
KeyStore ks = getKeyStore(keyStorePath,password);
return ks.getCertificate(alias);
}
private static PublicKey getPublicKeyByCertificate(String certificatePath) throws CertificateException, IOException{
Certificate certificate = getCertificate(certificatePath);
return certificate.getPublicKey();
}
public static byte[] encryptByPrivateKey(byte[] data,String keyStorePath,String alias,String password) throws UnrecoverableKeyException, KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException{
PrivateKey privateKey = getPrivateKeyByKeyStore(keyStorePath,alias,password);
Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, privateKey);
return cipher.doFinal(data);
}
public static byte[] decryptByPublicKey(byte[] data,String certificatePath) throws CertificateException, IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException{
PublicKey publicKey = getPublicKeyByCertificate(certificatePath);
Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, publicKey);
return cipher.doFinal(data);
}
public static byte[] decryptByPrivateKey(byte[] data,String keyStorePath,String alias,String password) throws UnrecoverableKeyException, KeyStoreException, NoSuchAlgorithmException, CertificateException, IOException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException{
PrivateKey privateKey = getPrivateKeyByKeyStore(keyStorePath,alias,password);
Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm());
cipher.init(Cipher.DECRYPT_MODE, privateKey);
System.err.println("in de by private");
return cipher.doFinal(data);
}
public static byte[] encryptByPublicKey(byte[] data,String certificatePath) throws CertificateException, IOException, NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IllegalBlockSizeException, BadPaddingException{
PublicKey publicKey = getPublicKeyByCertificate(certificatePath);
Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm());
cipher.init(Cipher.ENCRYPT_MODE, publicKey);
return cipher.doFinal(data);
}
public static byte[] sign(byte[] data,String keyStorePath,String alias,String password) throws NoSuchAlgorithmException, KeyStoreException, CertificateException, IOException, UnrecoverableKeyException, InvalidKeyException, SignatureException{
X509Certificate x509Certificate = (X509Certificate) getCertificate(keyStorePath,alias,password);
Signature signature = Signature.getInstance(x509Certificate.getSigAlgName());
PrivateKey privateKey = getPrivateKeyByKeyStore(keyStorePath,alias,password);
signature.initSign(privateKey);
signature.update(data);
return signature.sign();
}
public static boolean verify(byte[] data,byte[] sign, String certificatePath) throws NoSuchAlgorithmException, CertificateException, IOException, InvalidKeyException, SignatureException{
X509Certificate x509Certificate = (X509Certificate)getCertificate(certificatePath);
Signature signature = Signature.getInstance(x509Certificate.getSigAlgName());
signature.initVerify(x509Certificate);
signature.update(data);
return signature.verify(sign);
}
}