tcrypto: chacha20-methods: make associated_data param optional - electrum - Electrum Bitcoin wallet (HTM) git clone https://git.parazyd.org/electrum (DIR) Log (DIR) Files (DIR) Refs (DIR) Submodules --- (DIR) commit 725b6f15649c4f93dedfa2c241b6cbf7a82a65f0 (DIR) parent b9db16327a1feb9b345d6194859603b5b12a5eff (HTM) Author: SomberNight <somber.night@protonmail.com> Date: Wed, 17 Jun 2020 17:32:51 +0200 crypto: chacha20-methods: make associated_data param optional Diffstat: M electrum/crypto.py | 26 ++++++++++++++++++++------ M electrum/tests/test_bitcoin.py | 24 ++++++++++++++++++++++-- 2 files changed, 42 insertions(+), 8 deletions(-) --- (DIR) diff --git a/electrum/crypto.py b/electrum/crypto.py t@@ -268,14 +268,21 @@ def hmac_oneshot(key: bytes, msg: bytes, digest) -> bytes: return hmac.new(key, msg, digest).digest() -def chacha20_poly1305_encrypt(*, key: bytes, nonce: bytes, associated_data: bytes, data: bytes) -> bytes: +def chacha20_poly1305_encrypt( + *, + key: bytes, + nonce: bytes, + associated_data: bytes = None, + data: bytes +) -> bytes: assert isinstance(key, (bytes, bytearray)) assert isinstance(nonce, (bytes, bytearray)) - assert isinstance(associated_data, (bytes, bytearray)) + assert isinstance(associated_data, (bytes, bytearray, type(None))) assert isinstance(data, (bytes, bytearray)) if HAS_CRYPTODOME: cipher = CD_ChaCha20_Poly1305.new(key=key, nonce=nonce) - cipher.update(associated_data) + if associated_data is not None: + cipher.update(associated_data) ciphertext, mac = cipher.encrypt_and_digest(plaintext=data) return ciphertext + mac if HAS_CRYPTOGRAPHY: t@@ -284,14 +291,21 @@ def chacha20_poly1305_encrypt(*, key: bytes, nonce: bytes, associated_data: byte raise Exception("no chacha20 backend found") -def chacha20_poly1305_decrypt(*, key: bytes, nonce: bytes, associated_data: bytes, data: bytes) -> bytes: +def chacha20_poly1305_decrypt( + *, + key: bytes, + nonce: bytes, + associated_data: bytes = None, + data: bytes +) -> bytes: assert isinstance(key, (bytes, bytearray)) assert isinstance(nonce, (bytes, bytearray)) - assert isinstance(associated_data, (bytes, bytearray)) + assert isinstance(associated_data, (bytes, bytearray, type(None))) assert isinstance(data, (bytes, bytearray)) if HAS_CRYPTODOME: cipher = CD_ChaCha20_Poly1305.new(key=key, nonce=nonce) - cipher.update(associated_data) + if associated_data is not None: + cipher.update(associated_data) # raises ValueError if not valid (e.g. incorrect MAC) return cipher.decrypt_and_verify(ciphertext=data[:-16], received_mac_tag=data[-16:]) if HAS_CRYPTOGRAPHY: (DIR) diff --git a/electrum/tests/test_bitcoin.py b/electrum/tests/test_bitcoin.py t@@ -261,7 +261,7 @@ class Test_bitcoin(ElectrumTestCase): crypto.pw_decode(enc, wrong_password, version=1) @needs_test_with_all_chacha20_implementations - def test_chacha20_poly1305_encrypt(self): + def test_chacha20_poly1305_encrypt__with_associated_data(self): key = bytes.fromhex('37326d9d69a83b815ddfd947d21b0dd39111e5b6a5a44042c44d570ea03e3179') nonce = bytes.fromhex('010203040506070809101112') associated_data = bytes.fromhex('30c9572d4305d4f3ccb766b1db884da6f1e0086f55136a39740700c272095717') t@@ -270,7 +270,7 @@ class Test_bitcoin(ElectrumTestCase): crypto.chacha20_poly1305_encrypt(key=key, nonce=nonce, associated_data=associated_data, data=data)) @needs_test_with_all_chacha20_implementations - def test_chacha20_poly1305_decrypt(self): + def test_chacha20_poly1305_decrypt__with_associated_data(self): key = bytes.fromhex('37326d9d69a83b815ddfd947d21b0dd39111e5b6a5a44042c44d570ea03e3179') nonce = bytes.fromhex('010203040506070809101112') associated_data = bytes.fromhex('30c9572d4305d4f3ccb766b1db884da6f1e0086f55136a39740700c272095717') t@@ -281,6 +281,26 @@ class Test_bitcoin(ElectrumTestCase): crypto.chacha20_poly1305_decrypt(key=key, nonce=nonce, associated_data=b'', data=data) @needs_test_with_all_chacha20_implementations + def test_chacha20_poly1305_encrypt__without_associated_data(self): + key = bytes.fromhex('37326d9d69a83b815ddfd947d21b0dd39111e5b6a5a44042c44d570ea03e3179') + nonce = bytes.fromhex('010203040506070809101112') + data = bytes.fromhex('4a6cd75da76cedf0a8a47e3a5734a328') + self.assertEqual(bytes.fromhex('90fb51fcde1fbe4013500bd7a322804469c2be9b1385bc5ded5cd96be510280f'), + crypto.chacha20_poly1305_encrypt(key=key, nonce=nonce, data=data)) + self.assertEqual(bytes.fromhex('90fb51fcde1fbe4013500bd7a322804469c2be9b1385bc5ded5cd96be510280f'), + crypto.chacha20_poly1305_encrypt(key=key, nonce=nonce, data=data, associated_data=b'')) + + @needs_test_with_all_chacha20_implementations + def test_chacha20_poly1305_decrypt__without_associated_data(self): + key = bytes.fromhex('37326d9d69a83b815ddfd947d21b0dd39111e5b6a5a44042c44d570ea03e3179') + nonce = bytes.fromhex('010203040506070809101112') + data = bytes.fromhex('90fb51fcde1fbe4013500bd7a322804469c2be9b1385bc5ded5cd96be510280f') + self.assertEqual(bytes.fromhex('4a6cd75da76cedf0a8a47e3a5734a328'), + crypto.chacha20_poly1305_decrypt(key=key, nonce=nonce, data=data)) + self.assertEqual(bytes.fromhex('4a6cd75da76cedf0a8a47e3a5734a328'), + crypto.chacha20_poly1305_decrypt(key=key, nonce=nonce, data=data, associated_data=b'')) + + @needs_test_with_all_chacha20_implementations def test_chacha20_encrypt(self): key = bytes.fromhex('37326d9d69a83b815ddfd947d21b0dd39111e5b6a5a44042c44d570ea03e3179') nonce = bytes.fromhex('0102030405060708')