将PEM格式的字符串转换为java.security.cert.X509Certificate

Jef*_*ung 32 java ssl x509certificate

如何java.security.cert.X509Certificate从PEM格式的字符串创建实例?PEM格式的String是HTTP请求"SSL_CLIENT_CERT"标头值.

答案: 根据mgaert的回答,这是我在Scala中写的内容:

val cert = factory.generateCertificate(
    new ByteArrayInputStream(
      Base64.decodeBase64(
        cert.stripPrefix("-----BEGIN CERTIFICATE-----").stripSuffix("-----END CERTIFICATE-----")
      )
    ).asInstanceOf[X509Certificate]
Run Code Online (Sandbox Code Playgroud)

mga*_*ert 45

将Base64解码为二进制,一些InputStream读取它,然后尝试

CertificateFactory cf = CertificateFactory.getInstance("X.509");
Certificate cert = cf.generateCertificate(is);
Run Code Online (Sandbox Code Playgroud)

  • 实际上,不需要解码。@shuyu 的回答很有魅力 (2认同)
  • 哦,@ursa 和 @shuyu 你是对的 - 不需要解码。我的第一个想法是……“当我在 *2012 年 3 月*写下这个答案时,这是真的吗?” *是的*!我挖出了 JDK 7 源代码,果然“generateCertificate”已被“记录”为不仅支持二进制,还支持 Base64。另外,引用“如果证书以 Base64 编码提供,则其开头必须以 -----BEGIN CERTIFICATE----- 为界,并且必须以 -----END CERTIFICATE 结尾为界-----。” 感谢您送我来这里进行一次小型时间旅行:-) (2认同)

sim*_*onC 17

我有一个类似的问题,我也在这里粘贴了适用于我的java代码,以防任何人入侵它:

import java.util.Base64;

