2010-07-22 11 views
34

PEM 형식의 문자열에 X509Certificate을 쓰는 높은 수준의 방법이 있습니까? 현재 DER 서식이 지정된 문자열에 x509cert.encode()를 쓰고 64 인코딩을 기본으로하고 PEM 문자열을 만들기 위해 머리글과 바닥 글을 추가하지만 나쁘다고 생각됩니다. 특히 나도 줄 바꿈을해야하기 때문에.Java에서 PEM 형식의 문자열에 x509 인증서 쓰기?

답변

47

이것은 나쁘지 않습니다. Java는 PEM 파일을 작성하는 기능을 제공하지 않습니다. 당신이하는 일은 올바른 방법입니다. 심지어 키 도구가 같은 일을 당신이 BouncyCastle를 사용하는 경우,

BASE64Encoder encoder = new BASE64Encoder(); 
out.println(X509Factory.BEGIN_CERT); 
encoder.encodeBuffer(cert.getEncoded(), out); 
out.println(X509Factory.END_CERT); 

, 당신은 PEM에서 X509 인증서를 작성하는 PEMWriter 클래스를 사용할 수 있습니다.

+4

PEMWriter는 이제 사용되지 않습니다. JcaPEMWriter는 그것을 대신하는 새로운 클래스입니다. – rancidfishbreath

7

ZZ 코더의 아이디어를 구축하는 것이 아니라 JRE 버전 사이의 일관성이 보장되지 않는 sun.misc 클래스를 사용하지 않고,이

사용 등급을 고려

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(); 
} 
+0

sun. * 클래스는 안정적으로 사용할 수 없습니다. http://www.oracle.com/technetwork/java/faq-sun-packages-142232.html – pimlottc

+0

고맙습니다. pimlottc. sun.security.provider.X509Factory 필드 참조를 제거하고 문자열 값으로 대체했습니다. – judoman

15

이전 답변은 PEM 인증서가 올바르게 청크되지 않았기 때문에 3de 파티 소프트웨어 (예 : PHP)와의 호환성 문제를 발생시킵니다.

수입 :

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

코드 : 당신은 탄력이 성에서 PEMWriter이있는 경우

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; 
} 
+1

일반적으로 OpenSSL의 경우 64 자 라인이어야합니다. – Cathy

5

는, 당신은 다음을 수행 할 수 있습니다

수입 :

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(); 
} 
+0

"pw.flush()"객체를 작성한 후에 이것을 추가하기 위해 빈 문자열을 반환 할 것입니다. – StalkAlex

10

다음은 큰 외부 라이브러리 또는 버전이 일치하지 않는 sun. * 라이브러리를 사용하지 않습니다. 그것은 judoman의 답변을 기반으로하지만 OpenSSL, Java 및 기타 요구 사항에 따라 64 자로 줄을 채 웁니다.

가져 오기 :

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})", "$1\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(); 
9

Base64.getMimeEncoder 방법을 아직 사람이 자바 8의를 가져 보지 못했다 - 실제로 당신이 라인의 길이를 모두 지정할 수 있습니다 다음과 같은 줄 구분 기호 :

final Base64.Encoder encoder = Base64.getMimeEncoder(64, LINE_SEPARATOR.getBytes()); 

표준 인코더와 비교하여 차이가 있는지 살펴 보았으므로 아무 것도 찾을 수 없었습니다. javadoc은 BASIC 및 MIME 인코더 모두에 대해 RFC 2045을 인용하며 BASIC에는 RFC 4648이 추가되었습니다. AFAIK 두 표준 모두 동일한 Base64 알파벳 (표는 동일하게 나타남)을 사용하므로 줄 길이를 지정해야하는 경우 MIME을 사용하는 것이 좋습니다. 하여 부호화 아직 ...

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; 
} 
+0

호출에는 API 수준 26이 필요합니다. – Pei

0

을 :

자바 8, 이것이 달성 될 수 있다는 것을 의미 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; 

그리고 :

String encodedCertText = BaseEncoding.base64() 
            .withSeparator(LINE_SEPARATOR, LINE_LENGTH) 
            .encode(cert.getEncoded()); 
관련 문제