1
0
mirror of https://github.com/certbot/certbot.git synced 2026-01-29 10:02:08 +03:00

ACME Signature: JWK with pubkey only

This commit is contained in:
Jakub Warmuz
2015-02-05 09:40:52 +00:00
parent d68e4d564d
commit 79af38cd1b
4 changed files with 41 additions and 61 deletions

View File

@@ -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."""

View File

@@ -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

View File

@@ -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):

View File

@@ -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__':