From 495e1adaca91dd255b85989cbe821c34ff3e1e42 Mon Sep 17 00:00:00 2001 From: James Kasten Date: Fri, 17 Apr 2015 15:09:19 -0700 Subject: [PATCH] Add Registration encoding/fix hashable JWKRSA --- letsencrypt/acme/jose/jwk.py | 7 +++-- letsencrypt/acme/jose/jwk_test.py | 16 ++++++----- letsencrypt/acme/messages2.py | 3 +- letsencrypt/acme/messages2_test.py | 45 ++++++++++++++++++++++++++++++ 4 files changed, 60 insertions(+), 11 deletions(-) diff --git a/letsencrypt/acme/jose/jwk.py b/letsencrypt/acme/jose/jwk.py index 1b7e00e56..2e70ac66b 100644 --- a/letsencrypt/acme/jose/jwk.py +++ b/letsencrypt/acme/jose/jwk.py @@ -126,9 +126,10 @@ class JWKRSA(JWK): @classmethod def fields_from_json(cls, jobj): - return cls(key=Crypto.PublicKey.RSA.construct( - (cls._decode_param(jobj['n']), - cls._decode_param(jobj['e'])))) + return cls(key=util.HashableRSAKey( + Crypto.PublicKey.RSA.construct( + (cls._decode_param(jobj['n']), + cls._decode_param(jobj['e']))))) def fields_to_json(self): return { diff --git a/letsencrypt/acme/jose/jwk_test.py b/letsencrypt/acme/jose/jwk_test.py index b75d3e1ce..7006f74a8 100644 --- a/letsencrypt/acme/jose/jwk_test.py +++ b/letsencrypt/acme/jose/jwk_test.py @@ -6,6 +6,7 @@ import unittest from Crypto.PublicKey import RSA from letsencrypt.acme.jose import errors +from letsencrypt.acme.jose import util RSA256_KEY = RSA.importKey(pkg_resources.resource_string( @@ -42,15 +43,15 @@ class JWKRSATest(unittest.TestCase): def setUp(self): from letsencrypt.acme.jose.jwk import JWKRSA - self.jwk256 = JWKRSA(key=RSA256_KEY.publickey()) - self.jwk256_private = JWKRSA(key=RSA256_KEY) + self.jwk256 = JWKRSA(key=util.HashableRSAKey(RSA256_KEY.publickey())) + self.jwk256_private = JWKRSA(key=util.HashableRSAKey(RSA256_KEY)) self.jwk256json = { 'kty': 'RSA', 'e': 'AQAB', 'n': 'rHVztFHtH92ucFJD_N_HW9AsdRsUuHUBBBDlHwNlRd3fp5' '80rv2-6QWE30cWgdmJS86ObRz6lUTor4R0T-3C5Q', } - self.jwk512 = JWKRSA(key=RSA512_KEY.publickey()) + self.jwk512 = JWKRSA(key=util.HashableRSAKey(RSA512_KEY.publickey())) self.jwk512json = { 'kty': 'RSA', 'e': 'AQAB', @@ -68,10 +69,11 @@ class JWKRSATest(unittest.TestCase): def test_load(self): from letsencrypt.acme.jose.jwk import JWKRSA - self.assertEqual(JWKRSA(key=RSA256_KEY), JWKRSA.load( - pkg_resources.resource_string( - 'letsencrypt.client.tests', - os.path.join('testdata', 'rsa256_key.pem')))) + self.assertEqual( + JWKRSA(key=util.HashableRSAKey(RSA256_KEY)), JWKRSA.load( + pkg_resources.resource_string( + 'letsencrypt.client.tests', + os.path.join('testdata', 'rsa256_key.pem')))) def test_public(self): self.assertEqual(self.jwk256, self.jwk256_private.public()) diff --git a/letsencrypt/acme/messages2.py b/letsencrypt/acme/messages2.py index b04291af3..2fefefd11 100644 --- a/letsencrypt/acme/messages2.py +++ b/letsencrypt/acme/messages2.py @@ -136,7 +136,8 @@ class Registration(ResourceBody): # on new-reg key server ignores 'key' and populates it based on # JWS.signature.combined.jwk - key = jose.Field('key', omitempty=True, decoder=jose.JWK.from_json) + key = jose.Field('key', omitempty=True, + decoder=jose.JWK.from_json, encoder=jose.JWK.to_json) contact = jose.Field('contact', omitempty=True, default=()) recovery_token = jose.Field('recoveryToken', omitempty=True) agreement = jose.Field('agreement', omitempty=True) diff --git a/letsencrypt/acme/messages2_test.py b/letsencrypt/acme/messages2_test.py index 614895b98..15447eacc 100644 --- a/letsencrypt/acme/messages2_test.py +++ b/letsencrypt/acme/messages2_test.py @@ -1,9 +1,12 @@ """Tests for letsencrypt.acme.messages2.""" import datetime +import os +import pkg_resources import unittest import mock import pytz +from Crypto.PublicKey import RSA from letsencrypt.acme import challenges from letsencrypt.acme import jose @@ -66,6 +69,48 @@ class ConstantTest(unittest.TestCase): self.assertEqual('MockConstant(b)', repr(self.const_b)) +class RegistrationTest(unittest.TestCase): + """Tests for letsencrypt.acme.messages2.Registration.""" + + def setUp(self): + from letsencrypt.acme.messages2 import Registration + + rsa_key = RSA.importKey(pkg_resources.resource_string( + 'letsencrypt.client.tests', os.path.join( + 'testdata', 'rsa256_key.pem'))) + + self.key = jose.jwk.JWKRSA(key=jose.util.HashableRSAKey( + rsa_key.publickey())) + + self.contact = ("mailto:letsencrypt-client@letsencrypt.org",) + self.recovery_token = "XYZ" + self.agreement = "https://letsencrypt.org/terms" + self.reg = Registration( + key=self.key, contact=self.contact, + recovery_token=self.recovery_token, agreement=self.agreement) + + self.json_key = { + 'kty': 'RSA', + 'e': 'AQAB', + 'n': 'rHVztFHtH92ucFJD_N_HW9AsdRsUuHUBBBDlHwNlRd3fp5' + '80rv2-6QWE30cWgdmJS86ObRz6lUTor4R0T-3C5Q', + } + + self.json_reg = { + "contact": self.contact, + "recoveryToken": self.recovery_token, + "agreement": self.agreement, + "key": self.json_key, + } + + def test_to_json(self): + self.assertEqual(self.reg.to_json(), self.json_reg) + + def test_from_json(self): + from letsencrypt.acme.messages2 import Registration + + self.assertEqual(Registration.from_json(self.json_reg), self.reg) + class ChallengeResourceTest(unittest.TestCase): """Tests for letsencrypt.acme.messages2.ChallengeResource."""