2010-07-22 5 views
34

Есть ли способ высокого уровня записи X509Certificate в строку в формате PEM? В настоящее время я делаю x509cert.encode(), чтобы записать его в форматированную строку DER, затем базовую кодировку 64 и добавив верхний и нижний колонтитулы для создания строки PEM, но это кажется плохим. Тем более, что я тоже должен бросить перерывы.Записать сертификат x509 в строку в формате PEM в java?

ответ

47

Это не плохо. Java не предоставляет никаких функций для записи файлов PEM. То, что вы делаете, это правильный путь. Даже Keytool делает то же самое,

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

Если вы используете BouncyCastle, вы можете использовать класс PEMWriter выписать сертификат X509 в ПОМ.

+4

PEMWriter теперь осуждается. JcaPEMWriter - это новый класс, который его заменяет. – rancidfishbreath

7

Чтобы построить на идее ZZ Coder, но без использования sun.misc классов, которые не гарантированно соответствовать между версиями JRE, рассмотрим этот

Использование Класс:

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

+0

Спасибо pimlottc. Я удалил ссылки на sun.security.provider.X509Factory и заменил их строковыми значениями. – judoman

15

Предыдущий ответ дает проблемы совместимости с программным обеспечением 3de party (например, 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

Он должен быть в строках из 64 символов для OpenSSL в целом. – Cathy

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

10

Следующие не используют большие внешние библиотеки или библиотеки, не совместимые с версией. *. Он основывается на ответе жюри, но он также разбивает строки на 64 символа, как того требуют OpenSSL, Java и другие.

Импорт:

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 цитирует RFC 2045 для обоих кодировщиков BASIC и MIME, с добавлением RFC 4648 для BASIC. 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

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()); 
Смежные вопросы