diff --git a/tests/__init__.py b/tests/__init__.py index e69de29..190a8d5 100644 --- a/tests/__init__.py +++ b/tests/__init__.py @@ -0,0 +1,17 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-2019 Dan +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . diff --git a/tests/cbc/__init__.py b/tests/cbc/__init__.py index e69de29..190a8d5 100644 --- a/tests/cbc/__init__.py +++ b/tests/cbc/__init__.py @@ -0,0 +1,17 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-2019 Dan +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . diff --git a/tests/cbc/test_cbc.py b/tests/cbc/test_cbc.py index a4dc9ac..de16c33 100644 --- a/tests/cbc/test_cbc.py +++ b/tests/cbc/test_cbc.py @@ -1,4 +1,23 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-2019 Dan +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + import os +import random import re import unittest from pathlib import Path @@ -110,5 +129,92 @@ class TestCBC256Cryptography(unittest.TestCase): ) +class TestCBC256Input(unittest.TestCase): + def test_cbc256_encrypt_invalid_args_count(self): + with self.assertRaisesRegex(TypeError, r"function takes exactly \d arguments \(\d given\)"): + tgcrypto.cbc256_encrypt(os.urandom(16), os.urandom(32)) + + def test_cbc256_encrypt_invalid_args_type(self): + with self.assertRaisesRegex(TypeError, r"a bytes-like object is required, not '\w+'"): + tgcrypto.cbc256_encrypt(1, 2, 3) + + def test_cbc256_encrypt_empty_data(self): + with self.assertRaisesRegex(ValueError, r"Data must not be empty"): + tgcrypto.cbc256_encrypt(b"", os.urandom(32), os.urandom(16)) + + def test_cbc256_encrypt_invalid_key_size(self): + with self.assertRaisesRegex(ValueError, r"Key size must be exactly 32 bytes"): + tgcrypto.cbc256_encrypt(os.urandom(16), os.urandom(31), os.urandom(16)) + + def test_cbc256_encrypt_invalid_iv_size(self): + with self.assertRaisesRegex(ValueError, r"IV size must be exactly 16 bytes"): + tgcrypto.cbc256_encrypt(os.urandom(16), os.urandom(32), os.urandom(15)) + + def test_cbc256_decrypt_invalid_args_count(self): + with self.assertRaisesRegex(TypeError, r"function takes exactly \d arguments \(\d given\)"): + tgcrypto.cbc256_decrypt(os.urandom(16), os.urandom(32)) + + def test_cbc256_decrypt_invalid_args_type(self): + with self.assertRaisesRegex(TypeError, r"a bytes-like object is required, not '\w+'"): + tgcrypto.cbc256_decrypt(1, 2, 3) + + def test_cbc256_decrypt_empty_data(self): + with self.assertRaisesRegex(ValueError, r"Data must not be empty"): + tgcrypto.cbc256_decrypt(b"", os.urandom(32), os.urandom(16)) + + def test_cbc256_decrypt_invalid_key_size(self): + with self.assertRaisesRegex(ValueError, r"Key size must be exactly 32 bytes"): + tgcrypto.cbc256_decrypt(os.urandom(16), os.urandom(31), os.urandom(16)) + + def test_cbc256_decrypt_invalid_iv_size(self): + with self.assertRaisesRegex(ValueError, r"IV size must be exactly 16 bytes"): + tgcrypto.cbc256_decrypt(os.urandom(16), os.urandom(32), os.urandom(15)) + + +class TestCBC256Random(unittest.TestCase): + DATA_CHUNK_MAX_SIZE = 64 + KEY_SIZE = 32 + IV_SIZE = 16 + + TESTS_AMOUNT = 500 + + TEMPLATE = """ + def test_cbc256_random_{mode1}_{count}(self): + data = {data} + key = {key} + iv = {iv} + iv_copy = iv.copy() + + a = tgcrypto.cbc256_{mode1}(data, key, iv) + b = tgcrypto.cbc256_{mode2}(a, key, iv_copy) + + self.assertEqual(data, b) + """.replace("\n ", "\n") + + for count in range(TESTS_AMOUNT): + exec( + TEMPLATE.format( + mode1="encrypt", + mode2="decrypt", + count=count, + data=os.urandom(random.randint(1, DATA_CHUNK_MAX_SIZE) * 16), + key=os.urandom(KEY_SIZE), + iv=bytearray(os.urandom(IV_SIZE)), + ) + ) + + for count in range(TESTS_AMOUNT): + exec( + TEMPLATE.format( + mode1="decrypt", + mode2="encrypt", + count=count, + data=os.urandom(random.randint(1, DATA_CHUNK_MAX_SIZE) * 16), + key=os.urandom(KEY_SIZE), + iv=bytearray(os.urandom(IV_SIZE)), + ) + ) + + if __name__ == "__main__": unittest.main() diff --git a/tests/ctr/__init__.py b/tests/ctr/__init__.py index e69de29..190a8d5 100644 --- a/tests/ctr/__init__.py +++ b/tests/ctr/__init__.py @@ -0,0 +1,17 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-2019 Dan +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . diff --git a/tests/ctr/test_ctr.py b/tests/ctr/test_ctr.py index abf0bac..9fda80e 100644 --- a/tests/ctr/test_ctr.py +++ b/tests/ctr/test_ctr.py @@ -1,9 +1,29 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-2019 Dan +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +import os +import random import unittest import tgcrypto -class TestCTR256(unittest.TestCase): +class TestCTR256NIST(unittest.TestCase): # https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/AES_CTR.pdf def test_ctr256_encrypt(self): @@ -58,6 +78,8 @@ class TestCTR256(unittest.TestCase): self.assertEqual(tgcrypto.ctr256_decrypt(ciphertext, key, iv, bytes(1)), plaintext) + +class TestCTR256Cryptography(unittest.TestCase): # https://github.com/pyca/cryptography/blob/cd4de3ce6dc2a0dd4171b869e187857e4125853b/vectors/cryptography_vectors/ciphers/AES/CTR/aes-256-ctr.txt def test_ctr256_encrypt_extra1(self): @@ -85,5 +107,112 @@ class TestCTR256(unittest.TestCase): self.assertEqual(tgcrypto.ctr256_encrypt(plaintext, key, iv, bytes(1)), ciphertext) +class TestCTR256Input(unittest.TestCase): + def test_ctr256_encrypt_invalid_args_count(self): + with self.assertRaisesRegex(TypeError, r"function takes exactly \d arguments \(\d given\)"): + tgcrypto.ctr256_encrypt(os.urandom(8), os.urandom(32), os.urandom(16)) + + def test_ctr256_encrypt_invalid_args_type(self): + with self.assertRaisesRegex(TypeError, r"a bytes-like object is required, not '\w+'"): + tgcrypto.ctr256_encrypt(1, 2, 3, 4) + + def test_ctr256_encrypt_empty_data(self): + with self.assertRaisesRegex(ValueError, r"Data must not be empty"): + tgcrypto.ctr256_encrypt(b"", os.urandom(32), os.urandom(16), bytes(1)) + + def test_ctr256_encrypt_invalid_key_size(self): + with self.assertRaisesRegex(ValueError, r"Key size must be exactly 32 bytes"): + tgcrypto.ctr256_encrypt(os.urandom(8), os.urandom(31), os.urandom(16), bytes(1)) + + def test_ctr256_encrypt_invalid_iv_size(self): + with self.assertRaisesRegex(ValueError, r"IV size must be exactly 16 bytes"): + tgcrypto.ctr256_encrypt(os.urandom(8), os.urandom(32), os.urandom(15), bytes(1)) + + def test_ctr256_encrypt_invalid_state_size(self): + with self.assertRaisesRegex(ValueError, r"State size must be exactly 1 byte"): + tgcrypto.ctr256_encrypt(os.urandom(8), os.urandom(32), os.urandom(16), bytes([1, 2, 3])) + + def test_ctr256_encrypt_invalid_state_value(self): + with self.assertRaisesRegex(ValueError, r"State value must be in the range \[0, 15\]"): + tgcrypto.ctr256_encrypt(os.urandom(8), os.urandom(32), os.urandom(16), bytes([16])) + + def test_ctr256_decrypt_invalid_args_count(self): + with self.assertRaisesRegex(TypeError, r"function takes exactly \d arguments \(\d given\)"): + tgcrypto.ctr256_decrypt(os.urandom(8), os.urandom(32), os.urandom(16)) + + def test_ctr256_decrypt_invalid_args_type(self): + with self.assertRaisesRegex(TypeError, r"a bytes-like object is required, not '\w+'"): + tgcrypto.ctr256_decrypt(1, 2, 3, 4) + + def test_ctr256_decrypt_empty_data(self): + with self.assertRaisesRegex(ValueError, r"Data must not be empty"): + tgcrypto.ctr256_decrypt(b"", os.urandom(32), os.urandom(16), bytes(1)) + + def test_ctr256_decrypt_invalid_key_size(self): + with self.assertRaisesRegex(ValueError, r"Key size must be exactly 32 bytes"): + tgcrypto.ctr256_decrypt(os.urandom(8), os.urandom(31), os.urandom(16), bytes(1)) + + def test_ctr256_decrypt_invalid_iv_size(self): + with self.assertRaisesRegex(ValueError, r"IV size must be exactly 16 bytes"): + tgcrypto.ctr256_decrypt(os.urandom(8), os.urandom(32), os.urandom(15), bytes(1)) + + def test_ctr256_decrypt_invalid_state_size(self): + with self.assertRaisesRegex(ValueError, r"State size must be exactly 1 byte"): + tgcrypto.ctr256_decrypt(os.urandom(8), os.urandom(32), os.urandom(16), bytes([1, 2, 3])) + + def test_ctr256_decrypt_invalid_state_value(self): + with self.assertRaisesRegex(ValueError, r"State value must be in the range \[0, 15\]"): + tgcrypto.ctr256_decrypt(os.urandom(8), os.urandom(32), os.urandom(16), bytes([16])) + + +class TestCTR256Random(unittest.TestCase): + DATA_MAX_SIZE = 1024 + KEY_SIZE = 32 + IV_SIZE = 16 + + TESTS_AMOUNT = 500 + + TEMPLATE = """ + def test_ctr256_random_{mode1}_{count}(self): + data = {data} + key = {key} + iv = {iv} + iv_copy = iv.copy() + state = {state} + state_copy = state.copy() + + a = tgcrypto.ctr256_{mode1}(data, key, iv, state) + b = tgcrypto.ctr256_{mode2}(a, key, iv_copy, state_copy) + + self.assertEqual(data, b) + """.replace("\n ", "\n") + + for count in range(TESTS_AMOUNT): + exec( + TEMPLATE.format( + mode1="encrypt", + mode2="decrypt", + count=count, + data=os.urandom(random.randint(1, DATA_MAX_SIZE)), + key=os.urandom(KEY_SIZE), + iv=bytearray(os.urandom(IV_SIZE)), + state=bytearray([random.randint(0, 15)]) + ) + ) + + for count in range(TESTS_AMOUNT): + exec( + TEMPLATE.format( + mode1="decrypt", + mode2="encrypt", + count=count, + data=os.urandom(random.randint(1, DATA_MAX_SIZE)), + key=os.urandom(KEY_SIZE), + iv=bytearray(os.urandom(IV_SIZE)), + state=bytearray([random.randint(0, 15)]) + ) + ) + + if __name__ == "__main__": unittest.main() diff --git a/tests/ige/__init__.py b/tests/ige/__init__.py new file mode 100644 index 0000000..190a8d5 --- /dev/null +++ b/tests/ige/__init__.py @@ -0,0 +1,17 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-2019 Dan +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . diff --git a/tests/ige/test_ige.py b/tests/ige/test_ige.py new file mode 100644 index 0000000..bce6fad --- /dev/null +++ b/tests/ige/test_ige.py @@ -0,0 +1,113 @@ +# Pyrogram - Telegram MTProto API Client Library for Python +# Copyright (C) 2017-2019 Dan +# +# This file is part of Pyrogram. +# +# Pyrogram is free software: you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Pyrogram is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with Pyrogram. If not, see . + +import os +import random +import unittest + +import tgcrypto + + +class TestIGE256Input(unittest.TestCase): + def test_ige256_encrypt_invalid_args_count(self): + with self.assertRaisesRegex(TypeError, r"function takes exactly \d arguments \(\d given\)"): + tgcrypto.ige256_encrypt(os.urandom(16), os.urandom(32)) + + def test_ige256_encrypt_invalid_args_type(self): + with self.assertRaisesRegex(TypeError, r"a bytes-like object is required, not '\w+'"): + tgcrypto.ige256_encrypt(1, 2, 3) + + def test_ige256_encrypt_empty_data(self): + with self.assertRaisesRegex(ValueError, r"Data must not be empty"): + tgcrypto.ige256_encrypt(b"", os.urandom(32), os.urandom(32)) + + def test_ige256_encrypt_invalid_key_size(self): + with self.assertRaisesRegex(ValueError, r"Key size must be exactly 32 bytes"): + tgcrypto.ige256_encrypt(os.urandom(16), os.urandom(31), os.urandom(32)) + + def test_ige256_encrypt_invalid_iv_size(self): + with self.assertRaisesRegex(ValueError, r"IV size must be exactly 32 bytes"): + tgcrypto.ige256_encrypt(os.urandom(16), os.urandom(32), os.urandom(31)) + + def test_ige256_decrypt_invalid_args_count(self): + with self.assertRaisesRegex(TypeError, r"function takes exactly \d arguments \(\d given\)"): + tgcrypto.ige256_decrypt(os.urandom(16), os.urandom(32)) + + def test_ige256_decrypt_invalid_args_type(self): + with self.assertRaisesRegex(TypeError, r"a bytes-like object is required, not '\w+'"): + tgcrypto.ige256_decrypt(1, 2, 3) + + def test_ige256_decrypt_empty_data(self): + with self.assertRaisesRegex(ValueError, r"Data must not be empty"): + tgcrypto.ige256_decrypt(b"", os.urandom(32), os.urandom(32)) + + def test_ige256_decrypt_invalid_key_size(self): + with self.assertRaisesRegex(ValueError, r"Key size must be exactly 32 bytes"): + tgcrypto.ige256_decrypt(os.urandom(16), os.urandom(31), os.urandom(32)) + + def test_ige256_decrypt_invalid_iv_size(self): + with self.assertRaisesRegex(ValueError, r"IV size must be exactly 32 bytes"): + tgcrypto.ige256_decrypt(os.urandom(16), os.urandom(32), os.urandom(31)) + + +class TestIGE256Random(unittest.TestCase): + DATA_CHUNK_MAX_SIZE = 64 + KEY_SIZE = 32 + IV_SIZE = 32 + + TESTS_AMOUNT = 500 + + TEMPLATE = """ + def test_ige256_random_{mode1}_{count}(self): + data = {data} + key = {key} + iv = {iv} + + a = tgcrypto.ige256_{mode1}(data, key, iv) + b = tgcrypto.ige256_{mode2}(a, key, iv) + + self.assertEqual(data, b) + """.replace("\n ", "\n") + + for count in range(TESTS_AMOUNT): + exec( + TEMPLATE.format( + mode1="encrypt", + mode2="decrypt", + count=count, + data=os.urandom(random.randint(1, DATA_CHUNK_MAX_SIZE) * 16), + key=os.urandom(KEY_SIZE), + iv=os.urandom(IV_SIZE), + ) + ) + + for count in range(TESTS_AMOUNT): + exec( + TEMPLATE.format( + mode1="decrypt", + mode2="encrypt", + count=count, + data=os.urandom(random.randint(1, DATA_CHUNK_MAX_SIZE) * 16), + key=os.urandom(KEY_SIZE), + iv=os.urandom(IV_SIZE), + ) + ) + + +if __name__ == "__main__": + unittest.main()