def setUp(self): from acme.client import ClientNetwork self.net = ClientNetwork(key=None, alg=None) self.response = mock.MagicMock(ok=True, status_code=http_client.OK) self.response.headers = {} self.response.links = {} self.checked_response = mock.MagicMock() self.obj = mock.MagicMock() self.wrapped_obj = mock.MagicMock() self.content_type = mock.sentinel.content_type self.all_nonces = [jose.b64encode(b'Nonce'), jose.b64encode(b'Nonce2')] self.available_nonces = self.all_nonces[:] def send_request(*args, **kwargs): # pylint: disable=unused-argument,missing-docstring if self.available_nonces: self.response.headers = { self.net.REPLAY_NONCE_HEADER: self.available_nonces.pop().decode()} else: self.response.headers = {} return self.response # pylint: disable=protected-access self.net._send_request = self.send_request = mock.MagicMock( side_effect=send_request) self.net._check_response = self.check_response self.net._wrap_in_jws = mock.MagicMock(return_value=self.wrapped_obj)
def setUp(self): from acme.client import ClientNetwork self.net = ClientNetwork(key=None, alg=None) self.response = mock.MagicMock(ok=True, status_code=http_client.OK) self.response.headers = {} self.response.links = {} self.checked_response = mock.MagicMock() self.obj = mock.MagicMock() self.wrapped_obj = mock.MagicMock() self.content_type = mock.sentinel.content_type self.all_nonces = [ jose.b64encode(b'Nonce'), jose.b64encode(b'Nonce2'), jose.b64encode(b'Nonce3') ] self.available_nonces = self.all_nonces[:] def send_request(*args, **kwargs): # pylint: disable=unused-argument,missing-docstring if self.available_nonces: self.response.headers = { self.net.REPLAY_NONCE_HEADER: self.available_nonces.pop().decode() } else: self.response.headers = {} return self.response # pylint: disable=protected-access self.net._send_request = self.send_request = mock.MagicMock( side_effect=send_request) self.net._check_response = self.check_response self.net._wrap_in_jws = mock.MagicMock(return_value=self.wrapped_obj)
def setUp(self): refresh = 'https://example.com/refresh/Dr8eAwTVQfSS/' from acme.messages import Certificate self.msg = Certificate( certificate=CERT, chain=(CERT,), refresh=refresh) self.jmsg_to = { 'type': 'certificate', 'certificate': jose.b64encode(CERT.as_der()), 'chain': (jose.b64encode(CERT.as_der()),), 'refresh': refresh, } self.jmsg_from = self.jmsg_to.copy() # TODO: schema validation array tuples self.jmsg_from['chain'] = list(self.jmsg_from['chain'])
def test_post_wrong_post_response_nonce(self): self.available_nonces = [jose.b64encode(b'good'), b'f'] self.assertRaises(errors.BadNonce, self.net.post, 'uri', self.obj, content_type=self.content_type)
def _perform_single(self, achall): # same path for each challenge response would be easier for # users, but will not work if multiple domains point at the # same server: default command doesn't support virtual hosts response = challenges.SimpleHTTPResponse( path=jose.b64encode(os.urandom(18)), tls=(not self.config.no_simple_http_tls)) assert response.good_path # is encoded os.urandom(18) good? self._notify_and_wait( self.MESSAGE_TEMPLATE.format( achall=achall, response=response, uri=response.uri(achall.domain), ct=response.CONTENT_TYPE, command=self.template.format( achall=achall, response=response, ct=response.CONTENT_TYPE, port=(response.port if self.config.simple_http_port is None else self.config.simple_http_port)))) if response.simple_verify(achall.challb, achall.domain, self.config.simple_http_port): return response else: return None
def test_post_replay_nonce_handling(self, requests_mock): # pylint: disable=protected-access self.net._check_response = mock.MagicMock() self._mock_wrap_in_jws() self.net._nonces.clear() self.assertRaises( errors.NetworkError, self.net._post, 'uri', mock.sentinel.obj) nonce2 = jose.b64encode('Nonce2') requests_mock.head('uri').headers = { self.net.REPLAY_NONCE_HEADER: nonce2} requests_mock.post('uri').headers = { self.net.REPLAY_NONCE_HEADER: self.nonce} self.net._post('uri', mock.sentinel.obj) requests_mock.head.assert_called_with('uri') self.wrap_in_jws.assert_called_once_with(mock.sentinel.obj, nonce2) self.assertEqual(self.net._nonces, set([self.nonce])) # wrong nonce requests_mock.post('uri').headers = {self.net.REPLAY_NONCE_HEADER: 'F'} self.assertRaises( errors.NetworkError, self.net._post, 'uri', mock.sentinel.obj)
def verify(self, chall, account_public_key): """Verify the key authorization. :param KeyAuthorization chall: Challenge that corresponds to this response. :param JWK account_public_key: :return: ``True`` iff verification of the key authorization was successful. :rtype: bool """ parts = self.key_authorization.split('.') # pylint: disable=no-member if len(parts) != 2: logger.debug("Key authorization (%r) is not well formed", self.key_authorization) return False if parts[0] != chall.encode("token"): logger.debug( "Mismatching token in key authorization: " "%r instead of %r", parts[0], chall.encode("token")) return False thumbprint = jose.b64encode( account_public_key.thumbprint( hash_function=self.thumbprint_hash_function)).decode() if parts[1] != thumbprint: logger.debug( "Mismatching thumbprint in key authorization: " "%r instead of %r", parts[0], thumbprint) return False return True
def verify(self, chall, account_public_key): """Verify the key authorization. :param KeyAuthorization chall: Challenge that corresponds to this response. :param JWK account_public_key: :return: ``True`` iff verification of the key authorization was successful. :rtype: bool """ parts = self.key_authorization.split('.') # pylint: disable=no-member if len(parts) != 2: logger.debug("Key authorization (%r) is not well formed", self.key_authorization) return False if parts[0] != chall.encode("token"): logger.debug("Mismatching token in key authorization: " "%r instead of %r", parts[0], chall.encode("token")) return False thumbprint = jose.b64encode(account_public_key.thumbprint( hash_function=self.thumbprint_hash_function)).decode() if parts[1] != thumbprint: logger.debug("Mismatching thumbprint in key authorization: " "%r instead of %r", parts[0], thumbprint) return False return True
def setUp(self): jwk = jose.JWKRSA(key=KEY.publickey()) issuers = ( 'C=US, O=SuperT LLC, CN=SuperTrustworthy Public CA', 'O=LessTrustworthy CA Inc, CN=LessTrustworthy But StillSecure', ) cert_fingerprints = ( '93416768eb85e33adc4277f4c9acd63e7418fcfe', '16d95b7b63f1972b980b14c20291f3c0d1855d95', '48b46570d9fc6358108af43ad1649484def0debf', ) subject_key_identifiers = ('d0083162dcc4c8a23ecb8aecbd86120e56fd24e5') authorized_for = ('www.example.com', 'example.net') serial_numbers = (34234239832, 23993939911, 17) from acme.challenges import ProofOfPossession self.msg = ProofOfPossession.Hints( jwk=jwk, issuers=issuers, cert_fingerprints=cert_fingerprints, certs=(CERT,), subject_key_identifiers=subject_key_identifiers, authorized_for=authorized_for, serial_numbers=serial_numbers) self.jmsg_to = { 'jwk': jwk, 'certFingerprints': cert_fingerprints, 'certs': (jose.b64encode(CERT.as_der()),), 'subjectKeyIdentifiers': subject_key_identifiers, 'serialNumbers': serial_numbers, 'issuers': issuers, 'authorizedFor': authorized_for, } self.jmsg_from = self.jmsg_to.copy() self.jmsg_from.update({'jwk': jwk.to_json()})
def test_post_wrong_initial_nonce(self): # HEAD self.available_nonces = [b'f', jose.b64encode(b'good')] self.assertRaises(errors.BadNonce, self.net.post, 'uri', self.obj, content_type=self.content_type)
def test_post_replay_nonce_handling(self, requests_mock): # pylint: disable=protected-access self.net._check_response = mock.MagicMock() self._mock_wrap_in_jws() self.net._nonces.clear() self.assertRaises(errors.NetworkError, self.net._post, 'uri', mock.sentinel.obj) nonce2 = jose.b64encode('Nonce2') requests_mock.head('uri').headers = { self.net.REPLAY_NONCE_HEADER: nonce2 } requests_mock.post('uri').headers = { self.net.REPLAY_NONCE_HEADER: self.nonce } self.net._post('uri', mock.sentinel.obj) requests_mock.head.assert_called_with('uri') self.wrap_in_jws.assert_called_once_with(mock.sentinel.obj, nonce2) self.assertEqual(self.net._nonces, set([self.nonce])) # wrong nonce requests_mock.post('uri').headers = {self.net.REPLAY_NONCE_HEADER: 'F'} self.assertRaises(errors.NetworkError, self.net._post, 'uri', mock.sentinel.obj)
def setUp(self): refresh = 'https://example.com/refresh/Dr8eAwTVQfSS/' from acme.messages import Certificate self.msg = Certificate(certificate=CERT, chain=(CERT, ), refresh=refresh) self.jmsg_to = { 'type': 'certificate', 'certificate': jose.b64encode(CERT.as_der()), 'chain': (jose.b64encode(CERT.as_der()), ), 'refresh': refresh, } self.jmsg_from = self.jmsg_to.copy() # TODO: schema validation array tuples self.jmsg_from['chain'] = list(self.jmsg_from['chain'])
def setUp(self): self.verify_ssl = mock.MagicMock() self.wrap_in_jws = mock.MagicMock(return_value=mock.sentinel.wrapped) from letsencrypt.network2 import Network self.net = Network( new_reg_uri='https://www.letsencrypt-demo.org/acme/new-reg', key=KEY, alg=jose.RS256, verify_ssl=self.verify_ssl) self.nonce = jose.b64encode('Nonce') self.net._nonces.add(self.nonce) # pylint: disable=protected-access self.response = mock.MagicMock(ok=True, status_code=httplib.OK) self.response.headers = {} self.response.links = {} self.post = mock.MagicMock(return_value=self.response) self.get = mock.MagicMock(return_value=self.response) self.identifier = messages2.Identifier(typ=messages2.IDENTIFIER_FQDN, value='example.com') self.config = mock.Mock(accounts_dir=tempfile.mkdtemp()) # Registration self.contact = ('mailto:[email protected]', 'tel:+12025551212') reg = messages2.Registration(contact=self.contact, key=KEY.public(), recovery_token='t') self.regr = messages2.RegistrationResource( body=reg, uri='https://www.letsencrypt-demo.org/acme/reg/1', new_authzr_uri='https://www.letsencrypt-demo.org/acme/new-reg', terms_of_service='https://www.letsencrypt-demo.org/tos') # Authorization authzr_uri = 'https://www.letsencrypt-demo.org/acme/authz/1' challb = messages2.ChallengeBody(uri=(authzr_uri + '/1'), status=messages2.STATUS_VALID, chall=challenges.DNS(token='foo')) self.challr = messages2.ChallengeResource(body=challb, authzr_uri=authzr_uri) self.authz = messages2.Authorization(identifier=messages2.Identifier( typ=messages2.IDENTIFIER_FQDN, value='example.com'), challenges=(challb, ), combinations=None) self.authzr = messages2.AuthorizationResource( body=self.authz, uri=authzr_uri, new_cert_uri='https://www.letsencrypt-demo.org/acme/new-cert') # Request issuance self.certr = messages2.CertificateResource( body=CERT, authzrs=(self.authzr, ), uri='https://www.letsencrypt-demo.org/acme/cert/1', cert_chain_uri='https://www.letsencrypt-demo.org/ca')
def validation(self, account_key, **unused_kwargs): """Generate validation. :param JWK account_key: :rtype: unicode """ return jose.b64encode(hashlib.sha256(self.key_authorization( account_key).encode("utf-8")).digest()).decode()
def key_authorization(self, account_key): """Generate Key Authorization. :param JWK account_key: :rtype unicode: """ return self.encode("token") + "." + jose.b64encode( account_key.thumbprint( hash_function=self.thumbprint_hash_function)).decode()
def setUp(self): self.verify_ssl = mock.MagicMock() self.wrap_in_jws = mock.MagicMock(return_value=mock.sentinel.wrapped) from letsencrypt.network2 import Network self.net = Network( new_reg_uri='https://www.letsencrypt-demo.org/acme/new-reg', key=KEY, alg=jose.RS256, verify_ssl=self.verify_ssl) self.nonce = jose.b64encode('Nonce') self.net._nonces.add(self.nonce) # pylint: disable=protected-access self.response = mock.MagicMock(ok=True, status_code=httplib.OK) self.response.headers = {} self.response.links = {} self.post = mock.MagicMock(return_value=self.response) self.get = mock.MagicMock(return_value=self.response) self.identifier = messages2.Identifier( typ=messages2.IDENTIFIER_FQDN, value='example.com') self.config = mock.Mock(accounts_dir=tempfile.mkdtemp()) # Registration self.contact = ('mailto:[email protected]', 'tel:+12025551212') reg = messages2.Registration( contact=self.contact, key=KEY.public(), recovery_token='t') self.regr = messages2.RegistrationResource( body=reg, uri='https://www.letsencrypt-demo.org/acme/reg/1', new_authzr_uri='https://www.letsencrypt-demo.org/acme/new-reg', terms_of_service='https://www.letsencrypt-demo.org/tos') # Authorization authzr_uri = 'https://www.letsencrypt-demo.org/acme/authz/1' challb = messages2.ChallengeBody( uri=(authzr_uri + '/1'), status=messages2.STATUS_VALID, chall=challenges.DNS(token='foo')) self.challr = messages2.ChallengeResource( body=challb, authzr_uri=authzr_uri) self.authz = messages2.Authorization( identifier=messages2.Identifier( typ=messages2.IDENTIFIER_FQDN, value='example.com'), challenges=(challb,), combinations=None) self.authzr = messages2.AuthorizationResource( body=self.authz, uri=authzr_uri, new_cert_uri='https://www.letsencrypt-demo.org/acme/new-cert') # Request issuance self.certr = messages2.CertificateResource( body=CERT, authzrs=(self.authzr,), uri='https://www.letsencrypt-demo.org/acme/cert/1', cert_chain_uri='https://www.letsencrypt-demo.org/ca')
def _perform_single(self, achall): # same path for each challenge response would be easier for # users, but will not work if multiple domains point at the # same server: default command doesn't support virtual hosts response = challenges.SimpleHTTPResponse( path=jose.b64encode(os.urandom(18)), tls=(not self.config.no_simple_http_tls)) assert response.good_path # is encoded os.urandom(18) good? command = self.template.format( root=self._root, achall=achall, response=response, ct=response.CONTENT_TYPE, port=( response.port if self.config.simple_http_port is None else self.config.simple_http_port)) if self.conf("test-mode"): logger.debug("Test mode. Executing the manual command: %s", command) try: self._httpd = subprocess.Popen( command, # don't care about setting stdout and stderr, # we're in test mode anyway shell=True, # "preexec_fn" is UNIX specific, but so is "command" preexec_fn=os.setsid) except OSError as error: # ValueError should not happen! logger.debug( "Couldn't execute manual command: %s", error, exc_info=True) return False logger.debug("Manual command running as PID %s.", self._httpd.pid) # give it some time to bootstrap, before we try to verify # (cert generation in case of simpleHttpS might take time) time.sleep(4) # XXX if self._httpd.poll() is not None: raise errors.Error("Couldn't execute manual command") else: self._notify_and_wait(self.MESSAGE_TEMPLATE.format( achall=achall, response=response, uri=response.uri(achall.domain), ct=response.CONTENT_TYPE, command=command)) if response.simple_verify( achall.challb, achall.domain, self.config.simple_http_port): return response else: if self.conf("test-mode") and self._httpd.poll() is not None: # simply verify cause command failure... return False return None
def _perform_single(self, achall): # same path for each challenge response would be easier for # users, but will not work if multiple domains point at the # same server: default command doesn't support virtual hosts response = challenges.SimpleHTTPResponse( path=jose.b64encode(os.urandom(18)), tls=(not self.config.no_simple_http_tls)) assert response.good_path # is encoded os.urandom(18) good? self._notify_and_wait(self.MESSAGE_TEMPLATE.format( achall=achall, response=response, uri=response.uri(achall.domain), command=self.template.format(achall=achall, response=response))) if self._verify(achall, response): return response else: return None
def setUp(self): signature = other.Signature( alg=jose.RS256, jwk=jose.JWKRSA(key=KEY.publickey()), sig='\x15\xed\x84\xaa:\xf2DO\x0e9 \xbcg\xf8\xc0\xcf\x87\x9a' '\x95\xeb\xffT[\x84[\xec\x85\x7f\x8eK\xe9\xc2\x12\xc8Q' '\xafo\xc6h\x07\xba\xa6\xdf\xd1\xa7"$\xba=Z\x13n\x14\x0b' 'k\xfe\xee\xb4\xe4\xc8\x05\x9a\x08\xa7', nonce='\xec\xd6\xf2oYH\xeb\x13\xd5#q\xe0\xdd\xa2\x92\xa9') from acme.messages import CertificateRequest self.msg = CertificateRequest(csr=CSR, signature=signature) self.jmsg_to = { 'type': 'certificateRequest', 'csr': jose.b64encode(CSR.as_der()), 'signature': signature, } self.jmsg_from = self.jmsg_to.copy() self.jmsg_from['signature'] = self.jmsg_from['signature'].to_json()
def setUp(self): self.sig_nonce = '\xec\xd6\xf2oYH\xeb\x13\xd5#q\xe0\xdd\xa2\x92\xa9' signature = other.Signature( alg=jose.RS256, jwk=jose.JWKRSA(key=KEY.publickey()), sig='eJ\xfe\x12"U\x87\x8b\xbf/ ,\xdeP\xb2\xdc1\xb00\xe5\x1dB' '\xfch<\xc6\x9eH@!\x1c\x16\xb2\x0b_\xc4\xddP\x89\xc8\xce?' '\x16g\x069I\xb9\xb3\x91\xb9\x0e$3\x9f\x87\x8e\x82\xca\xc5' 's\xd9\xd0\xe7', nonce=self.sig_nonce) from acme.messages import RevocationRequest self.msg = RevocationRequest(certificate=CERT, signature=signature) self.jmsg_to = { 'type': 'revocationRequest', 'certificate': jose.b64encode(CERT.as_der()), 'signature': signature, } self.jmsg_from = self.jmsg_to.copy() self.jmsg_from['signature'] = self.jmsg_from['signature'].to_json()
class HeaderTest(unittest.TestCase): """Tests for acme.jws.Header.""" good_nonce = jose.b64encode('foo') wrong_nonce = 'F' # Following just makes sure wrong_nonce is wrong try: jose.b64decode(wrong_nonce) except (ValueError, TypeError): assert True else: assert False # pragma: no cover def test_validate_nonce(self): from acme.jws import Header self.assertTrue(Header.validate_nonce(self.good_nonce) is None) self.assertFalse(Header.validate_nonce(self.wrong_nonce) is None) def test_nonce_decoder(self): from acme.jws import Header nonce_field = Header._fields['nonce'] self.assertRaises(errors.Error, nonce_field.decode, self.wrong_nonce) self.assertEqual(self.good_nonce, nonce_field.decode(self.good_nonce))
def setUp(self): jwk = jose.JWKRSA(key=KEY.publickey()) issuers = ( 'C=US, O=SuperT LLC, CN=SuperTrustworthy Public CA', 'O=LessTrustworthy CA Inc, CN=LessTrustworthy But StillSecure', ) cert_fingerprints = ( '93416768eb85e33adc4277f4c9acd63e7418fcfe', '16d95b7b63f1972b980b14c20291f3c0d1855d95', '48b46570d9fc6358108af43ad1649484def0debf', ) subject_key_identifiers = ('d0083162dcc4c8a23ecb8aecbd86120e56fd24e5') authorized_for = ('www.example.com', 'example.net') serial_numbers = (34234239832, 23993939911, 17) from acme.challenges import ProofOfPossession self.msg = ProofOfPossession.Hints( jwk=jwk, issuers=issuers, cert_fingerprints=cert_fingerprints, certs=(CERT, ), subject_key_identifiers=subject_key_identifiers, authorized_for=authorized_for, serial_numbers=serial_numbers) self.jmsg_to = { 'jwk': jwk, 'certFingerprints': cert_fingerprints, 'certs': (jose.b64encode(CERT.as_der()), ), 'subjectKeyIdentifiers': subject_key_identifiers, 'serialNumbers': serial_numbers, 'issuers': issuers, 'authorizedFor': authorized_for, } self.jmsg_from = self.jmsg_to.copy() self.jmsg_from.update({'jwk': jwk.to_json()})
def _validation(response): """ Get the validation value for a challenge response. """ h = hashlib.sha256(response.key_authorization.encode("utf-8")) return jose.b64encode(h.digest()).decode()
def setUp(self): self.privkey = KEY self.pubkey = self.privkey.public_key() self.nonce = jose.b64encode(b'Nonce') self.url = 'hi' self.kid = 'baaaaa'
def setUp(self): self.privkey = KEY self.pubkey = self.privkey.public_key() self.nonce = jose.b64encode(b'Nonce')
def test_post_wrong_post_response_nonce(self): self.available_nonces = [jose.b64encode(b"good"), b"f"] self.assertRaises(errors.BadNonce, self.net.post, "uri", self.obj, content_type=self.content_type)
def setUp(self): self.privkey = jose.JWKRSA(key=RSA512_KEY) self.pubkey = self.privkey.public() self.nonce = jose.b64encode('Nonce')
def setUp(self): self.privkey = jose.JWKRSA(key=RSA512_KEY) self.pubkey = self.privkey.public_key() self.nonce = jose.b64encode('Nonce')