证书
通过Java Development Kit (JDK)工具包中的Keytool工具,生成Java Keystore(JKS)格式的证书文件,使用OpenSSL工具提供的密码库,生成PEM、KEY、CRT等格式的证书文件
证书格式
-
.DER或.CER文件: 证书文件是二进制格式,只含有证书信息,不包含私钥
-
*.CRT文件: 证书文件可以是二进制格式,可以是文本格式,一般均为文本格式,功能与 .DER及.CER证书文件相同
-
*.PEM文件: 证书文件一般是文本格式,可以存放证书或私钥,或者两者都包含。 .PEM 文件如果只包含私钥,一般用.KEY文件代替
-
.PFX或.P12文件: 证书文件是二进制格式,同时包含证书和私钥且一般有密码保护
KeyTool 管理证书
KeyTool与本地密钥库相关联,将私钥存于密钥库,公钥则以数字证书输出。KeyTool位于JDK目录下的bin目录中,需要通过命令行进行相应的操作。
1)构建自签名证书
申请数字证书之前,需要在密钥库中以别名的方式生成本地数字证书,建立相应的加密算法,密钥,有效期等信息。
keytool -genkeypair -keyalg RSA -keysize 2048 -sigalg SHA1withRSA -validity 3600 -alias myCertificate -keystore myKeystore.keystore
参数含义
-genkeypair 表示生成密钥对 -keyalg 指定密钥算法,这里是RSA -keysize 指定密钥长度,默认1024,这里指定2048 -sigal 指定签名算法,这里是SHA1withRSA -validity 指定有效期,单位为天 -alias 指定别名 -keystore 指定密钥库存储位置
-dname:指定证书拥有者信息。例如: "CN=名字与姓氏,OU=组织单位名称,O=组织名称,L=城市或区域名称,ST=州或省份名称,C=单位的两字母国家代码";
注意:一个keystore应该是可以存储多套<私钥-数字证书>的信息,通过别名来区分

上述操作后,密钥库中已经创建数字证书。虽然数字证书并没有经过CA认证,但并不影响使用。可将证书导出,发送给合作伙伴进行加密交互
keytool -exportcert -alias myCertificate -keystore myKeystore.keystore -file myCer.cer -rfc
-exportcert 表示证书导出操作 -alias 指定别名 -keystore 指定密钥库文件 -file 指定导出证书的文件路径 -rfc 指定以Base64编码格式输出
打印证书
keytool -printcert -file myCer.cer

2)构建CA签发证书
如果要获取CA机构的数字证书,需要将数字证书签发申请(CSR)导出,经由CA机构认证并颁发,将认证后的证书导入本地密钥库和信息库。
-certreq 表示数字证书申请操作 -alias 指定别名 -keystore 指定密钥库文件路径 -file 指定导出申请的路径 -v 详细信息

获得签发的数字证书后,需要将其导入信任库。
keytool -importcert -trustcacerts -alias myCertificate -file myCer.cer -keystore myKeystore.keystore
查看证书
keytool -list -alias myCertificate -keystore myKeystore.keystore

