Converting ACME Spec DER Certificates to PEM Format with CURL

Hello guys.
I have a certbot and boulder copy running in 2 local VM and I m using Ubuntu server trusty. Everything works fine. However, now im trying to get the certificate after the challenges are completed using curl. So after doing all the challenges and getting a new certificate I do this:
curl -i -H "Accept: application/crt" -H "Content-Type: application/json" Btw, this is where my Boulder is listening :grinning:

I was expecting to get the same certificate but I get some cyphered text, I guess it is the certificate, so how can I read that? Or im getting it all wrong and that cant be done?
Thanks in advance!!

Hi @Chopi64

This is the DER representation of the certificate

If you have a look at one of mine:

You will see the same thing

Section 6.6 describes this:

GET /acme/cert/asdf HTTP/1.1
Accept: application/pkix-cert

HTTP/1.1 202 Accepted
Retry-After: 120

The default format of the certificate is DER (application/pkix-cert).
The client may request other formats by including an Accept header in
its request.

The server provides metadata about the certificate in HTTP headers.
In particular, the server MUST include a Link relation header field
[RFC5988] with relation “up” to provide a certificate under which
this certificate was issued, and one with relation “author” to
indicate the registration under which this certicate was issued. The
server MAY also include an Expires header as a hint to the client
about when to renew the certificate. (Of course, the real expiration
of the certificate is controlled by the notAfter time in the
certificate itself.)

You will need to grab the DER and Conver it to PEM.

An example from the letsencryptshell client

def sslutils_x509_dertopem(x = “”):
Conversion from DER to PEM format
XXX TODO - remove dependency on openssl

    if x.find("BEGIN CERTIFICATE") != -1:
            return x
    cmd = ['openssl', 'x509', '-inform', 'der', '-outform', 'pem']
    p = subprocess.Popen(cmd, stdout = subprocess.PIPE, stdin = subprocess.PIPE)
    ret = p.communicate(x)[0]
    if (p.returncode != 0):
            raise Exception("%s: failed" % (" ".join(cmd)))
    return ret


Well, you don’t have to use all of that Python wrapping around the openssl program. You can use it directly:

openssl x509 -in mycert.der -out mycert.pem -inform der -outform pem

Thank you all, after @ahaw021 comment I realized that it wasnt base64 encoded so of course I couldnt view the contents. However, I still dont get the .pem certificate after saving it in a file and then using the openssl command…what I get is a malformed der encoded file, so I think I ll have to rethink the curl approach, I ll keep working around it, thank you all guys!:grin:

I'm afraid that doesn't make sense to me. Would you be willing to post the original DER file and the OpenSSL commands that you're running?

I cant till Friday morning :sweat:

Hello, I m back here with my computer. After seeing the DER file carefully I have realized that the certificate i am getting when doing the curl petition comes from the fake CA and it is not the actual certificate that im trying to get with curl. I guess this is because after Certbot ends, then the certificate isnt available again at the the uri, right?
curl -i -H "Accept: application/json" -H "Content-Type: application/json" > myDer.cer

Content of the DER file:

HTTP/1.1 200 OK
Boulder-Request-Id: ZtXs6FJ1b0yrNXltb9uAk-c1kESeyV0X6Wijm9qhG44
Cache-Control: public, max-age=0, no-cache
Content-Type: application/pkix-cert
Link: <>;rel="up"
Replay-Nonce: IeNwJQJTSl5c3EqwraRY0eO5yjItyG4eVo5JoMExr4M
Date: Fri, 09 Jun 2017 07:43:40 GMT
Content-Length: 1156
<DF>y<EF><FB><FA><FA><B2><E6><A8><EC>^K<BA>J<A2>0^M^F   *<86>H<86><F7>^M^A^A^K^E^@0^_1^]0ESC^F^CU^D^C^L^Th2ppy h2cker fake CA0^^^W
^O=0^_^F^CU^]#^D^X0^V<80>^T<FB>xO^R<F9>`^U<83>,<9F>^W^?4^Y<B3>.6<EA>A<89>0f^F^H+^F^A^E^E^G^A^A^DZ0X0"^F^H+^F^A^E^E^G0^A<86>^Vhttp://^F^H+^F^A^E^E^G0^B<86>&^V^F^CU^]^Q^D^O0^M<82>^Kwww.bye.com0'^F^CU^]^_^D 0
^^0^\<A0>^Z<A0>^X<86>^V^F^CU^] ^DZ0X^F^Fg<81>^L^A^B^A0L^F^C*^C^D0E0"^F^H+^F^A^E^E^G^B^A^V^V^_^F^H+^F^A^E^E^G^B^B0^S^L^QDo What Thou Wilt0^M^F       *<86>H<86><F7>^M^A^A^K^E^@^C<82>^A^A^@*^R#<C6>w<B9>j<A6><97><D7>
<D1>ZQ^<CC>^M|y^^^_<F2>T^M^Zd<E7>C\d<C6>ӿ}q٩^Oj<E7><92>^F<8D><C0><AC>D<83>^S"<<F1><FF>r<F1>^O<EE><DD>+<96>      <F9><AE>^SسY<E4>/
<CC>gΩ<BD>D^V<C5><D6>L<C5>]<B0>^@M~<B2><F7>    <C0>C)M<97><FB><DD>m<AA>Ѭ#b<8C>l^U,q:<EC>g^\L^X<B9><D8>ll<F4><94>f^\<F5>\<B2>k*^Pex
<DD>6^Rz<EC>S<E8>;<94>^?^A<C5>p<E8><86>^_<DB><C4>#<CE><C9><E3>0n}2<98>b`^_<EC><E5><C5><^C;^M<8F><8F>D<AD>^Y<8C>>c^G#<D6>^Y^F<FE>ߔ^^<D1><C8>3e<F0><8C><CD><E1><F1>   ^L<F6>f<B4>˛<A4>[<9B>
myDer.cer (END)

I haven’t thought about the other possible part of the problem, but the reason your DER file is corrupt is that you used curl -i. The -i option includes web headers in the output, yet they are not part of the file sent by the web server and hence your output is a “web transaction that includes a DER file” rather than “a DER file”. If you leave off the -i option, you can at least fix the file corruption concern.

You were absolutely right!!! I was modifying the der file myself to remove the headers but it was corrupted anyway, I removed the -i field and it worked perfect so I got the certificate just like I wanted :grin:
About the h2ppy h2cker fake CA I first checked if it was because I was passing the -csr myself but removing that field didn’t change the CA. Then I thought that it may just be because I am using my own Boulder copy and doing the challenge to a server that I am running but it is not accessible from the Internet. In fact, all the other certifiactes that I have asked for using the full certbot procedure have the the same CA but the message after the challenge says Congratulations!!
So, am I right or am I f***?

Thanks again for the the help, guys.

I’m not sure if I understood your most recent question, but if you run your own copy of Boulder, the certificates that it issues are signed by itself, not by Let’s Encrypt. Only Let’s Encrypt itself can issue publicly-trusted Let’s Encrypt certificates. Running your own copy of Boulder is appropriate only for testing purposes, or when you want to create your own internal organizational CA, or when you want to go through the auditing and approval process to become a publicly-trusted CA.

It is just for testing purposes, so I guess that ends it, thank you all :smile_cat:

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.