首页 > 其他分享 >证书杂谈

证书杂谈

时间:2024-02-01 15:01:12浏览次数:31  
标签:KeyStore java 证书 杂谈 pem new import com

证书杂谈

密钥对和签名概念

不对称加密方式要求提供一个密钥对,既私钥(privateKey)公钥(publicKey).

在tls中,密钥对要求有第三方ca的签名认证,因此认证的提供方式通常为Certificate(cert.pem)Key(key.pem)

  • Certificate: Certificate中包含公钥和签名认证, 一般还有出现证书链,即可以提供多个Certificate.
    例如java.security.KeyStore.setKeyEntry(java.lang.String, java.security.Key, char[], java.security.cert.Certificate[]),可以看到可以提供一个Certificate数组.
  • Key: Key就很简单了,就是上面的私钥(privateKey)

PEM是何方神圣

pem格式比较常用,通常是base64编码的文本文件. pem并不是指私钥或者公钥什么的,它是一种文本格式,可以将公钥、私钥、证书等等base64编码后,就变成了pem文件.


JAVA中的KeyStore和KeyManager

在JAVA中,KeyStore就类似于pem一样,私钥公钥签名都能存, 通常以KeyStore的形式存储Certificate(cert.pem)Key(key.pem),还可以设置一个密码来加密这个KeyStore, 读取时要求提供密码.

可以想见,KeyStorecert.pem/key.pem是可以相互转换的. 参考

PEM -> KeyStore

/**
 * 引用 {@link com.github.dockerjava.core.util.CertificateUtils}
 */
public class PEM2KeyStore {
    public static KeyStore createKeyStore(final String keypem, final String certpem) throws NoSuchAlgorithmException,
            InvalidKeySpecException, IOException, CertificateException, KeyStoreException {
        PrivateKey privateKey = loadPrivateKey(keypem);
        requireNonNull(privateKey);
        List<Certificate> privateCertificates = loadCertificates(certpem);

        KeyStore keyStore = KeyStore.getInstance("JKS");
        keyStore.load(null);

        keyStore.setKeyEntry("docker",
                privateKey,
                "docker".toCharArray(),
                privateCertificates.toArray(new Certificate[privateCertificates.size()])
        );

        return keyStore;
    }

    /**
     * Return KeyPair from "key.pem"
     */
    @CheckForNull
    public static PrivateKey loadPrivateKey(final String keypem) throws IOException, NoSuchAlgorithmException,
            InvalidKeySpecException {
        try (StringReader certReader = new StringReader(keypem);
             BufferedReader reader = new BufferedReader(certReader)) {
            return loadPrivateKey(reader);
        }
    }

    /**
     * Return private key ("key.pem") from Reader
     */
    @CheckForNull
    public static PrivateKey loadPrivateKey(final Reader reader) throws IOException, NoSuchAlgorithmException,
            InvalidKeySpecException {
        try (PEMParser pemParser = new PEMParser(reader)) {
            Object readObject = pemParser.readObject();
            while (readObject != null) {
                PrivateKeyInfo privateKeyInfo = getPrivateKeyInfoOrNull(readObject);
                if (privateKeyInfo != null) {
                    return new JcaPEMKeyConverter().getPrivateKey(privateKeyInfo);
                }
                readObject = pemParser.readObject();
            }
        }

        return null;
    }

    /**
     * from "cert.pem" String
     */
    public static List<Certificate> loadCertificates(final String certpem) throws IOException,
            CertificateException {
        final StringReader certReader = new StringReader(certpem);
        try (BufferedReader reader = new BufferedReader(certReader)) {
            return loadCertificates(reader);
        }
    }

    /**
     * "cert.pem" from reader
     */
    public static List<Certificate> loadCertificates(final Reader reader) throws IOException,
            CertificateException {
        try (PEMParser pemParser = new PEMParser(reader)) {
            List<Certificate> certificates = new ArrayList<>();

            JcaX509CertificateConverter certificateConverter = new JcaX509CertificateConverter()
                    .setProvider(BouncyCastleProvider.PROVIDER_NAME);
            Object certObj;

            while ((certObj = pemParser.readObject()) != null) {
                if (certObj instanceof X509CertificateHolder) {
                    X509CertificateHolder certificateHolder = (X509CertificateHolder) certObj;
                    certificates.add(certificateConverter.getCertificate(certificateHolder));
                }
            }

            return certificates;
        }
    }
    
    
}

KeyStore -> pem