4. 证书使用
数据导出场景:服务端需要将证书给B,同时用私钥加密数据,生成签名,导出到文件中,客户端用收到的数字证书进行解密和验签
public class MyCertificate { private static final String STORE_PASS = "123456"; private static final String PASS_WORD = "12345678"; private static final String ALIAS = "myCertificate"; private static final String KEYSTORE_PATH = "D:\\certificate\\myKeystore.keystore"; private static final String CERT_PATH = "D:\\certificate\\myCer.cer"; private static final String PLAIN_TEXT = "the most greatest man in the country"; private static final String CERT_TYPE = "X.509"; public static void main(String[] args) throws IOException { /** * 服务端 */ KeyStore keyStore = getKeyStore(STORE_PASS, KEYSTORE_PATH); PrivateKey privateKey = getPrivateKey(keyStore, ALIAS, PASS_WORD); X509Certificate certificate = getCertificateByKeystore(keyStore, ALIAS); /** * 加密和签名 */ byte[] encodeText = encode(PLAIN_TEXT.getBytes(), privateKey); byte[] signature = sign(certificate, privateKey, PLAIN_TEXT.getBytes()); /** *客户端收到服务端的密文和签名 */ X509Certificate receiveCertificate = getCertificateByCertPath(CERT_PATH, CERT_TYPE); PublicKey publicKey = getPublicKey(receiveCertificate); byte[] decodeText = decode(encodeText, publicKey); System.out.println("Decoded Text:" + new String(decodeText)); System.out.println("Signature is:" + verify(receiveCertificate, decodeText, signature)); } /** * 验证、公钥包含在证书里面 * * @param certificate * @param decodeText * @param receivedignature * @return */ public static boolean verify(X509Certificate certificate, byte[] decodeText, final byte[] receivedignature) { try { Signature signature = Signature.getInstance(certificate.getSigAlgName()); signature.initVerify(certificate); signature.update(decodeText); return signature.verify(receivedignature); } catch (NoSuchAlgorithmException | SignatureException | InvalidKeyException e) { e.printStackTrace(); } return false; } /** * 加载密钥库 * * @param storePass * @param keyStorePath * @return */ public static KeyStore getKeyStore(String storePass, String keyStorePath) throws IOException { InputStream inputStream = null; try { KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType()); inputStream = new FileInputStream(keyStorePath); keyStore.load(inputStream, storePass.toCharArray()); return keyStore; } catch (KeyStoreException | IOException | NoSuchAlgorithmException | CertificateException e) { e.printStackTrace(); } finally { if (null != inputStream) { inputStream.close(); } } return null; } /** * 获取私钥 * * @param keyStore * @param alias * @param password * @return */ public static PrivateKey getPrivateKey(KeyStore keyStore, String alias, String password) { try { return (PrivateKey) keyStore.getKey(alias, password.toCharArray()); } catch (UnrecoverableKeyException | NoSuchAlgorithmException | KeyStoreException e) { e.printStackTrace(); } return null; } /** * 获取公钥 * * @param certificate * @return */ public static PublicKey getPublicKey(Certificate certificate) { return certificate.getPublicKey(); } /** * 通过密钥库获取数字证书 * * @param keyStore * @param alias * @return */ public static X509Certificate getCertificateByKeystore(KeyStore keyStore, String alias) { try { return (X509Certificate) keyStore.getCertificate(alias); } catch (KeyStoreException e) { e.printStackTrace(); } return null; } /** * 密钥,密钥是可以获取到适合的算法 * * @param plainText * @param privateKey * @return */ public static byte[] encode(byte[] plainText, PrivateKey privateKey) { try { Cipher cipher = Cipher.getInstance(privateKey.getAlgorithm()); cipher.init(Cipher.ENCRYPT_MODE, privateKey); return cipher.doFinal(plainText); } catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) { e.printStackTrace(); } return null; } /** * 从证书获取加密算法,进行签名 * * @param certificate * @param privateKey * @param plainText * @return */ public static byte[] sign(X509Certificate certificate, PrivateKey privateKey, byte[] plainText) { try { Signature signature = Signature.getInstance(certificate.getSigAlgName()); signature.initSign(privateKey); signature.update(plainText); return signature.sign(); } catch (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) { e.printStackTrace(); } return null; } public static X509Certificate getCertificateByCertPath(String path, String certType) throws IOException { InputStream inputStream = null; try { CertificateFactory factory = CertificateFactory.getInstance(certType); inputStream = new FileInputStream(path); Certificate certificate = factory.generateCertificate(inputStream); return (X509Certificate) certificate; } catch (CertificateException | FileNotFoundException e) { e.printStackTrace(); } finally { if (null != inputStream) { inputStream.close(); } } return null; } /** * 密钥可以获取适用的算法 * * @param encodedText * @param publicKey * @return */ public static byte[] decode(byte[] encodedText, PublicKey publicKey) { try { Cipher cipher = Cipher.getInstance(publicKey.getAlgorithm()); cipher.init(Cipher.DECRYPT_MODE, publicKey); return cipher.doFinal(encodedText); } catch (NoSuchPaddingException | NoSuchAlgorithmException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) { e.printStackTrace(); } return null; } }
浙公网安备 33010602011771号