public static X509Certificate parseCertificate(String _headerName, HttpServletRequest _request) throws CertificateException {
    String certStr = _request.getHeader("x-clientcert");
    //before decoding we need to get rod off the prefix and suffix
    byte [] decoded = Base64.getDecoder().decode(certStr.replaceAll(X509Factory.BEGIN_CERT, "").replaceAll(X509Factory.END_CERT, ""));

    return (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(new ByteArrayInputStream(decoded));
}
Run Code Online (Sandbox Code Playgroud)


Bal*_*yan 10

转换PEM格式化字符串的步骤与(x509 - > String)的发生方式相反.

示例PEM格式化字符串:

-----BEGIN CERTIFICATE-----
MIIEczCCA1ugAwIBAgIBADANBgkqhkiG9w0BAQQFAD..AkGA1UEBhMCR0Ix
EzARBgNVBAgTClNvbWUtU3RhdGUxFDASBgNVBAoTC0..0EgTHRkMTcwNQYD
VQQLEy5DbGFzcyAxIFB1YmxpYyBQcmltYXJ5IENlcn..XRpb24gQXV0aG9y
aXR5MRQwEgYDVQQDEwtCZXN0IENBIEx0ZDAeFw0wMD..TUwMTZaFw0wMTAy
MDQxOTUwMTZaMIGHMQswCQYDVQQGEwJHQjETMBEGA1..29tZS1TdGF0ZTEU
MBIGA1UEChMLQmVzdCBDQSBMdGQxNzA1BgNVBAsTLk..DEgUHVibGljIFBy
aW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxFD..AMTC0Jlc3QgQ0Eg
THRkMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCg..Tz2mr7SZiAMfQyu
vBjM9OiJjRazXBZ1BjP5CE/Wm/Rr500PRK+Lh9x5eJ../ANBE0sTK0ZsDGM
ak2m1g7oruI3dY3VHqIxFTz0Ta1d+NAjwnLe4nOb7/..k05ShhBrJGBKKxb
8n104o/5p8HAsZPdzbFMIyNjJzBM2o5y5A13wiLitE..fyYkQzaxCw0Awzl
kVHiIyCuaF4wj571pSzkv6sv+4IDMbT/XpCo8L6wTa..sh+etLD6FtTjYbb
rvZ8RQM1tlKdoMHg2qxraAV++HNBYmNWs0duEdjUbJ..XI9TtnS4o1Ckj7P
OfljiQIDAQABo4HnMIHkMB0GA1UdDgQWBBQ8urMCRL..5AkIp9NJHJw5TCB
tAYDVR0jBIGsMIGpgBQ8urMCRLYYMHUKU5AkIp9NJH..aSBijCBhzELMAkG
A1UEBhMCR0IxEzARBgNVBAgTClNvbWUtU3RhdGUxFD..AoTC0Jlc3QgQ0Eg
THRkMTcwNQYDVQQLEy5DbGFzcyAxIFB1YmxpYyBQcm..ENlcnRpZmljYXRp
b24gQXV0aG9yaXR5MRQwEgYDVQQDEwtCZXN0IENBIE..DAMBgNVHRMEBTAD
AQH/MA0GCSqGSIb3DQEBBAUAA4IBAQC1uYBcsSncwA..DCsQer772C2ucpX
xQUE/C0pWWm6gDkwd5D0DSMDJRqV/weoZ4wC6B73f5..bLhGYHaXJeSD6Kr
XcoOwLdSaGmJYslLKZB3ZIDEp0wYTGhgteb6JFiTtn..sf2xdrYfPCiIB7g
BMAV7Gzdc4VspS6ljrAhbiiawdBiQlQmsBeFz9JkF4..b3l8BoGN+qMa56Y
It8una2gY4l2O//on88r5IWJlm1L0oA8e4fR2yrBHX..adsGeFKkyNrwGi/
7vQMfXdGsRrXNGRGnX+vWDZ3/zWI0joDtCkNnqEpVn..HoX
-----END CERTIFICATE-----
Run Code Online (Sandbox Code Playgroud)

以下是步骤:

1. Remove headers from PEM formatted String
Headers are : ---- BEGIN CERTIFICATE ----- and ----- END CERTIFICATE ------
2. Decode the rest of the part using Base64 to byte array
3. Then you can use CertificateFactory to convert byte stream to x509Certificate object
Run Code Online (Sandbox Code Playgroud)

上面的示例代码(使用PEM Writer):

  /**
     * Converts a PEM formatted String to a {@link X509Certificate} instance.
     *
     * @param pem PEM formatted String
     * @return a X509Certificate instance
     * @throws CertificateException 
     * @throws IOException
     */
    public X509Certificate convertToX509Certificate(String pem) throws CertificateException, IOException {
        X509Certificate cert = null;
        StringReader reader = new StringReader(pem);
        PEMReader pr = new PEMReader(reader);
        cert = (X509Certificate)pr.readObject();
        return cert;
    }
Run Code Online (Sandbox Code Playgroud)

  • 请注意,PEMReader 是 Bouncy Castle Crypto API 的一部分,请参阅 https://www.bouncycastle.org/。@mgaert 的代码无需外部库即可工作。 (2认同)

Zei*_*ist 5

另一个样本,

public static X509Certificate convertToX509Cert(String certificateString) throws CertificateException {
    X509Certificate certificate = null;
    CertificateFactory cf = null;
    try {
        if (certificateString != null && !certificateString.trim().isEmpty()) {
            certificateString = certificateString.replace("-----BEGIN CERTIFICATE-----\n", "")
                    .replace("-----END CERTIFICATE-----", ""); // NEED FOR PEM FORMAT CERT STRING
            byte[] certificateData = Base64.getDecoder().decode(certificateString);
            cf = CertificateFactory.getInstance("X509");
            certificate = (X509Certificate) cf.generateCertificate(new ByteArrayInputStream(certificateData));
        }
    } catch (CertificateException e) {
        throw new CertificateException(e);
    }
    return certificate;
}
Run Code Online (Sandbox Code Playgroud)

  • `Base64.getMimeDecoder()` 可能是一个更安全的选择,否则您可能会看到诸如“非法的 base64 字符 a” 之类的问题,如此处所述 https://bugs.openjdk.java.net/browse/JDK-8213780。 (4认同)

shu*_*uyu 5

试图遵循@Balaji Boggaram Ramanarayan 代码,但 IDE 继续抛出异常。相反,我将字符串转换为字节,它完美地工作。

private X509Certificate convertStringToX509Cert(String certificate) throws Exception{
    InputStream targetStream = new ByteArrayInputStream(certificate.getBytes());
    return (X509Certificate) CertificateFactory
            .getInstance("X509")
            .generateCertificate(targetStream);
}
Run Code Online (Sandbox Code Playgroud)

更不用说,这种方法不需要删除 .pem 页眉和页脚(-----BEGIN PRIVATE KEY----- 和 -----END PRIVATE KEY-----)