import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.api.exception.DockerClientException;
import com.github.dockerjava.core.DefaultDockerClientConfig;
import com.github.dockerjava.core.DockerClientImpl;
import com.github.dockerjava.core.LocalDirectorySSLConfig;
import com.github.dockerjava.core.util.CertificateUtils;
import com.github.dockerjava.httpclient5.ApacheDockerHttpClient;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.jcajce.JcaPEMWriter;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;


public class KeyStore2PEM {
    public static void KeyStore2Pem(KeyStore keyStore, File outKeyPemFile, File outCertPemFile) throws UnrecoverableKeyException, KeyStoreException, NoSuchAlgorithmException, IOException {
        PrivateKey privateKey = (PrivateKey) keyStore.getKey("docker", "docker".toCharArray());
        Certificate[] certificateChain = keyStore.getCertificateChain("docker");

        // 写入私钥文件, key.pem文件
        try (JcaPEMWriter pemWriter = new JcaPEMWriter(new FileWriter(outKeyPemFile))) {
            pemWriter.writeObject(privateKey);
        }

        // 写入证书文件, cert.pem
        try (JcaPEMWriter pemWriter = new JcaPEMWriter(new FileWriter(outCertPemFile))) {
            for (Certificate certificate : certificateChain) {
                pemWriter.writeObject(certificate);
            }
        }
    }
    
}
        


JAVA中的TrustStore和TrustManager

在JAVA中,密钥存储还分为两大类: trustStore和KeyStore. 参考
trustStore 的目的 是验证凭据 ,keyStore 的目的 是提供凭据.
trustStore 用于TrustManager, keyStore 用于KeyManager, in Java

First and major difference between trustStore and keyStore is that trustStore is used by TrustManager and keyStore is used by KeyManager class in Java. KeyManager and TrustManager performs different job in Java, TrustManager determines whether remote connection should be trusted or not i.e. whether remote party is who it claims to and KeyManager decides which authentication credentials should be sent to the remote host for authentication during SSL handshake. if you are an SSL Server you will use private key during key exchange algorithm and send certificates corresponding to your public keys to client, this certificate is acquired from keyStore. On SSL client side, if its written in Java, it will use certificates stored in trustStore to verify identity of Server.

在Java发起的https请求中,一般都要求提供trustManager来验证服务器的证书,也就是说,trustStore可以看作ca.pem的等价,是中心证书.
作为客户端在一般的https请求中是不需要提供keyManager的, 因为https是单向tls认证,只需要客户端验证服务端,而不需要服务端认证客户端.
如果启用了双向tls认证(Docker的tls verify就是这样的),那么在我们的程序发起请求时,也需要提供KeyManager,作为服务端认证客户端的认证方式.

题外话,在一些内部的调用中,使用自签名证书,往往需要忽略tls证书认证,这时候就是通过提供空的trustManager来实现忽略证书认证.

同样的, TrustStoreca.pem也是可以相互转换的

PEM -> TrustStore

/**
 * 引用 {@link com.github.dockerjava.core.util.CertificateUtils}
 */
public class PEM2TrustStore {

    /**
     * "ca.pem" from String
     */
    public static KeyStore createTrustStore(String capem) throws IOException, CertificateException,
            KeyStoreException, NoSuchAlgorithmException {
        try (Reader certReader = new StringReader(capem)) {
            return createTrustStore(certReader);
        }
    }

    /**
     * "ca.pem" from Reader
     */
    public static KeyStore createTrustStore(final Reader certReader) throws IOException, CertificateException,
            KeyStoreException, NoSuchAlgorithmException {
        try (PEMParser pemParser = new PEMParser(certReader)) {

            KeyStore trustStore = KeyStore.getInstance("JKS");
            trustStore.load(null);

            int index = 1;
            Object pemCert;

            while ((pemCert = pemParser.readObject()) != null) {
                Certificate caCertificate = new JcaX509CertificateConverter()
                        .setProvider(BouncyCastleProvider.PROVIDER_NAME)
                        .getCertificate((X509CertificateHolder) pemCert);
                trustStore.setCertificateEntry("ca-" + index, caCertificate);
                index++;
            }

            return trustStore;
        }
    }
}

TrustStore -> PEM

import com.github.dockerjava.api.DockerClient;
import com.github.dockerjava.api.exception.DockerClientException;
import com.github.dockerjava.core.DefaultDockerClientConfig;
import com.github.dockerjava.core.DockerClientImpl;
import com.github.dockerjava.core.LocalDirectorySSLConfig;
import com.github.dockerjava.core.util.CertificateUtils;
import com.github.dockerjava.httpclient5.ApacheDockerHttpClient;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.openssl.jcajce.JcaPEMWriter;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;


