2010-07-22 43 views
34

是否有一些高水平的方法将X509Certificate写入PEM格式的字符串? 目前我正在做x509cert.encode()把它写入一个DER格式的字符串,然后base 64编码它并附加页眉和页脚来创建一个PEM字符串,但它看起来很糟糕。特别是因为我必须抛出分行。在java中将x509证书写入PEM格式的字符串?

回答

47

这并不坏。 Java不提供任何函数来编写PEM文件。你正在做的是正确的方式。即使密钥工具做同样的事情,

BASE64Encoder encoder = new BASE64Encoder(); 
out.println(X509Factory.BEGIN_CERT); 
encoder.encodeBuffer(cert.getEncoded(), out); 
out.println(X509Factory.END_CERT); 

如果使用BouncyCastle的,你可以使用PEMWriter类写出来的PEM X509证书。

+4

PEMWriter现在已经过时。 JcaPEMWriter是替代它的新类。 – rancidfishbreath 2016-07-21 05:30:43

7

要建立在ZZ编码器的想法,但不使用那些不能保证JRE版本之间是一致的sun.misc类,认为这

使用类:

import javax.xml.bind.DatatypeConverter; 

代码:

try { 
    System.out.println("-----BEGIN CERTIFICATE-----"); 
    System.out.println(DatatypeConverter.printBase64Binary(x509cert.getEncoded())); 
    System.out.println("-----END CERTIFICATE-----"); 
} catch (CertificateEncodingException e) { 
    e.printStackTrace(); 
} 
+0

没有太阳。*类的目的是稳定的:http://www.oracle.com/technetwork/java/faq-sun-packages-142232.html – pimlottc 2012-12-17 22:17:59

+0

感谢pimlottc。我删除了sun.security.provider.X509Factory字段引用,并用字符串值替换它们。 – judoman 2012-12-19 01:46:53

15

以前的回答给出了第三方软件(如PHP)的兼容性问题,因为PEM证书没有正确分块。

进口:

import org.apache.commons.codec.binary.Base64; 

代码:

protected static String convertToPem(X509Certificate cert) throws CertificateEncodingException { 
Base64 encoder = new Base64(64); 
String cert_begin = "-----BEGIN CERTIFICATE-----\n"; 
String end_cert = "-----END CERTIFICATE-----"; 

byte[] derCert = x509cert.getEncoded(); 
String pemCertPre = new String(encoder.encode(derCert)); 
String pemCert = cert_begin + pemCertPre + end_cert; 
return pemCert; 
} 
+1

一般来说,OpenSSL需要64行。 – Cathy 2013-05-23 05:57:35

5

如果从充气城堡有PEMWriter,那么你就可以做到以下几点:

进口:

import org.bouncycastle.openssl.PEMWriter; 

代码:

/** 
* Converts a {@link X509Certificate} instance into a Base-64 encoded string (PEM format). 
* 
* @param x509Cert A X509 Certificate instance 
* @return PEM formatted String 
* @throws CertificateEncodingException 
*/ 
public String convertToBase64PEMString(Certificate x509Cert) throws IOException { 
    StringWriter sw = new StringWriter(); 
    try (PEMWriter pw = new PEMWriter(sw)) { 
     pw.writeObject(x509Cert); 
    } 
    return sw.toString(); 
} 
+0

现在将返回空字符串,以便在写入对象“pw.flush()”后添加此项。 – StalkAlex 2017-01-20 10:58:27

10

以下内容不使用大的外部库或版本不一致的sun。*库。它建立在Judoman的答案之上,但它也按照OpenSSL,Java和其他语言的要求,分成64个字符的行。

导入:

import javax.xml.bind.DatatypeConverter; 
import java.security.cert.X509Certificate; 
import java.io.StringWriter; 

代码:

public static String certToString(X509Certificate cert) { 
    StringWriter sw = new StringWriter(); 
    try { 
     sw.write("-----BEGIN CERTIFICATE-----\n"); 
     sw.write(DatatypeConverter.printBase64Binary(cert.getEncoded()).replaceAll("(.{64})", "$1\n")); 
     sw.write("\n-----END CERTIFICATE-----\n"); 
    } catch (CertificateEncodingException e) { 
     e.printStackTrace(); 
    } 
    return sw.toString(); 
} 

(我刚才谈到judoman的答案,但我没有被允许足够的信誉分置评,而我的简单编辑被拒绝了,因为它应该是评论或答案,所以这里是答案。)

如果你想写直奔文件,也import java.io.FileWriter和:

FileWriter fw = new FileWriter(certFilePath); 
fw.write(certToString(myCert)); 
fw.close(); 
9

没见过有人弹出的Java 8的又Base64.getMimeEncoder方法 - 实际上允许你同时指定线路长度如下所示:

final Base64.Encoder encoder = Base64.getMimeEncoder(64, LINE_SEPARATOR.getBytes()); 

我期待着看看这个^与标准编码器有什么不同,我找不到任何东西。 javadoc引用了BASIC和MIME编码器的RFC 2045,并增加了BASIC的RFC 4648。 AFAIK这两个标准都使用相同的Base64字母表(表看起来相同),所以如果需要指定行长度,则应该使用MIME。

这意味着,与Java 8,这可以用完成:

import java.security.cert.Certificate; 
import java.security.cert.CertificateEncodingException; 
import java.util.Base64; 

然而,对于使用编码...

public static final String BEGIN_CERT = "-----BEGIN CERTIFICATE-----"; 
public static final String END_CERT = "-----END CERTIFICATE-----"; 
public final static String LINE_SEPARATOR = System.getProperty("line.separator"); 

...

public static String formatCrtFileContents(final Certificate certificate) throws CertificateEncodingException { 
    final Base64.Encoder encoder = Base64.getMimeEncoder(64, LINE_SEPARATOR.getBytes()); 

    final byte[] rawCrtText = certificate.getEncoded(); 
    final String encodedCertText = new String(encoder.encode(rawCrtText)); 
    final String prettified_cert = BEGIN_CERT + LINE_SEPARATOR + encodedCertText + LINE_SEPARATOR + END_CERT; 
    return prettified_cert; 
} 
+0

通话需要API等级26。 – Pei 2017-09-07 02:23:31

0

另一种选择Guava's BaseEncoding

import com.google.common.io.BaseEncoding; 

public static final String LINE_SEPARATOR = System.getProperty("line.separator"); 
public static final int LINE_LENGTH = 64; 

然后:

String encodedCertText = BaseEncoding.base64() 
            .withSeparator(LINE_SEPARATOR, LINE_LENGTH) 
            .encode(cert.getEncoded()); 
相关问题