From 639efaeb7ba590ba056c60fdcccb7c0a5b77e69a Mon Sep 17 00:00:00 2001 From: chrismarget Date: Wed, 11 May 2016 12:01:53 -0400 Subject: [PATCH 1/8] Randomize serial numbers of DVSNI challenge certificates. --- acme/acme/crypto_util.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme/acme/crypto_util.py b/acme/acme/crypto_util.py index 73f7f8f62..e121b1ac3 100644 --- a/acme/acme/crypto_util.py +++ b/acme/acme/crypto_util.py @@ -203,7 +203,7 @@ def gen_ss_cert(key, domains, not_before=None, """ assert domains, "Must provide one or more hostnames for the cert." cert = OpenSSL.crypto.X509() - cert.set_serial_number(1337) + cert.set_serial_number(int(OpenSSL.rand.bytes(16).encode("hex"), 16)) cert.set_version(2) extensions = [ From a7ef4940b6fabde1730c2a4cf7aef2d689895dff Mon Sep 17 00:00:00 2001 From: chrismarget Date: Wed, 11 May 2016 13:57:18 -0400 Subject: [PATCH 2/8] Randomize DVSNI challenge certificate serial number, now for python 3.3. --- acme/acme/crypto_util.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acme/acme/crypto_util.py b/acme/acme/crypto_util.py index e121b1ac3..6cb5ad6fc 100644 --- a/acme/acme/crypto_util.py +++ b/acme/acme/crypto_util.py @@ -203,7 +203,7 @@ def gen_ss_cert(key, domains, not_before=None, """ assert domains, "Must provide one or more hostnames for the cert." cert = OpenSSL.crypto.X509() - cert.set_serial_number(int(OpenSSL.rand.bytes(16).encode("hex"), 16)) + cert.set_serial_number(int.from_bytes(OpenSSL.rand.bytes(16),'big')) cert.set_version(2) extensions = [ From 7f70c09c5374ab225a341c73984ed12b3351abd7 Mon Sep 17 00:00:00 2001 From: chrismarget Date: Wed, 11 May 2016 15:19:39 -0400 Subject: [PATCH 3/8] Randomize serial numbers of DVSNI challenge certs. Should now work on python 2.7 and 3.3+ --- acme/acme/crypto_util.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/acme/acme/crypto_util.py b/acme/acme/crypto_util.py index 6cb5ad6fc..6465533a1 100644 --- a/acme/acme/crypto_util.py +++ b/acme/acme/crypto_util.py @@ -203,7 +203,12 @@ def gen_ss_cert(key, domains, not_before=None, """ assert domains, "Must provide one or more hostnames for the cert." cert = OpenSSL.crypto.X509() - cert.set_serial_number(int.from_bytes(OpenSSL.rand.bytes(16),'big')) + + try: + cert.set_serial_number(int(OpenSSL.rand.bytes(16).encode("hex"), 16)) + except AttributeError: + cert.set_serial_number(int.from_bytes(OpenSSL.rand.bytes(16),'big')) + cert.set_version(2) extensions = [ From 6fbd5fa81110e5e0c6aca139e4f827d2bab1da4e Mon Sep 17 00:00:00 2001 From: chrismarget Date: Wed, 11 May 2016 16:04:08 -0400 Subject: [PATCH 4/8] Added missing whitespace. --- acme/acme/crypto_util.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/acme/acme/crypto_util.py b/acme/acme/crypto_util.py index 6465533a1..66590bb26 100644 --- a/acme/acme/crypto_util.py +++ b/acme/acme/crypto_util.py @@ -203,12 +203,10 @@ def gen_ss_cert(key, domains, not_before=None, """ assert domains, "Must provide one or more hostnames for the cert." cert = OpenSSL.crypto.X509() - try: cert.set_serial_number(int(OpenSSL.rand.bytes(16).encode("hex"), 16)) except AttributeError: - cert.set_serial_number(int.from_bytes(OpenSSL.rand.bytes(16),'big')) - + cert.set_serial_number(int.from_bytes(OpenSSL.rand.bytes(16), 'big')) cert.set_version(2) extensions = [ From 4759bc9034a3e2dffbab561345a1716354e89b55 Mon Sep 17 00:00:00 2001 From: chrismarget Date: Wed, 11 May 2016 16:41:19 -0400 Subject: [PATCH 5/8] Trying to make pylint happy. --- acme/acme/crypto_util.py | 1 + 1 file changed, 1 insertion(+) diff --git a/acme/acme/crypto_util.py b/acme/acme/crypto_util.py index 66590bb26..40004c4d0 100644 --- a/acme/acme/crypto_util.py +++ b/acme/acme/crypto_util.py @@ -206,6 +206,7 @@ def gen_ss_cert(key, domains, not_before=None, try: cert.set_serial_number(int(OpenSSL.rand.bytes(16).encode("hex"), 16)) except AttributeError: + # pylint: disable=E1101 cert.set_serial_number(int.from_bytes(OpenSSL.rand.bytes(16), 'big')) cert.set_version(2) From f7b10bb83e01f21bf9aac06b6b7b78d65a1d279d Mon Sep 17 00:00:00 2001 From: chrismarget Date: Wed, 11 May 2016 17:06:29 -0400 Subject: [PATCH 6/8] Serial number randomization with improved portability. No exception handling required this time. --- acme/acme/crypto_util.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/acme/acme/crypto_util.py b/acme/acme/crypto_util.py index 40004c4d0..2b2133475 100644 --- a/acme/acme/crypto_util.py +++ b/acme/acme/crypto_util.py @@ -1,4 +1,5 @@ """Crypto utilities.""" +import binascii import contextlib import logging import re @@ -203,11 +204,7 @@ def gen_ss_cert(key, domains, not_before=None, """ assert domains, "Must provide one or more hostnames for the cert." cert = OpenSSL.crypto.X509() - try: - cert.set_serial_number(int(OpenSSL.rand.bytes(16).encode("hex"), 16)) - except AttributeError: - # pylint: disable=E1101 - cert.set_serial_number(int.from_bytes(OpenSSL.rand.bytes(16), 'big')) + cert.set_serial_number(int(binascii.hexlify(OpenSSL.rand.bytes(16)), 16)) cert.set_version(2) extensions = [ From 85e962455559e25933cdf4ef7ecf8d37c8a03bde Mon Sep 17 00:00:00 2001 From: chrismarget Date: Tue, 17 May 2016 19:50:57 +0000 Subject: [PATCH 7/8] Added test for random certificate serial numbers from gen_ss_cert. --- acme/acme/crypto_util_test.py | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/acme/acme/crypto_util_test.py b/acme/acme/crypto_util_test.py index 147cd5a2a..b41243b8f 100644 --- a/acme/acme/crypto_util_test.py +++ b/acme/acme/crypto_util_test.py @@ -8,6 +8,8 @@ import unittest import six from six.moves import socketserver # pylint: disable=import-error +import OpenSSL + from acme import errors from acme import jose from acme import test_util @@ -126,5 +128,23 @@ class PyOpenSSLCertOrReqSANTest(unittest.TestCase): self._get_idn_names()) +class RandomSnTest(unittest.TestCase): + """Test for random certificate serial numbers.""" + + def setUp(self): + self.certCount = 5 + self.serialNum = [] + self.key = OpenSSL.crypto.PKey() + self.key.generate_key(OpenSSL.crypto.TYPE_RSA, 2048) + + def test_sn_collisions(self): + from acme.crypto_util import gen_ss_cert + + for _ in range(self.certCount): + cert = gen_ss_cert(self.key, ['dummy'], force_san=True) + self.serialNum.append(cert.get_serial_number()) + self.assertTrue(len(set(self.serialNum)) > 1) + + if __name__ == '__main__': unittest.main() # pragma: no cover From 6dd99913719df02d5fbee28952774cdbf16a596e Mon Sep 17 00:00:00 2001 From: chrismarget Date: Tue, 17 May 2016 20:10:20 +0000 Subject: [PATCH 8/8] Fix invalid attribute for pylint --- acme/acme/crypto_util_test.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/acme/acme/crypto_util_test.py b/acme/acme/crypto_util_test.py index b41243b8f..75a908d4f 100644 --- a/acme/acme/crypto_util_test.py +++ b/acme/acme/crypto_util_test.py @@ -132,18 +132,18 @@ class RandomSnTest(unittest.TestCase): """Test for random certificate serial numbers.""" def setUp(self): - self.certCount = 5 - self.serialNum = [] + self.cert_count = 5 + self.serial_num = [] self.key = OpenSSL.crypto.PKey() self.key.generate_key(OpenSSL.crypto.TYPE_RSA, 2048) def test_sn_collisions(self): from acme.crypto_util import gen_ss_cert - for _ in range(self.certCount): + for _ in range(self.cert_count): cert = gen_ss_cert(self.key, ['dummy'], force_san=True) - self.serialNum.append(cert.get_serial_number()) - self.assertTrue(len(set(self.serialNum)) > 1) + self.serial_num.append(cert.get_serial_number()) + self.assertTrue(len(set(self.serial_num)) > 1) if __name__ == '__main__':