From ce199a24dc36123b3e2a9d38509114f37810a5ec Mon Sep 17 00:00:00 2001 From: Lee Miller Date: Tue, 28 Jun 2022 01:37:39 +0300 Subject: [PATCH] Added more tests for pyelliptic.ECC including parts of the encryption process, described in the Specification with samples. Appended TestECC to builtin tests. --- src/pyelliptic/tests/__init__.py | 3 +- src/pyelliptic/tests/samples.py | 74 ++++++++++++++++++++++++++++++++ src/pyelliptic/tests/test_ecc.py | 69 +++++++++++++++++++++++++++-- 3 files changed, 142 insertions(+), 4 deletions(-) create mode 100644 src/pyelliptic/tests/samples.py diff --git a/src/pyelliptic/tests/__init__.py b/src/pyelliptic/tests/__init__.py index 62bffa9a..b53ef881 100644 --- a/src/pyelliptic/tests/__init__.py +++ b/src/pyelliptic/tests/__init__.py @@ -3,6 +3,7 @@ import sys if getattr(sys, 'frozen', None): from test_arithmetic import TestArithmetic from test_blindsig import TestBlindSig + from test_ecc import TestECC from test_openssl import TestOpenSSL - __all__ = ["TestArithmetic", "TestBlindSig", "TestOpenSSL"] + __all__ = ["TestArithmetic", "TestBlindSig", "TestECC", "TestOpenSSL"] diff --git a/src/pyelliptic/tests/samples.py b/src/pyelliptic/tests/samples.py new file mode 100644 index 00000000..d6d71c02 --- /dev/null +++ b/src/pyelliptic/tests/samples.py @@ -0,0 +1,74 @@ +"""Testing samples""" + +from binascii import unhexlify + +# pubkey K +sample_pubkey = unhexlify( + '0409d4e5c0ab3d25fe' + '048c64c9da1a242c' + '7f19417e9517cd26' + '6950d72c75571358' + '5c6178e97fe092fc' + '897c9a1f1720d577' + '0ae8eaad2fa8fcbd' + '08e9324a5dde1857' +) + +sample_iv = unhexlify( + 'bddb7c2829b08038' + '753084a2f3991681' +) + +# Private key r +sample_ephem_privkey = unhexlify( + '5be6facd941b76e9' + 'd3ead03029fbdb6b' + '6e0809293f7fb197' + 'd0c51f84e96b8ba4' +) +# Public key R +sample_ephem_pubkey = unhexlify( + '040293213dcf1388b6' + '1c2ae5cf80fee6ff' + 'ffc049a2f9fe7365' + 'fe3867813ca81292' + 'df94686c6afb565a' + 'c6149b153d61b3b2' + '87ee2c7f997c1423' + '8796c12b43a3865a' +) + +# First 32 bytes of H called key_e +sample_enkey = unhexlify( + '1705438282678671' + '05263d4828efff82' + 'd9d59cbf08743b69' + '6bcc5d69fa1897b4' +) + +# Last 32 bytes of H called key_m +sample_mackey = unhexlify( + 'f83f1e9cc5d6b844' + '8d39dc6a9d5f5b7f' + '460e4a78e9286ee8' + 'd91ce1660a53eacd' +) + +# No padding of input! +sample_data = b'The quick brown fox jumps over the lazy dog.' + +sample_ciphertext = unhexlify( + '64203d5b24688e25' + '47bba345fa139a5a' + '1d962220d4d48a0c' + 'f3b1572c0d95b616' + '43a6f9a0d75af7ea' + 'cc1bd957147bf723' +) + +sample_mac = unhexlify( + 'f2526d61b4851fb2' + '3409863826fd2061' + '65edc021368c7946' + '571cead69046e619' +) diff --git a/src/pyelliptic/tests/test_ecc.py b/src/pyelliptic/tests/test_ecc.py index 4a6a5aef..02217100 100644 --- a/src/pyelliptic/tests/test_ecc.py +++ b/src/pyelliptic/tests/test_ecc.py @@ -1,11 +1,23 @@ """Tests for ECC object""" import unittest +from hashlib import sha512 try: - from pyelliptic.ecc import ECC + import pyelliptic except ImportError: - from pybitmessage.pyelliptic import ECC + from pybitmessage import pyelliptic + +from .samples import ( + sample_pubkey, sample_iv, sample_ephem_privkey, sample_ephem_pubkey, + sample_enkey, sample_mackey, sample_data, sample_ciphertext, sample_mac) + + +sample_pubkey_x = sample_ephem_pubkey[1:-32] +sample_pubkey_y = sample_ephem_pubkey[-32:] +sample_pubkey_bin = ( + b'\x02\xca\x00\x20' + sample_pubkey_x + b'\x00\x20' + sample_pubkey_y) +sample_privkey_bin = b'\x02\xca\x00\x20' + sample_ephem_privkey class TestECC(unittest.TestCase): @@ -13,7 +25,58 @@ class TestECC(unittest.TestCase): def test_random_keys(self): """A dummy test for random keys in ECC object""" - eccobj = ECC(curve='secp256k1') + eccobj = pyelliptic.ECC(curve='secp256k1') self.assertEqual(len(eccobj.privkey), 32) pubkey = eccobj.get_pubkey() self.assertEqual(pubkey[:4], b'\x02\xca\x00\x20') + + def test_decode_keys(self): + """Check keys decoding""" + curve_secp256k1 = pyelliptic.OpenSSL.get_curve('secp256k1') + curve, raw_privkey, _ = pyelliptic.ECC._decode_privkey( + sample_privkey_bin) + self.assertEqual(curve, curve_secp256k1) + self.assertEqual( + pyelliptic.OpenSSL.get_curve_by_id(curve), 'secp256k1') + self.assertEqual(sample_ephem_privkey, raw_privkey) + + curve, pubkey_x, pubkey_y, _ = pyelliptic.ECC._decode_pubkey( + sample_pubkey_bin) + self.assertEqual(curve, curve_secp256k1) + self.assertEqual(sample_pubkey_x, pubkey_x) + self.assertEqual(sample_pubkey_y, pubkey_y) + + def test_encode_keys(self): + """Check keys encoding""" + cryptor = pyelliptic.ECC( + pubkey_x=sample_pubkey_x, + pubkey_y=sample_pubkey_y, + raw_privkey=sample_ephem_privkey, curve='secp256k1') + self.assertEqual(cryptor.get_privkey(), sample_privkey_bin) + self.assertEqual(cryptor.get_pubkey(), sample_pubkey_bin) + + def test_encryption_parts(self): + """Check results of the encryption steps against samples in the Spec""" + ephem = pyelliptic.ECC( + pubkey_x=sample_pubkey_x, + pubkey_y=sample_pubkey_y, + raw_privkey=sample_ephem_privkey, curve='secp256k1') + key = sha512(ephem.raw_get_ecdh_key( + sample_pubkey[1:-32], sample_pubkey[-32:])).digest() + self.assertEqual(sample_enkey, key[:32]) + self.assertEqual(sample_mackey, key[32:]) + + ctx = pyelliptic.Cipher(sample_enkey, sample_iv, 1) + self.assertEqual(ctx.ciphering(sample_data), sample_ciphertext) + self.assertEqual( + sample_mac, + pyelliptic.hash.hmac_sha256( + sample_mackey, + sample_iv + sample_pubkey_bin + sample_ciphertext)) + + def test_decryption(self): + """Check decription of a message by random cryptor""" + random_recipient = pyelliptic.ECC(curve='secp256k1') + payload = pyelliptic.ECC.encrypt( + sample_data, random_recipient.get_pubkey()) + self.assertEqual(random_recipient.decrypt(payload), sample_data)