diff --git a/letsencrypt/acme/jose.py b/letsencrypt/acme/jose.py index 7507178a8..156ada1e0 100644 --- a/letsencrypt/acme/jose.py +++ b/letsencrypt/acme/jose.py @@ -17,7 +17,7 @@ def _leading_zeros(arg): class JWK(object): """JSON Web Key. - .. todo:: Currently works for RSA keys only. + .. todo:: Currently works for RSA public keys only. """ zope.interface.implements(interfaces.IJSONSerializable) @@ -32,14 +32,6 @@ class JWK(object): raise TypeError( 'Unable to compare JWK object with: {0}'.format(other)) - def same_public_key(self, other): - """Does ``other`` have the same public key?""" - if isinstance(other, JWK): - return self.key.publickey() == other.key.publickey() - else: - raise TypeError( - 'Unable to compare JWK object with: {0}'.format(other)) - @classmethod def _encode_param(cls, param): """Encode numeric key parameter.""" diff --git a/letsencrypt/acme/jose_test.py b/letsencrypt/acme/jose_test.py index 343731a6f..7c31975e7 100644 --- a/letsencrypt/acme/jose_test.py +++ b/letsencrypt/acme/jose_test.py @@ -5,26 +5,31 @@ import unittest import Crypto.PublicKey.RSA -RSA256_KEY_PATH = pkg_resources.resource_string( - 'letsencrypt.client.tests', 'testdata/rsa256_key.pem') -RSA256_KEY = Crypto.PublicKey.RSA.importKey(RSA256_KEY_PATH) -RSA512_KEY_PATH = pkg_resources.resource_string( - 'letsencrypt.client.tests', 'testdata/rsa512_key.pem') -RSA512_KEY = Crypto.PublicKey.RSA.importKey(RSA512_KEY_PATH) +RSA256_KEY = Crypto.PublicKey.RSA.importKey(pkg_resources.resource_string( + 'letsencrypt.client.tests', 'testdata/rsa256_key.pem')) +RSA512_KEY = Crypto.PublicKey.RSA.importKey(pkg_resources.resource_string( + 'letsencrypt.client.tests', 'testdata/rsa512_key.pem')) class JWKTest(unittest.TestCase): + """Tests fro letsencrypt.acme.jose.JWK.""" def setUp(self): from letsencrypt.acme.jose import JWK - self.jwk256 = JWK(RSA256_KEY) + self.jwk256 = JWK(RSA256_KEY.publickey()) self.jwk256json = { 'kty': 'RSA', 'e': 'AQAB', 'n': 'rHVztFHtH92ucFJD_N_HW9AsdRsUuHUBBBDlHwNlRd3fp5' '80rv2-6QWE30cWgdmJS86ObRz6lUTor4R0T-3C5Q', } - self.jwk512 = JWK(RSA512_KEY) + self.jwk512 = JWK(RSA512_KEY.publickey()) + self.jwk512json = { + 'kty': 'RSA', + 'e': 'AQAB', + 'n': '9LYRcVE3Nr-qleecEcX8JwVDnjeG1X7ucsCasuuZM0e09c' + 'mYuUzxIkMjO_9x4AVcvXXRXPEV-LzWWkfkTlzRMw', + } def test_equals(self): self.assertEqual(self.jwk256, self.jwk256) @@ -37,24 +42,14 @@ class JWKTest(unittest.TestCase): def test_equals_raises_type_error(self): self.assertRaises(TypeError, self.jwk256.__eq__, 123) - def test_same_public_key(self): - from letsencrypt.acme.jose import JWK - self.assertTrue(self.jwk256.same_public_key( - JWK(Crypto.PublicKey.RSA.importKey(RSA256_KEY_PATH)))) - - def test_not_same_public_key(self): - self.assertFalse(self.jwk256.same_public_key(self.jwk512)) - - def test_same_public_key_raises_type_error(self): - self.assertRaises(TypeError, self.jwk256.same_public_key, 5) - def test_to_json(self): self.assertEqual(self.jwk256.to_json(), self.jwk256json) + self.assertEqual(self.jwk512.to_json(), self.jwk512json) def test_from_json(self): from letsencrypt.acme.jose import JWK - self.assertTrue(self.jwk256.same_public_key( - JWK.from_json(self.jwk256json))) + self.assertEqual(self.jwk256, JWK.from_json(self.jwk256json)) + self.assertEqual(self.jwk512, JWK.from_json(self.jwk512json)) # https://en.wikipedia.org/wiki/Base64#Examples diff --git a/letsencrypt/acme/other.py b/letsencrypt/acme/other.py index b920282a2..968d1f5f4 100644 --- a/letsencrypt/acme/other.py +++ b/letsencrypt/acme/other.py @@ -64,7 +64,7 @@ class Signature(object): logging.debug('%s signed as %s', msg_with_nonce, sig) - return cls('RS256', sig, nonce, jose.JWK(key)) + return cls('RS256', sig, nonce, jose.JWK(key.publickey())) def __eq__(self, other): if isinstance(other, Signature): diff --git a/letsencrypt/acme/other_test.py b/letsencrypt/acme/other_test.py index 0498443d9..50b77f50a 100644 --- a/letsencrypt/acme/other_test.py +++ b/letsencrypt/acme/other_test.py @@ -27,7 +27,7 @@ class SigatureTest(unittest.TestCase): '\xb9X\xc3w\xaa\xc0_\xd0\x05$y>l#\x10<\x96\xd2\xcdr\xa3' '\x1b\xa1\xf5!f\xef\xc64\xb6\x13') self.nonce = '\xec\xd6\xf2oYH\xeb\x13\xd5#q\xe0\xdd\xa2\x92\xa9' - self.jwk = jose.JWK(RSA256_KEY) + self.jwk = jose.JWK(RSA256_KEY.publickey()) b64sig = ('SUPYKucUnhlTt8_sMxLiigOYdf_wlOLXPI-o7aRLTsOquVjDd6r' 'AX9AFJHk-bCMQPJbSzXKjG6H1IWbvxjS2Ew') @@ -39,60 +39,53 @@ class SigatureTest(unittest.TestCase): 'sig': b64sig, } - self.pub_jwk = jose.JWK(RSA256_KEY.publickey()) self.jsig_from = { 'nonce': b64nonce, 'alg': self.alg, - 'jwk': self.pub_jwk.to_json(), + 'jwk': self.jwk.to_json(), 'sig': b64sig, } - self.signature = self._from_msg(self.msg, RSA256_KEY, self.nonce) from letsencrypt.acme.other import Signature - self.pub_signature = Signature( - self.alg, self.sig, self.nonce, self.pub_jwk) + self.signature = Signature(self.alg, self.sig, self.nonce, self.jwk) + + def test_attributes(self): + self.assertEqual(self.signature.nonce, self.nonce) + self.assertEqual(self.signature.alg, self.alg) + self.assertEqual(self.signature.sig, self.sig) + self.assertEqual(self.signature.jwk, self.jwk) + + def test_verify_good_succeeds(self): + self.assertTrue(self.signature.verify(self.msg)) + + def test_verify_bad_fails(self): + self.assertFalse(self.signature.verify(self.msg + 'x')) @classmethod def _from_msg(cls, *args, **kwargs): from letsencrypt.acme.other import Signature return Signature.from_msg(*args, **kwargs) - def test_verify_with_private_key(self): - self.assertTrue(self.signature.verify(self.msg)) - - def test_verify_without_private_key(self): - self.assertTrue(self.pub_signature.verify(self.msg)) - - def test_verify_bad_fails(self): - self.signature.sig = self.sig + "foo" - self.assertFalse(self.signature.verify(self.msg)) - def test_create_from_msg(self): - self.assertEqual(self.signature.nonce, self.nonce) - self.assertEqual(self.signature.alg, self.alg) - self.assertEqual(self.signature.sig, self.sig) - self.assertEqual(self.signature.jwk, self.jwk) + signature = self._from_msg(self.msg, RSA256_KEY, self.nonce) + self.assertEqual(self.signature, signature) def test_create_from_msg_random_nonce(self): - sig = self._from_msg(self.msg, RSA256_KEY) - self.assertEqual(sig.alg, self.alg) - self.assertEqual(sig.jwk, self.jwk) - self.assertTrue(sig.verify(self.msg)) + signature = self._from_msg(self.msg, RSA256_KEY) + self.assertEqual(signature.alg, self.alg) + self.assertEqual(signature.jwk, self.jwk) + self.assertTrue(signature.verify(self.msg)) def test_to_json(self): self.assertEqual(self.signature.to_json(), self.jsig_to) def test_from_json(self): from letsencrypt.acme.other import Signature - signature = Signature.from_json(self.jsig_from) - self.assertEqual(self.pub_signature, signature) - - def test_sig_and_pub_sig_not_equal(self): - self.assertNotEqual(self.pub_signature, self.signature) + self.assertEqual(self.signature, Signature.from_json(self.jsig_from)) def test_eq_raises_type_error(self): self.assertRaises( - TypeError, functools.partial(operator.eq, self.signature), "foo") + TypeError, functools.partial(operator.eq, self.signature), 'foo') if __name__ == '__main__':