java - for - p7b to pem
¿Escribir el certificado x509 en una cadena con formato PEM en java? (7)
A continuación, no se utilizan grandes bibliotecas externas o bibliotecas. * Incompatibles con la versión. Se basa en la respuesta de Judoman, pero también fragmenta líneas en 64 caracteres, tal como lo requieren OpenSSL, Java y otros.
Importar:
import javax.xml.bind.DatatypeConverter;
import java.security.cert.X509Certificate;
import java.io.StringWriter;
Código:
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();
}
(Acabo de comentar la respuesta de Judoman, pero no tengo suficientes puntos de reputación para poder comentar, y mi edición simple fue rechazada porque debería haber sido un comentario o una respuesta, así que aquí está la respuesta).
Si desea escribir directamente en el archivo, también import java.io.FileWriter
y:
FileWriter fw = new FileWriter(certFilePath);
fw.write(certToString(myCert));
fw.close();
¿Hay alguna forma de alto nivel para escribir un certificado X509 en una cadena con formato PEM? Actualmente estoy haciendo x509cert.encode () para escribirlo en una cadena con formato DER, luego base 64 codificándolo y agregando el encabezado y pie de página para crear una cadena PEM, pero parece malo. Especialmente porque tengo que lanzar pausas de línea también.
Esto no es malo. Java no proporciona ninguna función para escribir archivos PEM. Lo que estás haciendo es la forma correcta. Incluso KeyTool hace lo mismo,
BASE64Encoder encoder = new BASE64Encoder();
out.println(X509Factory.BEGIN_CERT);
encoder.encodeBuffer(cert.getEncoded(), out);
out.println(X509Factory.END_CERT);
Si usa BouncyCastle, puede usar la clase PEMWriter para escribir el certificado X509 en PEM.
La respuesta anterior ofrece problemas de compatibilidad con el software 3de party (como PHP), porque el certificado PEM no está fragmentado correctamente.
Importaciones:
import org.apache.commons.codec.binary.Base64;
Código:
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;
}
Otra alternativa más para codificar usando BaseEncoding de Guava :
import com.google.common.io.BaseEncoding;
public static final String LINE_SEPARATOR = System.getProperty("line.separator");
public static final int LINE_LENGTH = 64;
Y entonces:
String encodedCertText = BaseEncoding.base64()
.withSeparator(LINE_SEPARATOR, LINE_LENGTH)
.encode(cert.getEncoded());
Para construir sobre la idea de ZZ Coder, pero sin usar las clases sun.misc
que no se garantiza que sean consistentes entre las versiones de JRE, considere esto
Usar clase:
import javax.xml.bind.DatatypeConverter;
Código:
try {
System.out.println("-----BEGIN CERTIFICATE-----");
System.out.println(DatatypeConverter.printBase64Binary(x509cert.getEncoded()));
System.out.println("-----END CERTIFICATE-----");
} catch (CertificateEncodingException e) {
e.printStackTrace();
}
Si tiene PEMWriter del castillo hinchable, puede hacer lo siguiente:
Importaciones:
import org.bouncycastle.openssl.PEMWriter;
Código:
/**
* 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();
}
Todavía no he visto a nadie abrir el método Base64.getMimeEncoder
Java 8; de hecho, le permite especificar tanto la longitud de línea como el separador de línea de la siguiente manera:
final Base64.Encoder encoder = Base64.getMimeEncoder(64, LINE_SEPARATOR.getBytes());
Miré para ver si había alguna diferencia con este ^ frente al codificador estándar, y no pude encontrar nada. El javadoc cita RFC 2045 para codificadores BASIC y MIME, con la adición de RFC 4648 para BASIC. AFAIK ambos estándares usan el mismo alfabeto Base64 (las tablas tienen el mismo aspecto), por lo que debe usar MIME si necesita especificar una longitud de línea.
Esto significa que con Java 8, esto se puede lograr con:
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;
}