Existe-t-il une méthode de haut niveau pour écrire un certificat X509 dans une chaîne au format PEM? Actuellement je fais x509cert.encode() pour l'écrire dans une chaîne au format DER, puis base 64 l'encoder et ajouter l'en-tête et le pied de page pour créer une chaîne PEM, mais il semble mauvais. Surtout que je dois aussi faire des sauts de ligne.Écrire le certificat x509 dans une chaîne au format PEM dans Java?
Répondre
Ce n'est pas mauvais. 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 certificat X509 dans PEM.
Pour construire sur l'idée de ZZ Coder, mais sans utiliser les sun.misc
classes qui ne sont pas censés être compatibles entre les versions JRE, considérez ceci
Classe d'emploi:
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();
}
La réponse précédente donne des problèmes de compatibilité avec le logiciel 3de party (comme PHP), car le cert PEM n'est pas correctement segmenté.
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 = x509cert.getEncoded();
String pemCertPre = new String(encoder.encode(derCert));
String pemCert = cert_begin + pemCertPre + end_cert;
return pemCert;
}
Il doit généralement contenir 64 caractères pour OpenSSL. – Cathy
Si vous avez PEMWriter du château plein d'entrain, alors vous pouvez effectuer les opérations suivantes:
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();
}
Il va retourner la chaîne vide maintenant, pour corriger cela ajouter ceci après avoir écrit l'objet "pw.flush()". – StalkAlex
Ce qui suit n'utilise pas de grandes bibliothèques externes ou éventuellement des bibliothèques sun. * Incompatibles avec la version. Il se base sur la réponse de Judoman, mais aussi des lignes à 64 caractères, comme requis par OpenSSL, Java et d'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();
}
(je viens de parler sur la réponse de judoman, mais je n'ai pas assez de points de réputation pour être autorisés à commenter, et mon simple, edit a été rejeté car il aurait dû être un commentaire ou une réponse, alors voici la réponse.)
Si vous voulez écrire directement à déposer, aussi import java.io.FileWriter
et:
FileWriter fw = new FileWriter(certFilePath);
fw.write(certToString(myCert));
fw.close();
ai pas vu quelqu'un mettre en place la méthode Java 8 de Base64.getMimeEncoder
encore - vous permet en fait de spécifier à la fois la longueur de la ligne et ligne de séparation comme ceci:
final Base64.Encoder encoder = Base64.getMimeEncoder(64, LINE_SEPARATOR.getBytes());
je regardais pour voir s'il y avait une différence avec ce^vs l'encodeur standard, et je ne pouvais pas trouver quoi que ce soit. Le javadoc cite RFC 2045 pour les codeurs BASIC et MIME, avec l'ajout de RFC 4648 pour BASIC. AFAIK deux de ces normes utilisent le même alphabet Base64 (les tables se ressemblent), donc vous devriez bien utiliser MIME si vous devez spécifier une longueur de ligne.
Cela signifie que Java 8, cela 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;
}
L'appel nécessite le niveau d'API 26. – Pei
Encore une autre alternative pour le codage au moyen 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;
Et puis:
String encodedCertText = BaseEncoding.base64()
.withSeparator(LINE_SEPARATOR, LINE_LENGTH)
.encode(cert.getEncoded());
PEMWriter est maintenant dépréciée. JcaPEMWriter est la nouvelle classe qui le remplace. – rancidfishbreath