Écrivez le certificate x509 dans une chaîne au format PEM en Java?

Existe-t-il un moyen de haut niveau d’écrire un certificate X509 dans une chaîne au format PEM? Actuellement, je fais x509cert.encode () pour l’écrire dans une chaîne au format DER, puis la base 64 pour l’encoder et append l’en-tête et le pied de page pour créer une chaîne PEM, mais cela semble mauvais. Surtout que je dois aussi lancer des sauts de ligne.

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 le certificate X509 dans PEM.

La réponse précédente pose des problèmes de compatibilité avec les logiciels tiers (comme PHP), car PEM cert n’est pas correctement fragmenté.

Importations:

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

Code:

 protected static Ssortingng convertToPem(X509Certificate cert) throws CertificateEncodingException { Base64 encoder = new Base64(64); Ssortingng cert_begin = "-----BEGIN CERTIFICATE-----\n"; Ssortingng end_cert = "-----END CERTIFICATE-----"; byte[] derCert = x509cert.getEncoded(); Ssortingng pemCertPre = new Ssortingng(encoder.encode(derCert)); Ssortingng pemCert = cert_begin + pemCertPre + end_cert; return pemCert; } 

Ce qui suit n’utilise pas de grandes bibliothèques externes ou des bibliothèques sun. * Incompatibles avec la version. Il repose sur la réponse de judoman, mais il coupe également les lignes à 64 caractères, comme requirejs par OpenSSL, Java et autres.

Importer:

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

Code:

 public static Ssortingng certToSsortingng(X509Certificate cert) { SsortingngWriter sw = new SsortingngWriter(); 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.toSsortingng(); } 

(J’aurais juste commenté la réponse de judoman, mais je n’ai pas assez de points de réputation pour être autorisé à commenter, et ma simple modification 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 le fichier, import java.io.FileWriter également import java.io.FileWriter et:

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

Base64.getMimeEncoder n’a encore Base64.getMimeEncoder méthode Base64.getMimeEncoder Java 8 – vous permet en fait de spécifier la longueur de ligne et le séparateur 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 cet encodeur par rapport à l’encodeur standard, et je n’ai rien trouvé. Le javadoc cite la RFC 2045 pour les codeurs BASIC et MIME, avec l’ajout de la RFC 4648 pour BASIC. Dans les deux cas, les deux standards utilisent le même alphabet Base64 (les tableaux se ressemblent), vous devriez donc utiliser MIME si vous avez besoin de spécifier une longueur de ligne.

Cela signifie qu’avec Java 8, cela peut être réalisé avec:

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

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

 public static Ssortingng formatCrtFileContents(final Certificate certificatee) throws CertificateEncodingException { final Base64.Encoder encoder = Base64.getMimeEncoder(64, LINE_SEPARATOR.getBytes()); final byte[] rawCrtText = certificatee.getEncoded(); final Ssortingng encodedCertText = new Ssortingng(encoder.encode(rawCrtText)); final Ssortingng prettified_cert = BEGIN_CERT + LINE_SEPARATOR + encodedCertText + LINE_SEPARATOR + END_CERT; return prettified_cert; } 

Pour construire sur l’idée de ZZ Coder, mais sans utiliser les classes sun.misc qui ne sont pas garanties cohérentes entre les versions de JRE, 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 d’un château gonflable, vous pouvez effectuer les opérations suivantes:

Importations:

 import org.bouncycastle.openssl.PEMWriter; 

Code:

 /** * Converts a {@link X509Certificate} instance into a Base-64 encoded ssortingng (PEM format). * * @param x509Cert A X509 Certificate instance * @return PEM formatted Ssortingng * @throws CertificateEncodingException */ public Ssortingng convertToBase64PEMSsortingng(Certificate x509Cert) throws IOException { SsortingngWriter sw = new SsortingngWriter(); try (PEMWriter pw = new PEMWriter(sw)) { pw.writeObject(x509Cert); } return sw.toSsortingng(); } 

Encore une autre alternative pour l’encodage utilisant BaseEncoding de Guava :

 import com.google.common.io.BaseEncoding; public static final Ssortingng LINE_SEPARATOR = System.getProperty("line.separator"); public static final int LINE_LENGTH = 64; 

Et alors:

 Ssortingng encodedCertText = BaseEncoding.base64() .withSeparator(LINE_SEPARATOR, LINE_LENGTH) .encode(cert.getEncoded());