Serial numbers of DVSNI challenge certificates are a problem


#1

It seems that when responding to dvsni challenges for multiple domains, the python client creates an independent self-signed challenge certificate for each DVSNI challenge.

These are certificates with SAN <32chars>.<32chars>.acme.invalid.

Each of these certificates needs to be loaded into the TLS speaking application (apache or whatever), and the application needs to be configured to use the appropriate certificate in response to client hellos which reference the .acme.invalid name.

Do I have this right so far?

My problem with the scheme is in acme/acme/crypto_util.py, which contains the following: cert.set_serial_number(1337)

Each certificate came from the same issuer (dummy), and sports the same serial number (1337). These are effectively the same certificate. I’m unable to load them concurrently into my application (a 3rd party hardware device).

This seems to fix it but, being random, invites collisions.

--- crypto_util.py	2016-04-14 19:50:56.786495094 +0000
+++ /tmp/crypto_util.py	2016-04-14 19:50:48.567495584 +0000
@@ -203,7 +203,8 @@
     """
     assert domains, "Must provide one or more hostnames for the cert."
     cert = OpenSSL.crypto.X509()
-    cert.set_serial_number(1337)
+    import random
+    cert.set_serial_number(random.randint(10,1000))
     cert.set_version(2)
 
     extensions = [

Or… Maybe all of the challenges are supposed to be solved by a single certificate with an alt name for each challenge? If so, I’ve gone horribly off the rails somewhere!


#2

I can’t answer your broader question, but I can tell you that serial numbers are allowed to be way longer than that which ought to fix your collision concern. Using a 64-bit serial number (still far smaller than the maximum allowed) you can have billions of certificates before the Birthday Paradox means you’ve got a fighting chance of two of them colliding.


#3

Thanks! The silly random implementation I’ve done was just a test I did to prove to myself that I understood the problem, and that I could install challenge certs for two alt names. Ultimately, the fix (if there’s actually a problem) belongs in something upstream, and a counter (even one that starts at 1 with every renewal) would probably be more appropriate.


#4

That seems like a reasonable fix, and large random serial numbers are common practice in x509, so I’d recommend that over a counter. You should send this as a pull request on the client!


#5

Thanks very much.

I remain fuzzy on whether responding to several DVSNI challenges is expected to involve several certificates (one for each challenge), vs. a single certificate prepared for all challenges. The ACME spec says the following which seems to leave the door open to both possibilities:

The client will generate a self-signed certificate with the subjectAlternativeName extension containing the dNSName “<Z[0:32]>.<Z[32:64]>.acme.invalid”.

I think that the python client intends to take the former approach (one certificate per SNI challenge), but I’m open to the possibility that my plugin is using the framework incorrectly, and that I should be provoking it to generate a single certificate with many alt names.

If the client intends to create many certificates, then I think there’s a pretty rational argument that producing several certificates with overlapping issuer+serial is bad behavior and should be fixed.

Picking serial numbers at random without doing collision detection doesn’t feel right to me, but it’s certainly an improvement over the guaranteed collision situation that we have now :slight_smile:


#6

It should be one certificate per challenge.


#7

one certificate per challenge

Wonderful, thank you for clearing that up.


#8

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