zoukankan      html  css  js  c++  java
  • 【转载】OpenSSL 提取 pfx 数字证书公钥与私钥

    转自https://www.cnblogs.com/Irving/p/9551110.html

    OpenSSL 提取 pfx 数字证书公钥与私钥

     

    由于之前生产环境已经使用了 Identityserver4 用来做授权与认证的服务,而新项目采用 Spring Cloud 微服务体系,一方面 Spring Cloud 官方暂时只支持 OAuth2.0 协议,还不支持 OpenID Connect 协议(由于考虑到前项目后端分离登陆安全相关的功能已经做好了,不考虑再次修改 Spring Security 二次开发与其他开源框架如:Keycloak);另外默认 Identityserver4  也支持 JwtToken ,现在的思路是登陆使用 Identityserver4  的 OpenID Connect 协议认证,授权是在 Zuul 网关中获得 Identityserver4 服务端的公钥从而进行验签,所以就有了这篇文章。

    创建证书

    复制代码
    #生成私钥文件
    openssl genrsa -out idsrv4.key 2048
    #创建证书签名请求文件 CSR(Certificate Signing Request),用于提交给证书颁发机构(即 Certification Authority (CA))即对证书签名,申请一个数字证书。
    openssl req -new -key idsrv4.key -out idsrv4.csr
    #生成自签名证书(证书颁发机构(CA)签名后的证书,因为自己做测试那么证书的申请机构和颁发机构都是自己,crt 证书包含持有人的信息,持有人的公钥,以及签署者的签名等信息。当用户安装了证书之后,便意味着信任了这份证书,同时拥有了其中的公钥。)
    openssl x509 -req -days 365 -in idsrv4.csr -signkey idsrv4.key -out idsrv4.crt
    #自签名证书与私匙合并成一个文件
    openssl pkcs12 -export -in idsrv4.crt -inkey idsrv4.key -out idsrv4.pfx
    
    或
    openssl req -newkey rsa:2048 -nodes -keyout idsrv4.key -x509 -days 365 -out idsrv4.cer
    openssl pkcs12 -export -in idsrv4.cer -inkey idsrv4.key -out idsrv4.pfx
    复制代码

    OpenSSL 提取 pfx 证书公钥与私钥

    复制代码
    从pfx证书中提取密钥信息,并转换为key格式(pfx使用pkcs12模式补足)
    提取密钥对(如果pfx证书已加密,会提示输入密码)
    openssl pkcs12 -in idsrv4.pfx -nocerts -nodes -out idsrv4.key
    从密钥对提取公钥
    openssl rsa -in idsrv4.key -pubout -out idsrv4_pub.key
    从密钥对提取私钥
    openssl rsa -in  idsrv4.key -out idsrv4_pri.key
    因为RSA算法使用的是 pkcs8 模式补足,需要对提取的私钥进一步处理得到最终私钥
    openssl pkcs8 -topk8 -inform PEM -in idsrv4_pri.key -outform PEM -nocrypt
    复制代码

    代码方式获取

    复制代码
    public class PFXUtil {
    
        /**
         * 获取RSA算法的keyFactory
         *
         * @return
         */
        private static KeyFactory getKeyFactory() throws Exception {
            return getKeyFactory("RSA");
        }
    
        /**
         * 获取指定算法的keyFactory
         *
         * @param algorithm
         * @return
         */
        private static KeyFactory getKeyFactory(String algorithm) throws Exception {
            KeyFactory keyFactory = KeyFactory.getInstance(algorithm);
            return keyFactory;
        }
    
        /**
         * 根据pfx证书获取keyStore
         *
         * @param pfxData
         * @param password
         * @return
         * @throws Exception
         */
        private static KeyStore getKeyStore(byte[] pfxData, String password) throws Exception {
            KeyStore keystore = KeyStore.getInstance("PKCS12");
            keystore.load(new ByteArrayInputStream(pfxData), password.toCharArray());
            return keystore;
        }
    
        /**
         * 根据pfx证书得到私钥
         *
         * @param pfxData
         * @param password
         * @throws Exception
         */
        public static PrivateKey getPrivateKeyByPfx(byte[] pfxData, String password) throws Exception {
            PrivateKey privateKey = null;
            KeyStore keystore = getKeyStore(pfxData, password);
            Enumeration<String> enums = keystore.aliases();
            String keyAlias = "";
            while (enums.hasMoreElements()) {
                keyAlias = enums.nextElement();
                if (keystore.isKeyEntry(keyAlias)) {
                    privateKey = (PrivateKey) keystore.getKey(keyAlias, password.toCharArray());
                }
            }
            return privateKey;
        }
    
        /**
         * 根据pfx证书得到私钥
         *
         * @param pfxPath
         * @param password
         * @return
         * @throws Exception
         */
        public static PrivateKey getPrivateKeyByPfx(String pfxPath, String password) throws Exception {
            File pfxFile = new File(pfxPath);
            return getPrivateKeyByPfx(FileUtils.readFileToByteArray(pfxFile), password);
        }
    
        /**
         * 根据私钥字节数组获取私钥对象
         *
         * @param privateKeyByte
         * @return
         * @throws Exception
         */
        public static PrivateKey getPrivateKey(byte[] privateKeyByte) throws Exception {
            PrivateKey privateKey = null;
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(privateKeyByte);
            KeyFactory keyFactory = getKeyFactory();
            privateKey = keyFactory.generatePrivate(keySpec);
            return privateKey;
        }
    
        /**
         * 根据私钥Base64字符串获取私钥对象
         *
         * @param privateKeyStr
         * @return
         * @throws Exception
         */
        public static PrivateKey getPrivateKey(String privateKeyStr) throws Exception {
            byte[] privateKeyByte = Base64.decodeBase64(privateKeyStr);
            return getPrivateKey(privateKeyByte);
        }
    
        /**
         * 根据公钥字节数组获取公钥
         *
         * @param publicKeyByte 公钥字节数组
         * @return
         * @throws Exception
         */
        public static PublicKey getPublicKey(byte[] publicKeyByte) throws Exception {
            PublicKey publicKey = null;
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(publicKeyByte);
            KeyFactory keyFactory = getKeyFactory();
            publicKey = keyFactory.generatePublic(keySpec);
            return publicKey;
        }
    
        /**
         * 根据公钥base64字符串获取公钥
         *
         * @param publicKeyStr Base64编码后的公钥字节数组
         * @return
         * @throws Exception
         */
        public static PublicKey getPublicKey(String publicKeyStr) throws Exception {
            byte[] publicKeyByte = Base64.decodeBase64(publicKeyStr);
            return getPublicKey(publicKeyByte);
        }
    
        /**
         * 根据pfx证书获取证书对象
         *
         * @param pfxData  pfx的字节数组
         * @param password pfx证书密码
         * @return
         * @throws Exception
         */
        public static X509Certificate getX509Certificate(byte[] pfxData, String password) throws Exception {
            X509Certificate x509Certificate = null;
            KeyStore keystore = getKeyStore(pfxData, password);
            Enumeration<String> enums = keystore.aliases();
            String keyAlias = "";
            while (enums.hasMoreElements()) {
                keyAlias = enums.nextElement();
                if (keystore.isKeyEntry(keyAlias)) {
                    x509Certificate = (X509Certificate) keystore.getCertificate(keyAlias);
                }
            }
            return x509Certificate;
        }
    
        /**
         * 根据pfx证书获取证书对象
         *
         * @param pfxPath  pfx证书路径
         * @param password pfx证书密码
         * @return
         * @throws Exception
         */
        public static X509Certificate getX509Certificate(String pfxPath, String password) throws Exception {
            File pfxFile = new File(pfxPath);
            return getX509Certificate(FileUtils.readFileToByteArray(pfxFile), password);
        }
    
        //生成pkcs12
    
        /**
         * 根据私钥、公钥证书、密码生成pkcs12
         *
         * @param privateKey      私钥
         * @param x509Certificate 公钥证书
         * @param password        需要设置的密钥
         * @return
         * @throws Exception
         */
        public static byte[] generatorPkcx12(PrivateKey privateKey, X509Certificate x509Certificate, String password)
                throws Exception {
            Certificate[] chain = {x509Certificate};
            KeyStore keystore = KeyStore.getInstance("PKCS12");
            keystore.load(null, password.toCharArray());
            keystore.setKeyEntry(x509Certificate.getSerialNumber().toString(), privateKey, password.toCharArray(), chain);
            ByteArrayOutputStream bytesos = new ByteArrayOutputStream();
            keystore.store(bytesos, password.toCharArray());
            byte[] bytes = bytesos.toByteArray();
            return bytes;
        }
    
        //合成pfx
    
        /**
         * 根据私钥、公钥证书、密钥,保存为pfx文件
         *
         * @param privateKey      私钥
         * @param x509Certificate 公钥证书
         * @param password        打开pfx的密钥
         * @param saveFile        保存的文件
         * @return
         * @throws Exception
         */
        public static String generatorPFX(PrivateKey privateKey, X509Certificate x509Certificate, String password, File
                saveFile) throws Exception {
            //判断文件是否存在
            if (!saveFile.exists()) {
                //判断文件的目录是否存在
                if (!saveFile.getParentFile().exists()) {
                    saveFile.getParentFile().mkdirs();
                }
                saveFile.createNewFile();
            }
            byte[] pkcs12Byte = generatorPkcx12(privateKey, x509Certificate, password);
            FileUtils.writeByteArrayToFile(saveFile, pkcs12Byte);
            return saveFile.getPath();
        }
    }
    
    public class TestRsa {
    
        @Test
        public void contextLoads() {
            String pfxPath ="D:\github\SecuringForWebAPI\IdSrv4.HostSrv\Certs\idsrv4.pfx";
            String password = "123456";
            try {
                //私钥:pfx文件中获取私钥对象
                PrivateKey privateKey  = getPrivateKeyByPfx(pfxPath, password);
                byte[] privateKeyByte = privateKey.getEncoded();
                String privateKeyStr = Base64.encodeBase64String(privateKeyByte);
                System.out.println("私钥Base64字符串:" + privateKeyStr);
                //=====私钥Base64字符串转私钥对象
                PrivateKey privateKey2 = getPrivateKey(privateKeyStr);
                System.out.println("私钥Base64字符串2:" + Base64.encodeBase64String(privateKey2.getEncoded()));
                //证书:从pfx文件中获取证书对象
                X509Certificate certificate = getX509Certificate(pfxPath, password);
                System.out.println("证书主题:" + certificate.getSubjectDN().getName());
                String publicKeyStr = Base64.encodeBase64String(certificate.getPublicKey().getEncoded());
                System.out.println("公钥Base64字符串:" + publicKeyStr);
                //=====根据公钥Base64字符串获取公钥对象
                System.out.println("公钥Base64字符串2:" + Base64.encodeBase64String(getPublicKey(publicKeyStr).getEncoded()));
    //        //PFX:合成pfx(需要私钥、公钥证书)
    //        String savePath = generatorPFX(privateKey, certificate, "1", new File
    //                ("C:\Users\irving\Desktop\idrv4.pfx"));
    //        System.out.println(savePath);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    复制代码

    REFER:
    OpenSSL使用文档
    https://github.com/KaiZhang890/openssl-howto

  • 相关阅读:
    聚集索引
    第一天 尝试Thread
    sql 分区函数
    sql 查询表定义
    千万数量级分页存储过程
    成语解释
    sql 分组查询满足条件所以数据
    sql存储过程
    联表更新的反思
    从表保存了主表的id,以分号分隔,怎么样用一条sql搞定主表满足条件的查询? 不希望单独写存储过程,或者后台拆成int后传进来,就一条sql 搞定,一条
  • 原文地址:https://www.cnblogs.com/heben/p/10470895.html
Copyright © 2011-2022 走看看