证书

     通过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;
    }
}

 

 

 

 

 

 

 

 

 

 

        

 

posted on 2022-04-13 22:14  溪水静幽  阅读(206)  评论(0)    收藏  举报