Does the newline implementation matter?

I can’t find anything in the RFCs stating a newline must/should be a certain sequence.

Part of me thinks I am looking in the wrong RFCs, however in my usage, it has not mattered when connecting to boulder or pebble, or installing into a server.

certbot seems to use “\n”
the letsencrypt certs use either:

https://letsencrypt.org/certs/isrgrootx1.pem.txt
\r\n

https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem.txt
\n

https://letsencrypt.org/certs/letsencryptauthorityx3.pem.txt
\r\n

does anyone have info on this?

3 Likes

As you’re listing three certificates as examples, I’m assuming — although you didn’t specify this anywhere — this thread is limited to the textual encoding of certificates.

The first RFC I googled for (search keys: x509 pem rfc), has the answer:

RFC 7468 (“Textual Encodings of PKIX, PKCS, and CMS Structures”), section 3: ABNF:

eol = CRLF / CR / LF

Concluding: all three variations of an end of line are possible and allowed.

4 Likes

Yes! Thank You. I am concerned with PEM encoding of certs and what Boulder will expect, return, etc. I was mostly looking at the family of RFC 5280.

We’ll standardize to \n for storage.

3 Likes

As Boulder is coded in Go and I didn’t find any Boulder-specific code to load a PEM file, I guess it “just” uses the Go routines for PEM handeling:

From pem.go

getLine results the first \r\n or \n delineated line from the given byte array. The line does not include trailing whitespace or the trailing new line bytes. The remainder of the byte array (also not including the new line bytes) is also returned and this will always be smaller than the original argument.

This would mean that Go, in contrast of RFC 7468, does not accept "\r only" newlines. Fortunately, not many systems use \r newlines, the first thing that comes close is “classic Mac OS” (pre-Mac OS X versions).

3 Likes

I don’t think there is anywhere in the ACME API that requires us to handle PEM encoding from clients. Recall that RFC 8555 specifies the CSR parameter of an order finalize request to be the “base64url-encoded version of the DER”.

There is actually some Boulder-specific code that ends up enforcing that the certificate chain we serve in the response to a (POST-as-)GET to an order’s certificate endpoint only ends up containing \n newlines: https://github.com/letsencrypt/boulder/blob/65e53674935b05b0b066fa60eb32892cd36acb5d/cmd/boulder-wfe2/main.go#L124-L129O

The example URLs’ that @jvanasco shared aren’t part of the ACME API. It looks like we should probably normalize the newlines in those static files ref’d by the website anyway. I’ll file a website issue.

2 Likes

I’m not a Boulder expert :wink: but I was thinking more of using PEM-encoded stuff for signing et cetera, when nog using a HSM. In that case Boulder would need to read a private key from somewhere, possibly a PEM-encoded private key? Or would Boulder use a separate “software HSM” for the signing? Like I said, not a Boulder expert :slight_smile:

Hm, but according to RFC 7468 that’s actually not really necessary?

2 Likes

Yup, just our own preference to be consistent here and enforce one line encoding.

2 Likes

That’s why I couldn’t find anything in the RFC!

2 Likes

Well, in that case there are no newlines in play, making things even easier :stuck_out_tongue:

1 Like

For the API, sure. When managing a history/library of CSRs and Signed Certificates though… there are a lot of newlines involved!

1 Like
5 Likes