public class TrustStore2PEM {
    public static void KeyStore2Pem(KeyStore trustStore, File outCAPemFile) throws UnrecoverableKeyException, KeyStoreException, NoSuchAlgorithmException, IOException {
        Certificate[] certificateChain = trustStore.getCertificateChain("docker");

        // 写入证书文件, ca.pem
        try (JcaPEMWriter pemWriter = new JcaPEMWriter(new FileWriter(outCAPemFile))) {
            for (Certificate certificate : certificateChain) {
                pemWriter.writeObject(certificate);
            }
        }
    }
}

标签:KeyStore,java,证书,杂谈,pem,new,import,com
From: https://www.cnblogs.com/xiaojiluben/p/18001220

相关文章

  • npm证书过期:npm ERR! request to https://registry.npm.taobao.org/element-ui failed
    场景:使用淘宝源安装element-ui时npm证书过期报错信息如下:npmERR!codeCERT_HAS_EXPIREDnpmERR!errnoCERT_HAS_EXPIREDnpmERR!requesttohttps://registry.npm.taobao.org/element-uifailed,reason:certificatehasexpirednpmERR!Acompletelogofthisrun......
  • 生成Nginx服务器SSL证书和客户端证书
    Nginx服务器SSL证书生成passkey下面的命令用于生成一个2048bit的passkey,-passoutpass:111111用于避免交互式输入密码12345[tomcat@a02tmp]$opensslgenrsa-aes256-passoutpass:111111-outserver.pass.key2048GeneratingRSAprivatekey,2048b......
  • ClientBuilder https请求时忽略SSL证书。
    在chrome中连接https时,有时被告知不是私密链接,手动可以继续。用java代码进行https也遇到这种情况,可以 实现一个X509TrustManager接口,用于绕过验证,不用修改里面的方法附完整可用代码importorg.glassfish.jersey.jackson.JacksonFeature;importjavax.net.ssl.SSLContext;im......
  • 杂谈 —— 或许是低谷
    上个暑假去实习,导致很久没回家,到了这个假期国庆期间真的很想家。再加上在学校15号开始就需要集中住宿了,要搬家,所以就卡着15号的时间,早早回了家。 数到现在,已经在家呆了半个月了,按照自己的flag来说已经欠了16篇博客了。 上个学期12月左右可以说势头比较凶,论文中了,比赛也拿了......
  • 杂谈 1:论 [l, r] 之间的非平方数
    杂谈1:论\([l,r]\)之间的非平方数Part0例题先看一道例题;给定两个数\(l,r\),求\(l\simr\)之间有多少个数不是平方数。平方数的定义:是一个数的平方。如\(16\)是平方数,因为\(4^2=16\),\(11\)则不是,因为\(\sqrt{11}\)不为整数。数据范围:\(1\lel,r\le10^9\)......
  • PMP成绩查询及电子版证书下载
    2023年11月25日PMP考试成绩今日凌晨开始发布,按照往年的情况,成绩都是分批出的,如果暂时没查到成绩的同学请耐心等待,预计一周内成绩会全部出来。原创:厦门微思网络 【微思2002年成立,专业IT认证培训21年!】 我们主要课程:华为、思科、红帽、ORACLE、VMware、CISP、PMP等认证培训及考......
  • 使用 kubeadm 进行证书管理
    使用kubeadm进行证书管理1检查证书是否过期你可以使用check-expiration子命令来检查证书何时过期kubeadmcertscheck-expiration输出类似于以下内容:[root@k8s-master/]#kubeadmcertscheck-expiration[check-expiration]Readingconfigurationfromthecluster.......
  • windows 宝塔本地部署ssl证书
    1、使用 mkcert-v1.4.4-windows-amd64.exe参考《https本地自签名证书添加到信任证书访问》1#进入到mkcert-v1.4.4-windows-amd64.exe下载文件位置2#执行命令3./mkcert-v1.4.4-windows-amd64.exe*.game.localaiPlatform.devlocalhost127.0.......
  • SSL 数字证书的的格式
    base64base64格式可读性强强方便传输和查看例如git免密登录都这种格式opensslbase64-incert.cer-outcert.base64二进制DERDistinguishedEncodingRules通常用于表示X.509格式的证书二进制存贮和传输通常以.cer或.der为扩展名opensslx509-outform......
  • MTC证书|欧盟与英国金属类产品清关新要求
    欧盟严抓MTC认证获悉,从10月1日起,欧盟海关将严格检查所有申报HS代码为7323、7326等含有金属的货物,所有进口国家的金属相关产品必须提供MTC证书,证明产品材料的来源并非源自俄罗斯。 对于未使用7323、7326等含有金属类的HS编码申报,且品名未明显体现金属材质,但实际含有金属配件的产品(......