-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor: open for different encryption methods
- Loading branch information
Showing
5 changed files
with
104 additions
and
54 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,16 +1,16 @@ | ||
import json | ||
|
||
|
||
def encrypt_data(in_data, in_encrypt): | ||
def encrypt_data(in_data, in_encryptor): | ||
if list(in_data.keys()) == ["str"]: | ||
return {"str": in_data["str"]} | ||
rest_str = json.dumps(encrypt_data(in_data["rest"], in_encrypt)) | ||
encrypted_str, hash_str = in_encrypt(rest_str, in_data["pass"]) | ||
rest_str = json.dumps(encrypt_data(in_data["rest"], in_encryptor)) | ||
encrypted_str, hash_str = in_encryptor(rest_str, in_data["pass"]) | ||
return {"str": in_data["str"], "rest": encrypted_str, "hash": hash_str} | ||
|
||
|
||
def decrypt_data(in_rest, in_hash, in_pass, in_decrypt): | ||
rest_str = in_decrypt(in_rest, in_pass, in_hash) | ||
def decrypt_data(in_rest, in_hash, in_pass, in_decryptor): | ||
rest_str = in_decryptor(in_rest, in_pass, in_hash) | ||
if rest_str is None: | ||
return None | ||
return json.loads(rest_str) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,47 +1,61 @@ | ||
import itertools | ||
import typing | ||
import hashlib | ||
|
||
from .bytestr_utils import bytes_to_bytestr, bytestr_to_bytes | ||
|
||
|
||
def hash_bytes(in_bytes: bytes) -> str: | ||
return hashlib.sha512(in_bytes).hexdigest() | ||
def hash_bytes(in_bytes: bytes, in_hasher) -> str: | ||
return in_hasher(in_bytes).hexdigest() | ||
|
||
|
||
def int_to_bytes(in_val: int) -> bytes: | ||
return in_val.to_bytes((in_val.bit_length() + 7) // 8, "big") | ||
|
||
|
||
def proc_bytes(in_bytes: bytes, in_key: bytes) -> bytes: | ||
def proc_bytes(in_bytes: bytes, in_key: bytes, in_hasher) -> bytes: | ||
"""xors the in_bytes with a sequence of bytes generated with in_key""" | ||
key_bytes = itertools.chain.from_iterable( | ||
hashlib.sha512(in_key + int_to_bytes(block_num)).digest() | ||
in_hasher(in_key + int_to_bytes(block_num)).digest() | ||
for block_num in itertools.count(0) | ||
) | ||
return bytes(_d ^ _k for (_d, _k) in zip(in_bytes, key_bytes)) | ||
|
||
|
||
def encrypt_bytes(in_bytes: bytes, in_pass: bytes) -> typing.Tuple[bytes, str]: | ||
return proc_bytes(in_bytes, in_pass), hash_bytes(in_bytes) | ||
class Encryptor: | ||
def __init__(self, proc_hasher, signature_hasher): | ||
self._proc_hasher = proc_hasher | ||
self._signature_hasher = signature_hasher | ||
|
||
def __call__(self, in_str: str, in_pass: str) -> typing.Tuple[str, str]: | ||
encrypted_bytes, hash_str = self._encrypt_bytes( | ||
in_str.encode(), in_pass.encode() | ||
) | ||
return bytes_to_bytestr(encrypted_bytes), hash_str | ||
|
||
def decrypt_bytes(in_bytes: bytes, in_pass: bytes, in_hash: str) -> bytes | None: | ||
res = proc_bytes(in_bytes, in_pass) | ||
def _encrypt_bytes( | ||
self, in_bytes: bytes, in_pass: bytes | ||
) -> typing.Tuple[bytes, str]: | ||
return proc_bytes(in_bytes, in_pass, self._proc_hasher), hash_bytes( | ||
in_bytes, self._signature_hasher | ||
) | ||
|
||
if hash_bytes(res) == in_hash: | ||
return res | ||
return None | ||
|
||
class Decryptor: | ||
def __init__(self, proc_hasher, signature_hasher): | ||
self._proc_hasher = proc_hasher | ||
self._signature_hasher = signature_hasher | ||
|
||
def encrypt_str(in_str: str, in_pass: str) -> typing.Tuple[str, str]: | ||
"""encrypts in_str using in_pass""" | ||
encrypted_bytes, hash_str = encrypt_bytes(in_str.encode(), in_pass.encode()) | ||
return bytes_to_bytestr(encrypted_bytes), hash_str | ||
def __call__(self, in_str: str, in_pass: str, in_hash: str) -> str | None: | ||
res = self._decrypt_bytes(bytestr_to_bytes(in_str), in_pass.encode(), in_hash) | ||
if res is not None: | ||
return res.decode() | ||
return res | ||
|
||
def _decrypt_bytes( | ||
self, in_bytes: bytes, in_pass: bytes, in_hash: str | ||
) -> bytes | None: | ||
res = proc_bytes(in_bytes, in_pass, self._proc_hasher) | ||
|
||
def decrypt_str(in_str: str, in_pass: str, in_hash: str) -> str | None: | ||
res = decrypt_bytes(bytestr_to_bytes(in_str), in_pass.encode(), in_hash) | ||
if res is not None: | ||
return res.decode() | ||
return res | ||
if hash_bytes(res, self._signature_hasher) == in_hash: | ||
return res | ||
return None |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,36 +1,52 @@ | ||
import string | ||
import hashlib | ||
import itertools | ||
import pytest | ||
|
||
import puzzle_generator.simple_encryption_utils as seu | ||
|
||
|
||
_STRS = [ | ||
"", | ||
"some_str", | ||
"other_strstr!?#", | ||
"some_STR?!", | ||
string.printable, | ||
string.ascii_uppercase, | ||
string.whitespace, | ||
"ąęćśłń󿟥ĘĆŚŁŃÓŻŹ", | ||
"some_msg_with 🔨 and 🛷!", | ||
"a🎄b", | ||
"🎮🎈🥅🐾", | ||
"🎮🎈🥅🐾 a🎄b", | ||
"🏀", | ||
] | ||
|
||
_SOME_HASHES = [ | ||
hashlib.md5, | ||
hashlib.sha512, | ||
hashlib.sha3_512, | ||
hashlib.blake2s, | ||
] | ||
|
||
|
||
def _get_encryptor_decryptor_pair(proc_hasher, signature_hasher): | ||
return seu.Encryptor(proc_hasher, signature_hasher), seu.Decryptor( | ||
proc_hasher, signature_hasher | ||
) | ||
|
||
|
||
@pytest.mark.parametrize("in_str", _STRS) | ||
@pytest.mark.parametrize("in_pass", _STRS) | ||
@pytest.mark.parametrize( | ||
("in_encrypt_str", "in_decrypt_str"), [(seu.encrypt_str, seu.decrypt_str)] | ||
("encryptor", "decryptor"), | ||
[ | ||
_get_encryptor_decryptor_pair(*_) | ||
for _ in itertools.product(_SOME_HASHES, repeat=2) | ||
], | ||
) | ||
def test_seu(in_str, in_pass, in_encrypt_str, in_decrypt_str): | ||
encrypted, reshash = in_encrypt_str(in_str, in_pass) | ||
def test_seu(in_str, in_pass, encryptor, decryptor): | ||
encrypted, reshash = encryptor(in_str, in_pass) | ||
if in_str: | ||
assert encrypted != in_str | ||
else: | ||
assert not encrypted | ||
decrypted = in_decrypt_str(encrypted, in_pass, reshash) | ||
decrypted = decryptor(encrypted, in_pass, reshash) | ||
assert decrypted == in_str | ||
if in_str: | ||
assert in_decrypt_str(encrypted, in_pass + "?", reshash) is None | ||
assert decryptor(encrypted, in_pass + "?", reshash) is None |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters