Записать сертификат x509 в форматированную строку PEM в java?
есть ли какой-то способ высокого уровня для записи X509Certificate в строку в формате PEM? В настоящее время я делаю x509cert.encode (), чтобы записать его в форматированную строку DER, затем base 64 кодирует его и добавляет верхний и Нижний колонтитулы для создания строки PEM, но это кажется плохим. Тем более, что мне тоже приходится делать перерывы.
7 ответов
это неплохо. 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 в PEM.
предыдущий ответ дает проблемы совместимости с программным обеспечением 3de (например, PHP), потому что PEM cert неправильно разделен.
импорт:
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 = cert.getEncoded();
String pemCertPre = new String(encoder.encode(derCert));
String pemCert = cert_begin + pemCertPre + end_cert;
return pemCert;
}
не видел, чтобы кто-нибудь поднимал Java 8 Base64.getMimeEncoder
метод еще-на самом деле позволяет указать как длину строки и разделитель строк, например:
final Base64.Encoder encoder = Base64.getMimeEncoder(64, LINE_SEPARATOR.getBytes());
Я посмотрел, есть ли разница с этим ^ против стандартного кодировщика, и я ничего не мог найти. The javadoc СИТЕС RFC 2045 как для базовых, так и для 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;
}
следующее не использует большие внешние библиотеки или, возможно, версию-несогласованное солнце.* библиотеки. Он основан на ответе judoman, но он также разбивает строки на 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})", "\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();
Если у вас есть PEMWriter от bouncy castle, то вы можете сделать следующее:
импорт :
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();
}
чтобы построить на идее 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();
}
еще одна альтернатива для кодирования с использованием гуава 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());