diff --git a/boards/models/post/manager.py b/boards/models/post/manager.py --- a/boards/models/post/manager.py +++ b/boards/models/post/manager.py @@ -75,7 +75,7 @@ class PostManager(models.Manager): return post @transaction.atomic - def import_post(self, title: str, text: str, pub_time: str, + def import_post(self, title: str, text: str, pub_time: str, global_id, opening_post=None, tags=list()): if opening_post is None: thread = boards.models.thread.Thread.objects.create( @@ -88,7 +88,7 @@ class PostManager(models.Manager): pub_time=pub_time, poster_ip=NO_IP, last_edit_time=pub_time, - thread_id=thread.id) + thread_id=thread.id, global_id=global_id) post.build_url() post.connect_replies() diff --git a/boards/models/post/sync.py b/boards/models/post/sync.py --- a/boards/models/post/sync.py +++ b/boards/models/post/sync.py @@ -107,10 +107,7 @@ class SyncManager: for tag_model in tag_models: tag_content = tag_model.find(TAG_CONTENT) - valid = SyncManager._verify_model(tag_content, tag_model) - - if not valid: - raise Exception('Invalid model signature') + signatures = SyncManager._verify_model(tag_content, tag_model) tag_id = tag_content.find(TAG_ID) global_id, exists = GlobalId.from_xml_element(tag_id) @@ -119,6 +116,9 @@ class SyncManager: print('Post with same ID already exists') else: global_id.save() + for signature in signatures: + signature.global_id = global_id + signature.save() title = tag_content.find(TAG_TITLE).text text = tag_content.find(TAG_TEXT).text @@ -143,8 +143,8 @@ class SyncManager: post = Post.objects.import_post( title=title, text=text, pub_time=pub_time, - opening_post=opening_post, tags=tags) - post.global_id = global_id + opening_post=opening_post, tags=tags, + global_id=global_id) else: # TODO Throw an exception? pass @@ -155,7 +155,7 @@ class SyncManager: Verifies all signatures for a single model. """ - valid = True + signatures = [] tag_signatures = tag_model.find(TAG_SIGNATURES) for tag_signature in tag_signatures: @@ -163,11 +163,13 @@ class SyncManager: signature_value = tag_signature.get(ATTR_VALUE) signature_key = tag_signature.get(ATTR_KEY) + signature = Signature(key_type=signature_type, + key=signature_key, + signature=signature_value) + signatures.append(signature) + if not KeyPair.objects.verify( - signature_key, - et.tostring(tag_content, ENCODING_UNICODE), - signature_value, signature_type): - valid = False - break + signature, et.tostring(tag_content, ENCODING_UNICODE)): + raise Exception('Invalid model signature') - return valid + return signatures diff --git a/boards/models/sync_key.py b/boards/models/sync_key.py --- a/boards/models/sync_key.py +++ b/boards/models/sync_key.py @@ -25,10 +25,10 @@ class KeyPairManager(models.Manager): else: raise Exception('Key type not supported') - def verify(self, public_key_str, string, signature, key_type=TYPE_ECDSA): - if key_type == TYPE_ECDSA: - public = VerifyingKey.from_string(base64.b64decode(public_key_str)) - signature_byte = base64.b64decode(signature) + def verify(self, signature, string): + if signature.key_type == TYPE_ECDSA: + public = VerifyingKey.from_string(base64.b64decode(signature.key)) + signature_byte = base64.b64decode(signature.signature) try: return public.verify(signature_byte, string.encode()) except BadSignatureError: diff --git a/boards/tests/test_keys.py b/boards/tests/test_keys.py --- a/boards/tests/test_keys.py +++ b/boards/tests/test_keys.py @@ -2,7 +2,7 @@ from base64 import b64encode import logging from django.test import TestCase -from boards.models import KeyPair, GlobalId, Post +from boards.models import KeyPair, GlobalId, Post, Signature from boards.models.post.sync import SyncManager logger = logging.getLogger(__name__) @@ -17,9 +17,11 @@ class KeyTest(TestCase): def test_validation(self): key = KeyPair.objects.generate_key(key_type='ecdsa') message = 'msg' - signature = key.sign(message) - valid = KeyPair.objects.verify(key.public_key, message, signature, - key_type='ecdsa') + signature_value = key.sign(message) + + signature = Signature(key_type='ecdsa', key=key.public_key, + signature=signature_value) + valid = KeyPair.objects.verify(signature, message) self.assertTrue(valid, 'Message verification failed.') diff --git a/boards/tests/test_sync.py b/boards/tests/test_sync.py --- a/boards/tests/test_sync.py +++ b/boards/tests/test_sync.py @@ -67,3 +67,6 @@ class SyncTest(TestCase): SyncManager.parse_response_get(response) self.assertEqual(1, Post.objects.count(), 'The same post was imported twice.') + + self.assertEqual(1, parsed_post.global_id.signature_set.count(), + 'Signature was not saved.')