Merge ~cjwatson/launchpad:py3-signing-proxy into launchpad:master

Proposed by Colin Watson
Status: Merged
Approved by: Colin Watson
Approved revision: 4c6e2c957557b1680864e0ce79cff6a1e8e6c421
Merge reported by: Otto Co-Pilot
Merged at revision: not available
Proposed branch: ~cjwatson/launchpad:py3-signing-proxy
Merge into: launchpad:master
Diff against target: 151 lines (+25/-18)
3 files modified
lib/lp/services/signing/proxy.py (+11/-6)
lib/lp/services/signing/tests/test_proxy.py (+13/-11)
lib/lp/services/signing/tests/test_signingkey.py (+1/-1)
Reviewer Review Type Date Requested Status
Cristian Gonzalez (community) Approve
Review via email: mp+399081@code.launchpad.net

Commit message

lp.services.signing.proxy: Fix up bytes vs. text for Python 3

Description of the change

base64 operates on bytes while json generally operates on text, so a good deal of explicit encoding and decoding is needed.

To post a comment you must log in.
Revision history for this message
Cristian Gonzalez (cristiangsp) wrote :

Looks well encoded :)!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
diff --git a/lib/lp/services/signing/proxy.py b/lib/lp/services/signing/proxy.py
index 8d78e65..2cb5393 100644
--- a/lib/lp/services/signing/proxy.py
+++ b/lib/lp/services/signing/proxy.py
@@ -64,7 +64,8 @@ class SigningServiceClient:
64 def _decryptResponseJson(self, response, response_nonce):64 def _decryptResponseJson(self, response, response_nonce):
65 box = Box(self.private_key, self.service_public_key)65 box = Box(self.private_key, self.service_public_key)
66 return json.loads(box.decrypt(66 return json.loads(box.decrypt(
67 response.content, response_nonce, encoder=Base64Encoder))67 response.content, response_nonce,
68 encoder=Base64Encoder).decode("UTF-8"))
6869
69 def _requestJson(self, path, method="GET", encrypt=False, **kwargs):70 def _requestJson(self, path, method="GET", encrypt=False, **kwargs):
70 """Helper method to do an HTTP request and get back a json from the71 """Helper method to do an HTTP request and get back a json from the
@@ -138,8 +139,9 @@ class SigningServiceClient:
138 return {139 return {
139 "Content-Type": "application/x-boxed-json",140 "Content-Type": "application/x-boxed-json",
140 "X-Client-Public-Key": config.signing.client_public_key,141 "X-Client-Public-Key": config.signing.client_public_key,
141 "X-Nonce": base64.b64encode(nonce),142 "X-Nonce": base64.b64encode(nonce).decode("UTF-8"),
142 "X-Response-Nonce": base64.b64encode(response_nonce),143 "X-Response-Nonce": (
144 base64.b64encode(response_nonce).decode("UTF-8")),
143 }145 }
144146
145 def _encryptPayload(self, nonce, message):147 def _encryptPayload(self, nonce, message):
@@ -178,7 +180,8 @@ class SigningServiceClient:
178 "/generate", "POST", encrypt=True, json=payload)180 "/generate", "POST", encrypt=True, json=payload)
179 return {181 return {
180 "fingerprint": ret["fingerprint"],182 "fingerprint": ret["fingerprint"],
181 "public-key": base64.b64decode(ret["public-key"])}183 "public-key": base64.b64decode(ret["public-key"].encode("UTF-8")),
184 }
182185
183 def sign(self, key_type, fingerprint, message_name, message, mode):186 def sign(self, key_type, fingerprint, message_name, message, mode):
184 valid_modes = {SigningMode.ATTACHED, SigningMode.DETACHED}187 valid_modes = {SigningMode.ATTACHED, SigningMode.DETACHED}
@@ -199,8 +202,10 @@ class SigningServiceClient:
199202
200 ret = self._requestJson("/sign", "POST", encrypt=True, json=payload)203 ret = self._requestJson("/sign", "POST", encrypt=True, json=payload)
201 return {204 return {
202 "public-key": base64.b64decode(ret["public-key"]),205 "public-key": base64.b64decode(ret["public-key"].encode("UTF-8")),
203 "signed-message": base64.b64decode(ret["signed-message"])}206 "signed-message": base64.b64decode(
207 ret["signed-message"].encode("UTF-8")),
208 }
204209
205 def inject(self, key_type, private_key, public_key, description,210 def inject(self, key_type, private_key, public_key, description,
206 created_at):211 created_at):
diff --git a/lib/lp/services/signing/tests/test_proxy.py b/lib/lp/services/signing/tests/test_proxy.py
index 4405fe7..5f7fe7e 100644
--- a/lib/lp/services/signing/tests/test_proxy.py
+++ b/lib/lp/services/signing/tests/test_proxy.py
@@ -69,11 +69,11 @@ class SigningServiceResponseFactory:
6969
70 self.generated_public_key = PrivateKey.generate().public_key70 self.generated_public_key = PrivateKey.generate().public_key
71 self.b64_generated_public_key = base64.b64encode(71 self.b64_generated_public_key = base64.b64encode(
72 bytes(self.generated_public_key))72 bytes(self.generated_public_key)).decode("UTF-8")
73 self.generated_fingerprint = (73 self.generated_fingerprint = (
74 u'338D218488DFD597D8FCB9C328C3E9D9ADA16CEE')74 u'338D218488DFD597D8FCB9C328C3E9D9ADA16CEE')
7575
76 self.signed_msg_template = "%s::signed!"76 self.signed_msg_template = b"%d::signed!"
7777
78 @classmethod78 @classmethod
79 def getUrl(cls, path):79 def getUrl(cls, path):
@@ -86,7 +86,8 @@ class SigningServiceResponseFactory:
86 lp-signing would do."""86 lp-signing would do."""
87 box = Box(self.service_private_key, self.client_public_key)87 box = Box(self.service_private_key, self.client_public_key)
88 return box.encrypt(88 return box.encrypt(
89 json.dumps(data), nonce, encoder=Base64Encoder).ciphertext89 json.dumps(data).encode("UTF-8"), nonce,
90 encoder=Base64Encoder).ciphertext
9091
91 def _decryptPayload(self, value):92 def _decryptPayload(self, value):
92 """Decrypt a payload we encrypted.93 """Decrypt a payload we encrypted.
@@ -137,18 +138,18 @@ class SigningServiceResponseFactory:
137138
138 responses.add(139 responses.add(
139 responses.GET, self.getUrl("/service-key"),140 responses.GET, self.getUrl("/service-key"),
140 json={"service-key": self.b64_service_public_key.decode('utf8')},141 json={"service-key": self.b64_service_public_key},
141 status=200)142 status=200)
142143
143 responses.add(144 responses.add(
144 responses.POST, self.getUrl("/nonce"),145 responses.POST, self.getUrl("/nonce"),
145 json={"nonce": self.b64_nonce.decode('utf8')}, status=201)146 json={"nonce": self.b64_nonce}, status=201)
146147
147 responses.add(148 responses.add(
148 responses.POST, self.getUrl("/generate"),149 responses.POST, self.getUrl("/generate"),
149 body=self._encryptPayload({150 body=self._encryptPayload({
150 'fingerprint': self.generated_fingerprint,151 'fingerprint': self.generated_fingerprint,
151 'public-key': self.b64_generated_public_key.decode('utf8')152 'public-key': self.b64_generated_public_key,
152 }, nonce=self.response_nonce),153 }, nonce=self.response_nonce),
153 status=201)154 status=201)
154155
@@ -169,9 +170,9 @@ class SigningServiceResponseFactory:
169 def sign_callback(request):170 def sign_callback(request):
170 call_counts['/sign'] += 1171 call_counts['/sign'] += 1
171 signed_msg = self.signed_msg_template % call_counts['/sign']172 signed_msg = self.signed_msg_template % call_counts['/sign']
172 signed = base64.b64encode(signed_msg.encode('utf8'))173 signed = base64.b64encode(signed_msg)
173 data = {'signed-message': signed.decode('utf8'),174 data = {'signed-message': signed.decode('utf8'),
174 'public-key': self.b64_generated_public_key.decode('utf8')}175 'public-key': self.b64_generated_public_key}
175 return 201, {}, self._encryptPayload(data, self.response_nonce)176 return 201, {}, self._encryptPayload(data, self.response_nonce)
176177
177 responses.add_callback(178 responses.add_callback(
@@ -222,7 +223,7 @@ class SigningServiceProxyTest(TestCaseWithFactory, TestWithFixtures):
222 self.assertIsInstance(key, PublicKey)223 self.assertIsInstance(key, PublicKey)
223 self.assertEqual(224 self.assertEqual(
224 key.encode(Base64Encoder),225 key.encode(Base64Encoder),
225 self.response_factory.b64_service_public_key)226 self.response_factory.b64_service_public_key.encode("UTF-8"))
226227
227 # Checks that the HTTP call was made228 # Checks that the HTTP call was made
228 self.assertEqual(1, len(responses.calls))229 self.assertEqual(1, len(responses.calls))
@@ -241,7 +242,8 @@ class SigningServiceProxyTest(TestCaseWithFactory, TestWithFixtures):
241 nonce = signing.getNonce()242 nonce = signing.getNonce()
242243
243 self.assertEqual(244 self.assertEqual(
244 base64.b64encode(nonce), self.response_factory.b64_nonce)245 base64.b64encode(nonce),
246 self.response_factory.b64_nonce.encode("UTF-8"))
245247
246 # Checks that the HTTP call was made248 # Checks that the HTTP call was made
247 self.assertEqual(1, len(responses.calls))249 self.assertEqual(1, len(responses.calls))
@@ -422,7 +424,7 @@ class SigningServiceProxyTest(TestCaseWithFactory, TestWithFixtures):
422 key_type = SigningKeyType.KMOD424 key_type = SigningKeyType.KMOD
423 mode = SigningMode.DETACHED425 mode = SigningMode.DETACHED
424 message_name = 'my test msg'426 message_name = 'my test msg'
425 message = 'this is the message content'427 message = b'this is the message content'
426428
427 signing = getUtility(ISigningServiceClient)429 signing = getUtility(ISigningServiceClient)
428 data = signing.sign(430 data = signing.sign(
diff --git a/lib/lp/services/signing/tests/test_signingkey.py b/lib/lp/services/signing/tests/test_signingkey.py
index 00714f9..03e0a74 100644
--- a/lib/lp/services/signing/tests/test_signingkey.py
+++ b/lib/lp/services/signing/tests/test_signingkey.py
@@ -88,7 +88,7 @@ class TestSigningKey(TestCaseWithFactory, TestWithFixtures):
88 self.assertEqual(88 self.assertEqual(
89 self.signing_service.generated_fingerprint, db_key.fingerprint)89 self.signing_service.generated_fingerprint, db_key.fingerprint)
90 self.assertEqual(90 self.assertEqual(
91 self.signing_service.b64_generated_public_key,91 self.signing_service.b64_generated_public_key.encode("UTF-8"),
92 base64.b64encode(db_key.public_key))92 base64.b64encode(db_key.public_key))
93 self.assertEqual("this is my key", db_key.description)93 self.assertEqual("this is my key", db_key.description)
9494

Subscribers

People subscribed via source and target branches

to status/vote changes: