Existe-t-il un moyen simple d’écrire un X509Certificate dans une chaîne au format PEM? créer une chaîne PEM, mais cela semble mauvais. Surtout que je dois aussi faire la queue.
Ce n'est pas mal. Java ne fournit aucune fonction pour écrire des fichiers PEM. Ce que vous faites est la bonne façon. Même KeyTool fait la même chose,
BASE64Encoder encoder = new BASE64Encoder();
out.println(X509Factory.BEGIN_CERT);
encoder.encodeBuffer(cert.getEncoded(), out);
out.println(X509Factory.END_CERT);
Si vous utilisez BouncyCastle, vous pouvez utiliser la classe PEMWriter pour écrire un certificat X509 dans PEM.
La réponse précédente donne des problèmes de compatibilité avec les logiciels tiers (comme PHP), car le certificat PEM n'est pas correctement tronqué.
Importations:
import org.Apache.commons.codec.binary.Base64;
Code:
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;
}
Personne n'a encore vu la méthode Base64.getMimeEncoder
de Java 8 - vous permet en fait de spécifier le séparateur de longueur de ligne et de ligne comme suit:
final Base64.Encoder encoder = Base64.getMimeEncoder(64, LINE_SEPARATOR.getBytes());
J'ai regardé pour voir s'il y avait une différence avec ceci ^ par rapport à l'encodeur standard, et je n'ai rien trouvé. Le javadoc cites RFC 2045 pour les codeurs BASIC et MIME, avec l’ajout de RFC 4648 pour BASIC. Si je comprends bien, ces deux normes utilisent le même alphabet Base64 (les tableaux ont la même apparence), vous devriez donc pouvoir utiliser MIME si vous devez spécifier une longueur de ligne.
Cela signifie qu'avec Java 8, ceci peut être accompli avec:
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;
}
Les éléments suivants n'utilisent pas de bibliothèques externes volumineuses ni éventuellement de bibliothèques Sun. * incohérentes. Il s'appuie sur la réponse de judoman, mais il coupe également les lignes de 64 caractères, comme requis par OpenSSL, Java et autres.
Importation:
import javax.xml.bind.DatatypeConverter;
import Java.security.cert.X509Certificate;
import Java.io.StringWriter;
Code:
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();
}
(J'aurais juste commenté la réponse de judoman, mais je n'ai pas assez de points de réputation pour pouvoir commenter, et ma modification simple a été rejetée car elle aurait dû être un commentaire ou une réponse, alors voici la réponse.)
Si vous voulez écrire directement dans un fichier, import Java.io.FileWriter
et:
FileWriter fw = new FileWriter(certFilePath);
fw.write(certToString(myCert));
fw.close();
Pour tirer parti de l'idée de ZZ Coder, mais sans utiliser les classes Sun.misc
dont la cohérence entre les versions de JRE n'est pas garantie, considérez ceci.
Classe d'utilisation:
import javax.xml.bind.DatatypeConverter;
Code:
try {
System.out.println("-----BEGIN CERTIFICATE-----");
System.out.println(DatatypeConverter.printBase64Binary(x509cert.getEncoded()));
System.out.println("-----END CERTIFICATE-----");
} catch (CertificateEncodingException e) {
e.printStackTrace();
}
Si vous avez PEMWriter du château gonflable, vous pouvez alors:
Importations:
import org.bouncycastle.openssl.PEMWriter;
Code:
/**
* 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();
}
Dans BouncyCastle, 1.60 PEMWriter
a été déconseillé en faveur de PemWriter
.
StringWriter sw = new StringWriter();
try (PemWriter pw = new PemWriter(sw)) {
PemObjectGenerator gen = new JcaMiscPEMGenerator(cert);
pw.writeObject(gen);
}
return sw.toString();
PemWriter
est en mémoire tampon, vous devez donc la vider/la fermer avant d'accéder au scripteur avec lequel il a été construit.
Encore une autre alternative pour l'encodage avec 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;
Et alors:
String encodedCertText = BaseEncoding.base64()
.withSeparator(LINE_SEPARATOR, LINE_LENGTH)
.encode(cert.getEncoded());