diff --git a/letsencrypt/client/client.py b/letsencrypt/client/client.py index b6f507688..4765014ec 100644 --- a/letsencrypt/client/client.py +++ b/letsencrypt/client/client.py @@ -118,11 +118,6 @@ class Client(object): # Make sure we have key and csr to perform challenges self.init_key_csr() - # TODO: Handle this exception/problem - if not crypto_util.csr_matches_names(self.csr.data, self.names): - raise errors.LetsEncryptClientError( - "CSR subject does not contain one of the specified names") - # Perform Challenges responses, challenge_objs = self.verify_identity(challenge_msg) # Get Authorization diff --git a/letsencrypt/client/crypto_util.py b/letsencrypt/client/crypto_util.py index d19cbc0da..554ccf684 100644 --- a/letsencrypt/client/crypto_util.py +++ b/letsencrypt/client/crypto_util.py @@ -1,6 +1,5 @@ """Let's Encrypt client crypto utility functions""" import binascii -import hashlib import logging import time @@ -15,13 +14,6 @@ from letsencrypt.client import CONFIG from letsencrypt.client import le_util -# TODO: All of these functions need unit tests - -def b64_cert_to_pem(b64_der_cert): - return M2Crypto.X509.load_cert_der_string( - le_util.jose_b64decode(b64_der_cert)).as_pem() - - def create_sig(msg, key_str, nonce=None, nonce_len=CONFIG.NONCE_SIZE): """Create signature with nonce prepended to the message. @@ -76,27 +68,15 @@ def leading_zeros(arg): return arg -def sha256(arg): - return hashlib.sha256(arg).hexdigest() - - -# based on M2Crypto unit test written by Toby Allsopp -def make_key(bits=CONFIG.RSA_KEY_SIZE): - """ - Returns new RSA key in PEM form with specified bits - """ - # Python Crypto module doesn't produce any stdout - key = Crypto.PublicKey.RSA.generate(bits) - # rsa = M2Crypto.RSA.gen_key(bits, 65537) - # key_pem = rsa.as_pem(cipher=None) - # rsa = None # should not be freed here - - return key.exportKey(format='PEM') - - def make_csr(key_str, domains): - """ - Returns new CSR in PEM and DER form using key_file containing all domains + """Generate a CSR. + + :param str key_str: RSA key. + :param list domains: Domains included in the certificate. + + :returns: new CSR in PEM and DER form containing all domains + :rtype: tuple + """ assert domains, "Must provide one or more hostnames for the CSR." rsa_key = M2Crypto.RSA.load_key_string(key_str) @@ -115,7 +95,7 @@ def make_csr(key_str, domains): extstack = M2Crypto.X509.X509_Extension_Stack() ext = M2Crypto.X509.new_extension( - 'subjectAltName', ", ".join(["DNS:%s" % d for d in domains])) + 'subjectAltName', ", ".join("DNS:%s" % d for d in domains)) extstack.push(ext) csr.add_extensions(extstack) @@ -126,10 +106,82 @@ def make_csr(key_str, domains): return csr.as_pem(), csr.as_der() -def make_ss_cert(key_str, domains): +# WARNING: the csr and private key file are possible attack vectors for TOCTOU +# We should either... +# A. Do more checks to verify that the CSR is trusted/valid +# B. Audit the parsing code for vulnerabilities + +def valid_csr(csr): + """Validate CSR. + + Check if `csr` is a valid CSR for the given domains. + + :param str csr: CSR in PEM. + + :returns: Validity of CSR. + :rtype: bool + + """ + try: + csr_obj = M2Crypto.X509.load_request_string(csr) + return bool(csr_obj.verify(csr_obj.get_pubkey())) + except M2Crypto.X509.X509Error: + return False + + +def csr_matches_pubkey(csr, privkey): + """Does private key correspond to the subject public key in the CSR? + + :param str csr: CSR in PEM. + :param str privkey: Private key file contents + + :returns: Correspondence of private key to CSR subject public key. + :rtype: bool + + """ + csr_obj = M2Crypto.X509.load_request_string(csr) + privkey_obj = M2Crypto.RSA.load_key_string(privkey) + return csr_obj.get_pubkey().get_rsa().pub() == privkey_obj.pub() + + +# based on M2Crypto unit test written by Toby Allsopp +def make_key(bits=CONFIG.RSA_KEY_SIZE): + """Generate PEM encoded RSA key. + + :param int bits: Number of bits, at least 1024. + + :returns: new RSA key in PEM form with specified number of bits + :rtype: str + + """ + # rsa = M2Crypto.RSA.gen_key(bits, 65537) + # key_pem = rsa.as_pem(cipher=None) + # rsa = None # should not be freed here + # Python Crypto module doesn't produce any stdout + return Crypto.PublicKey.RSA.generate(bits).exportKey(format='PEM') + + +def valid_privkey(privkey): + """Is valid RSA private key? + + :param str privkey: Private key file contents + + :returns: Validity of private key. + :rtype: bool + + """ + try: + return bool(M2Crypto.RSA.load_key_string(privkey).check_key()) + except M2Crypto.RSA.RSAError: + return False + + +def make_ss_cert(key_str, domains, not_before=None, + validity=(7 * 24 * 60 * 60)): """Returns new self-signed cert in PEM form. Uses key_str and contains all domains. + """ assert domains, "Must provide one or more hostnames for the CSR." @@ -142,11 +194,11 @@ def make_ss_cert(key_str, domains): cert.set_serial_number(1337) cert.set_version(2) - current_ts = long(time.time()) + current_ts = long(time.time() if not_before is None else not_before) current = M2Crypto.ASN1.ASN1_UTCTIME() current.set_time(current_ts) expire = M2Crypto.ASN1.ASN1_UTCTIME() - expire.set_time((7 * 24 * 60 * 60) + current_ts) + expire.set_time(current_ts + validity) cert.set_not_before(current) cert.set_not_after(expire) @@ -158,11 +210,13 @@ def make_ss_cert(key_str, domains): subject.CN = domains[0] cert.set_issuer(cert.get_subject()) - cert.add_ext(M2Crypto.X509.new_extension('basicConstraints', 'CA:FALSE')) - # cert.add_ext(M2Crypto.X509.new_extension( - # 'extendedKeyUsage', 'TLS Web Server Authentication')) - cert.add_ext(M2Crypto.X509.new_extension( - 'subjectAltName', ", ".join(["DNS:%s" % d for d in domains]))) + if len(domains) > 1: + cert.add_ext(M2Crypto.X509.new_extension( + 'basicConstraints', 'CA:FALSE')) + # cert.add_ext(M2Crypto.X509.new_extension( + # 'extendedKeyUsage', 'TLS Web Server Authentication')) + cert.add_ext(M2Crypto.X509.new_extension( + 'subjectAltName', ", ".join(["DNS:%s" % d for d in domains]))) cert.sign(pubkey, 'sha256') assert cert.verify(pubkey) @@ -200,75 +254,6 @@ def get_cert_info(filename): } -# WARNING: the csr and private key file are possible attack vectors for TOCTOU -# We should either... -# A. Do more checks to verify that the CSR is trusted/valid -# B. Audit the parsing code for vulnerabilities - -def valid_csr(csr): - """Validate CSR. - - Check if `csr` is a valid CSR for the given domains. - - :param str csr: CSR file contents - - :returns: Validity of CSR. - :rtype: bool - - """ - try: - csr_obj = M2Crypto.X509.load_request_string(csr) - return bool(csr_obj.verify(csr_obj.get_pubkey())) - except M2Crypto.X509.X509Error: - return False - - -def csr_matches_names(csr, domains): - """Check if CSR contains the subject of one of the domains. - - M2Crypto currently does not expose the OpenSSL interface to - also check the SAN extension. This is insufficient for full testing - - :param str csr: CSR file contents - - :param list domains: Domains the CSR should contain. - - :returns: If the CSR subject contains one of the domains - :rtype: bool - - """ - try: - csr_obj = M2Crypto.X509.load_request_der_string(csr) - return csr_obj.get_subject().CN in domains - except M2Crypto.X509.X509Error: - return False - - -def valid_privkey(privkey): - """Is valid RSA private key? - - :param str privkey: Private key file contents - - :returns: Validity of private key. - :rtype: bool - - """ - try: - return bool(M2Crypto.RSA.load_key_string(privkey).check_key()) - except M2Crypto.RSA.RSAError: - return False - - -def csr_matches_pubkey(csr, privkey): - """Does private key correspond to the subject public key in the CSR? - - :param str csr: CSR file contents - :param str privkey: Private key file contents - - :returns: Correspondence of private key to CSR subject public key. - :rtype: bool - - """ - csr_obj = M2Crypto.X509.load_request_string(csr) - privkey_obj = M2Crypto.RSA.load_key_string(privkey) - return csr_obj.get_pubkey().get_rsa().pub() == privkey_obj.pub() +def b64_cert_to_pem(b64_der_cert): + return M2Crypto.X509.load_cert_der_string( + le_util.jose_b64decode(b64_der_cert)).as_pem() diff --git a/letsencrypt/client/tests/acme_test.py b/letsencrypt/client/tests/acme_test.py index df232c75a..808eefc1b 100644 --- a/letsencrypt/client/tests/acme_test.py +++ b/letsencrypt/client/tests/acme_test.py @@ -1,4 +1,5 @@ """Tests for letsencrypt.client.acme.""" +import pkg_resources import unittest import jsonschema @@ -58,15 +59,8 @@ class MessageFactoriesTest(unittest.TestCase): """Tests for ACME message factories from letsencrypt.client.acme.""" def setUp(self): - self.privkey = """-----BEGIN RSA PRIVATE KEY----- -MIIBOgIBAAJBAKx1c7RR7R/drnBSQ/zfx1vQLHUbFLh1AQQQ5R8DZUXd36efNK79 -vukFhN9HFoHZiUvOjm0c+pVE6K+EdE/twuUCAwEAAQJAMbrEnJCrQe8YqAbw1/Bn -elAzIamndfE3U8bTavf9sgFpS4HL83rhd6PDbvx81ucaJAT/5x048fM/nFl4fzAc -mQIhAOF/a9o3EIsDKEmUl+Z1OaOiUxDF3kqWSmALEsmvDhwXAiEAw8ljV5RO/rUp -Zu2YMDFq3MKpyyMgBIJ8CxmGRc6gCmMCIGRQzkcmhfqBrhOFwkmozrqIBRIKJIjj -8TRm2LXWZZ2DAiAqVO7PztdNpynugUy4jtbGKKjBrTSNBRGA7OHlUgm0dQIhALQq -6oGU29Vxlvt3k0vmiRKU4AVfLyNXIGtcWcNG46h/ ------END RSA PRIVATE KEY-----""" + self.privkey = pkg_resources.resource_string( + __name__, 'testdata/rsa256_key.pem') self.nonce = '\xec\xd6\xf2oYH\xeb\x13\xd5#q\xe0\xdd\xa2\x92\xa9' self.b64nonce = '7Nbyb1lI6xPVI3Hg3aKSqQ' diff --git a/letsencrypt/client/tests/crypto_util_test.py b/letsencrypt/client/tests/crypto_util_test.py new file mode 100644 index 000000000..e80988d83 --- /dev/null +++ b/letsencrypt/client/tests/crypto_util_test.py @@ -0,0 +1,178 @@ +"""Tests for letsencrypt.client.crypto_util.""" +import datetime +import os +import pkg_resources +import unittest + +import M2Crypto + + +RSA256_KEY = pkg_resources.resource_string(__name__, 'testdata/rsa256_key.pem') +RSA512_KEY = pkg_resources.resource_string(__name__, 'testdata/rsa512_key.pem') + + +class CreateSigTest(unittest.TestCase): + """Tests for letsencrypt.client.crypto_util.create_sig.""" + + def setUp(self): + self.nonce = '\xec\xd6\xf2oYH\xeb\x13\xd5#q\xe0\xdd\xa2\x92\xa9' + self.b64nonce = '7Nbyb1lI6xPVI3Hg3aKSqQ' + self.signature = { + 'nonce': self.b64nonce, + 'alg': 'RS256', + 'jwk': { + 'kty': 'RSA', + 'e': 'AQAB', + 'n': 'rHVztFHtH92ucFJD_N_HW9AsdRsUuHUBBBDlHwNlRd3fp5' + '80rv2-6QWE30cWgdmJS86ObRz6lUTor4R0T-3C5Q', + }, + 'sig': 'SUPYKucUnhlTt8_sMxLiigOYdf_wlOLXPI-o7aRLTsOquVjDd6r' + 'AX9AFJHk-bCMQPJbSzXKjG6H1IWbvxjS2Ew', + } + + def _call(self, *args, **kwargs): + from letsencrypt.client.crypto_util import create_sig + return create_sig(*args, **kwargs) + + def test_it(self): + self.assertEqual( + self._call('message', RSA256_KEY, self.nonce), self.signature) + + def test_random_nonce(self): + signature = self._call('message', RSA256_KEY) + signature.pop('sig') + signature.pop('nonce') + del self.signature['sig'] + del self.signature['nonce'] + self.assertEqual(signature, self.signature) + + +class ValidCSRTest(unittest.TestCase): + """Tests for letsencrypt.client.crypto_util.valid_csr.""" + + def _call(self, csr): + from letsencrypt.client.crypto_util import valid_csr + return valid_csr(csr) + + def _call_testdata(self, name): + return self._call(pkg_resources.resource_string( + __name__, os.path.join('testdata', name))) + + def test_valid_pem_true(self): + self.assertTrue(self._call_testdata('csr.pem')) + + def test_valid_pem_san_true(self): + self.assertTrue(self._call_testdata('csr-san.pem')) + + def test_valid_der_false(self): + self.assertFalse(self._call_testdata('csr.der')) + + def test_valid_der_san_false(self): + self.assertFalse(self._call_testdata('csr-san.der')) + + def test_empty_false(self): + self.assertFalse(self._call('')) + + def test_random_false(self): + self.assertFalse(self._call('foo bar')) + + +class CSRMatchesPubkeyTest(unittest.TestCase): + """Tests for letsencrypt.client.crypto_util.csr_matches_pubkey.""" + + def _call_testdata(self, name, privkey): + from letsencrypt.client.crypto_util import csr_matches_pubkey + return csr_matches_pubkey(pkg_resources.resource_string( + __name__, os.path.join('testdata', name)), privkey) + + def test_valid_true(self): + self.assertTrue(self._call_testdata('csr.pem', RSA256_KEY)) + + def test_invalid_false(self): + self.assertFalse(self._call_testdata('csr.pem', RSA512_KEY)) + + +class MakeKeyTest(unittest.TestCase): + """Tests for letsencrypt.client.crypto_util.make_key.""" + + def test_it(self): + from letsencrypt.client.crypto_util import make_key + M2Crypto.RSA.load_key_string(make_key(1024)) + + +class ValidPrivkeyTest(unittest.TestCase): + """Tests for letsencrypt.client.crypto_util.valid_privkey.""" + + def _call(self, privkey): + from letsencrypt.client.crypto_util import valid_privkey + return valid_privkey(privkey) + + def test_valid_true(self): + self.assertTrue(self._call(RSA256_KEY)) + + def test_empty_false(self): + self.assertFalse(self._call('')) + + def test_random_false(self): + self.assertFalse(self._call('foo bar')) + + +class MakeSSCertTest(unittest.TestCase): + """Tests for letsencrypt.client.crypto_util.make_ss_cert.""" + + def test_it(self): + from letsencrypt.client.crypto_util import make_ss_cert + make_ss_cert(RSA256_KEY, ['example.com', 'www.example.com']) + + +class GetCertInfoTest(unittest.TestCase): + """Tests for letsencrypt.client.crypto_util.get_cert_info.""" + + def setUp(self): + self.cert_info = { + 'not_before': datetime.datetime( + 2014, 12, 11, 22, 34, 45, tzinfo=M2Crypto.ASN1.UTC), + 'not_after': datetime.datetime( + 2014, 12, 18, 22, 34, 45, tzinfo=M2Crypto.ASN1.UTC), + 'subject': 'C=US, ST=Michigan, L=Ann Arbor, O=University ' + 'of Michigan and the EFF, CN=example.com', + 'cn': 'example.com', + 'issuer': 'C=US, ST=Michigan, L=Ann Arbor, O=University ' + 'of Michigan and the EFF, CN=example.com', + 'serial': 1337L, + 'pub_key': 'RSA 512', + } + + def _call(self, name): + from letsencrypt.client.crypto_util import get_cert_info + self.assertEqual(get_cert_info(pkg_resources.resource_filename( + __name__, os.path.join('testdata', name))), self.cert_info) + + def test_single_domain(self): + self.cert_info.update({ + 'san': '', + 'fingerprint': '9F8CE01450D288467C3326AC0457E351939C72E', + }) + self._call('cert.pem') + + def test_san(self): + self.cert_info.update({ + 'san': 'DNS:example.com, DNS:www.example.com', + 'fingerprint': '62F7110431B8E8F55905DBE5592518F9634AC50A', + }) + self._call('cert-san.pem') + + +class B64CertToPEMTest(unittest.TestCase): + """Tests for letsencrypt.client.crypto_util.b64_cert_to_pem.""" + + def test_it(self): + from letsencrypt.client.crypto_util import b64_cert_to_pem + self.assertEqual( + b64_cert_to_pem(pkg_resources.resource_string( + __name__, 'testdata/cert.b64jose')), + pkg_resources.resource_string(__name__, 'testdata/cert.pem')) + + +if __name__ == '__main__': + unittest.main() diff --git a/letsencrypt/client/tests/testdata/cert-san.pem b/letsencrypt/client/tests/testdata/cert-san.pem new file mode 100644 index 000000000..dcb835994 --- /dev/null +++ b/letsencrypt/client/tests/testdata/cert-san.pem @@ -0,0 +1,14 @@ +-----BEGIN CERTIFICATE----- +MIICFjCCAcCgAwIBAgICBTkwDQYJKoZIhvcNAQELBQAwdzELMAkGA1UEBhMCVVMx +ETAPBgNVBAgMCE1pY2hpZ2FuMRIwEAYDVQQHDAlBbm4gQXJib3IxKzApBgNVBAoM +IlVuaXZlcnNpdHkgb2YgTWljaGlnYW4gYW5kIHRoZSBFRkYxFDASBgNVBAMMC2V4 +YW1wbGUuY29tMB4XDTE0MTIxMTIyMzQ0NVoXDTE0MTIxODIyMzQ0NVowdzELMAkG +A1UEBhMCVVMxETAPBgNVBAgMCE1pY2hpZ2FuMRIwEAYDVQQHDAlBbm4gQXJib3Ix +KzApBgNVBAoMIlVuaXZlcnNpdHkgb2YgTWljaGlnYW4gYW5kIHRoZSBFRkYxFDAS +BgNVBAMMC2V4YW1wbGUuY29tMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKx1c7RR +7R/drnBSQ/zfx1vQLHUbFLh1AQQQ5R8DZUXd36efNK79vukFhN9HFoHZiUvOjm0c ++pVE6K+EdE/twuUCAwEAAaM2MDQwCQYDVR0TBAIwADAnBgNVHREEIDAeggtleGFt +cGxlLmNvbYIPd3d3LmV4YW1wbGUuY29tMA0GCSqGSIb3DQEBCwUAA0EASuvNKFTF +nTJsvnSXn52f4BMZJJ2id/kW7+r+FJRm+L20gKQ1aqq8d3e/lzRUrv5SMf1TAOe7 +RDjyGMKy5ZgM2w== +-----END CERTIFICATE----- diff --git a/letsencrypt/client/tests/testdata/cert.b64jose b/letsencrypt/client/tests/testdata/cert.b64jose new file mode 100644 index 000000000..fa1abdb9f --- /dev/null +++ b/letsencrypt/client/tests/testdata/cert.b64jose @@ -0,0 +1 @@ +MIIB3jCCAYigAwIBAgICBTkwDQYJKoZIhvcNAQELBQAwdzELMAkGA1UEBhMCVVMxETAPBgNVBAgMCE1pY2hpZ2FuMRIwEAYDVQQHDAlBbm4gQXJib3IxKzApBgNVBAoMIlVuaXZlcnNpdHkgb2YgTWljaGlnYW4gYW5kIHRoZSBFRkYxFDASBgNVBAMMC2V4YW1wbGUuY29tMB4XDTE0MTIxMTIyMzQ0NVoXDTE0MTIxODIyMzQ0NVowdzELMAkGA1UEBhMCVVMxETAPBgNVBAgMCE1pY2hpZ2FuMRIwEAYDVQQHDAlBbm4gQXJib3IxKzApBgNVBAoMIlVuaXZlcnNpdHkgb2YgTWljaGlnYW4gYW5kIHRoZSBFRkYxFDASBgNVBAMMC2V4YW1wbGUuY29tMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKx1c7RR7R_drnBSQ_zfx1vQLHUbFLh1AQQQ5R8DZUXd36efNK79vukFhN9HFoHZiUvOjm0c-pVE6K-EdE_twuUCAwEAATANBgkqhkiG9w0BAQsFAANBAC24z0IdwIVKSlntksllvr6zJepBH5fMndfk3XJp10jT6VE-14KNtjh02a56GoraAvJAT5_H67E8GvJ_ocNnB_o \ No newline at end of file diff --git a/letsencrypt/client/tests/testdata/cert.pem b/letsencrypt/client/tests/testdata/cert.pem new file mode 100644 index 000000000..96c55cbf4 --- /dev/null +++ b/letsencrypt/client/tests/testdata/cert.pem @@ -0,0 +1,13 @@ +-----BEGIN CERTIFICATE----- +MIIB3jCCAYigAwIBAgICBTkwDQYJKoZIhvcNAQELBQAwdzELMAkGA1UEBhMCVVMx +ETAPBgNVBAgMCE1pY2hpZ2FuMRIwEAYDVQQHDAlBbm4gQXJib3IxKzApBgNVBAoM +IlVuaXZlcnNpdHkgb2YgTWljaGlnYW4gYW5kIHRoZSBFRkYxFDASBgNVBAMMC2V4 +YW1wbGUuY29tMB4XDTE0MTIxMTIyMzQ0NVoXDTE0MTIxODIyMzQ0NVowdzELMAkG +A1UEBhMCVVMxETAPBgNVBAgMCE1pY2hpZ2FuMRIwEAYDVQQHDAlBbm4gQXJib3Ix +KzApBgNVBAoMIlVuaXZlcnNpdHkgb2YgTWljaGlnYW4gYW5kIHRoZSBFRkYxFDAS +BgNVBAMMC2V4YW1wbGUuY29tMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKx1c7RR +7R/drnBSQ/zfx1vQLHUbFLh1AQQQ5R8DZUXd36efNK79vukFhN9HFoHZiUvOjm0c ++pVE6K+EdE/twuUCAwEAATANBgkqhkiG9w0BAQsFAANBAC24z0IdwIVKSlntksll +vr6zJepBH5fMndfk3XJp10jT6VE+14KNtjh02a56GoraAvJAT5/H67E8GvJ/ocNn +B/o= +-----END CERTIFICATE----- diff --git a/letsencrypt/client/tests/testdata/csr-san.der b/letsencrypt/client/tests/testdata/csr-san.der new file mode 100644 index 000000000..68fd38723 Binary files /dev/null and b/letsencrypt/client/tests/testdata/csr-san.der differ diff --git a/letsencrypt/client/tests/testdata/csr-san.pem b/letsencrypt/client/tests/testdata/csr-san.pem new file mode 100644 index 000000000..a7128e35c --- /dev/null +++ b/letsencrypt/client/tests/testdata/csr-san.pem @@ -0,0 +1,10 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIBbjCCARgCAQAweTELMAkGA1UEBhMCVVMxETAPBgNVBAgMCE1pY2hpZ2FuMRIw +EAYDVQQHDAlBbm4gQXJib3IxDDAKBgNVBAoMA0VGRjEfMB0GA1UECwwWVW5pdmVy +c2l0eSBvZiBNaWNoaWdhbjEUMBIGA1UEAwwLZXhhbXBsZS5jb20wXDANBgkqhkiG +9w0BAQEFAANLADBIAkEArHVztFHtH92ucFJD/N/HW9AsdRsUuHUBBBDlHwNlRd3f +p580rv2+6QWE30cWgdmJS86ObRz6lUTor4R0T+3C5QIDAQABoDowOAYJKoZIhvcN +AQkOMSswKTAnBgNVHREEIDAeggtleGFtcGxlLmNvbYIPd3d3LmV4YW1wbGUuY29t +MA0GCSqGSIb3DQEBCwUAA0EAZGBM8J1rRs7onFgtc76mOeoT1c3v0ZsEmxQfb2Wy +tmReY6X1N4cs38D9VSow+VMRu2LWkKvzS7RUFSaTaeQz1A== +-----END CERTIFICATE REQUEST----- diff --git a/letsencrypt/client/tests/testdata/csr.der b/letsencrypt/client/tests/testdata/csr.der new file mode 100644 index 000000000..22900a612 Binary files /dev/null and b/letsencrypt/client/tests/testdata/csr.der differ diff --git a/letsencrypt/client/tests/testdata/csr.pem b/letsencrypt/client/tests/testdata/csr.pem new file mode 100644 index 000000000..b6818e39d --- /dev/null +++ b/letsencrypt/client/tests/testdata/csr.pem @@ -0,0 +1,10 @@ +-----BEGIN CERTIFICATE REQUEST----- +MIIBXTCCAQcCAQAweTELMAkGA1UEBhMCVVMxETAPBgNVBAgMCE1pY2hpZ2FuMRIw +EAYDVQQHDAlBbm4gQXJib3IxDDAKBgNVBAoMA0VGRjEfMB0GA1UECwwWVW5pdmVy +c2l0eSBvZiBNaWNoaWdhbjEUMBIGA1UEAwwLZXhhbXBsZS5jb20wXDANBgkqhkiG +9w0BAQEFAANLADBIAkEArHVztFHtH92ucFJD/N/HW9AsdRsUuHUBBBDlHwNlRd3f +p580rv2+6QWE30cWgdmJS86ObRz6lUTor4R0T+3C5QIDAQABoCkwJwYJKoZIhvcN +AQkOMRowGDAWBgNVHREEDzANggtleGFtcGxlLmNvbTANBgkqhkiG9w0BAQsFAANB +AHJH/O6BtC9aGzEVCMGOZ7z9iIRHWSzr9x/bOzn7hLwsbXPAgO1QxEwL+X+4g20G +n9XBE1N9W6HCIEut2d8wACg= +-----END CERTIFICATE REQUEST----- diff --git a/letsencrypt/client/tests/testdata/rsa256_key.pem b/letsencrypt/client/tests/testdata/rsa256_key.pem new file mode 100644 index 000000000..610c8d315 --- /dev/null +++ b/letsencrypt/client/tests/testdata/rsa256_key.pem @@ -0,0 +1,9 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIBOgIBAAJBAKx1c7RR7R/drnBSQ/zfx1vQLHUbFLh1AQQQ5R8DZUXd36efNK79 +vukFhN9HFoHZiUvOjm0c+pVE6K+EdE/twuUCAwEAAQJAMbrEnJCrQe8YqAbw1/Bn +elAzIamndfE3U8bTavf9sgFpS4HL83rhd6PDbvx81ucaJAT/5x048fM/nFl4fzAc +mQIhAOF/a9o3EIsDKEmUl+Z1OaOiUxDF3kqWSmALEsmvDhwXAiEAw8ljV5RO/rUp +Zu2YMDFq3MKpyyMgBIJ8CxmGRc6gCmMCIGRQzkcmhfqBrhOFwkmozrqIBRIKJIjj +8TRm2LXWZZ2DAiAqVO7PztdNpynugUy4jtbGKKjBrTSNBRGA7OHlUgm0dQIhALQq +6oGU29Vxlvt3k0vmiRKU4AVfLyNXIGtcWcNG46h/ +-----END RSA PRIVATE KEY----- diff --git a/letsencrypt/client/tests/testdata/rsa512_key.pem b/letsencrypt/client/tests/testdata/rsa512_key.pem new file mode 100644 index 000000000..709b6d8e3 --- /dev/null +++ b/letsencrypt/client/tests/testdata/rsa512_key.pem @@ -0,0 +1,9 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIBOwIBAAJBAPS2EXFRNza/qpXnnBHF/CcFQ543htV+7nLAmrLrmTNHtPXJmLlM +8SJDIzv/ceAFXL110VzxFfi81lpH5E5c0TMCAwEAAQJBALmppYQ/JVARjWBcsEm/ +1/bXBJ127YLv4gQIY5baL4r6IdEE33OXMTTmD9wf+ajuq1eaH0htHkwhOvREu0sz +bskCIQD/Cg+xhEVLcwK3pFp3afPIhj1IPFiL3Uy/nqyMZ6O/RQIhAPWiDBofp7Cp +J4dGZs+hkRySq/IOeeRJlNK1Pq64nToXAiBZ7+te1100YSd5KT051SRB94zO13EG +SZESFduVW8rz3QIgK+tLiqg6TYYRQUi/PUTAM4GuKNuZw828RGiPyqHLywUCIQCd +pkZrNphL/y0D7HSbPIfZzD90M2V8tUjlK0BTqk1bHA== +-----END RSA PRIVATE KEY-----