Skip to content

Commit 15fe9d5

Browse files
authored
Merge pull request #19 from ZhaoQi99/feat/add-unit-test
Feat/add unit test
2 parents 96f7d5e + 8e67666 commit 15fe9d5

File tree

17 files changed

+463
-57
lines changed

17 files changed

+463
-57
lines changed

dev-requirement.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
-r requirement.txt
22
isort==5.10.1
3-
yapf==0.31.0
3+
yapf==0.31.0
4+
pytest==6.2.5
5+
ipython==7.16.3

pyencrypt/aes.py

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -848,21 +848,3 @@ def aes_decrypt(data: bytes, key: str) -> bytes:
848848
plain.append(AESModeOfOperationECB(key).decrypt(x))
849849
return strip_padding(b''.join(plain))
850850

851-
852-
if __name__ == '__main__':
853-
plain = '你好!世界!'
854-
key = 'tB9qW0YGlYIyBfTmuyQbm6AjPQa9gTKwO8j5H4IBf1A='
855-
plain = add_padding(plain.encode())
856-
print('plain', plain)
857-
cipher = AESModeOfOperationECB(key).encrypt(plain)
858-
print('cipher', cipher)
859-
plain = strip_padding(AESModeOfOperationECB(key).decrypt(cipher))
860-
print(plain)
861-
print(plain.decode())
862-
863-
with open('generate.py', 'rb') as f:
864-
data = f.read()
865-
cipher = aes_encrypt(data, key)
866-
print(cipher)
867-
plain = aes_decrypt(cipher, key)
868-
print(plain.decode())

pyencrypt/decrypt.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
from pyencrypt.ntt import intt
55

66

7-
def decrypt_key(cipher_key: str, n: int, d: int) -> str:
7+
def decrypt_key(cipher_key: str, d: int, n: int) -> str:
88
plain_ls = list()
99
for num in map(int, cipher_key.split('O')):
1010
plain_ls.append(pow(num, d, n))

pyencrypt/encrypt.py

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
def _encrypt_file(
1515
data: bytes,
1616
key: bytes,
17-
) -> None:
17+
) -> bytes:
1818
return aes_encrypt(data, key)
1919

2020

@@ -32,14 +32,19 @@ def encrypt_key(key: bytes) -> str:
3232
ascii_ls = [ord(x) for x in key.decode()]
3333
numbers = generate_rsa_number(2048)
3434
e, n = numbers['e'], numbers['n']
35+
# fill length to be a power of 2
36+
length = len(ascii_ls)
37+
if length & (length - 1) != 0:
38+
length = 1 << length.bit_length()
39+
ascii_ls = ascii_ls + [0] * (length - len(ascii_ls))
3540
cipher_ls = list()
3641
# ntt后再用RSA加密
3742
for num in ntt(ascii_ls):
3843
cipher_ls.append(pow(num, e, n))
3944
return 'O'.join(map(str, cipher_ls)), numbers['d'], numbers['n']
4045

4146

42-
def generate_so_file(cipher_key: str, d: int, n: int):
47+
def generate_so_file(cipher_key: str, d: int, n: int, base_dir: Path = None):
4348
private_key = f'{n}O{d}'
4449
path = Path(os.path.abspath(__file__)).parent
4550

@@ -57,7 +62,10 @@ def generate_so_file(cipher_key: str, d: int, n: int):
5762
1).replace("__cipher_key = ''", f"__cipher_key = '{cipher_key}'",
5863
1).replace("from pyencrypt.decrypt import *", '')
5964

60-
temp_dir = Path(os.getcwd()) / 'encrypted'
65+
if base_dir is None:
66+
base_dir = Path(os.getcwd())
67+
68+
temp_dir = base_dir / 'encrypted'
6169
temp_dir.mkdir(exist_ok=True)
6270
loader_file_path = temp_dir / 'loader.py'
6371
loader_file_path.touch(exist_ok=True)
@@ -70,7 +78,6 @@ def generate_so_file(cipher_key: str, d: int, n: int):
7078
loader_origin_file_path.touch(exist_ok=True)
7179
loader_origin_file_path.write_text(f"{decrypt_source}\n{loader_source}")
7280

73-
setup_file_path = Path(os.path.abspath(__file__)).parent / 'setup.py'
7481
args = [
7582
'pyminifier', '--obfuscate-classes', '--obfuscate-import-methods',
7683
'--replacement-length', '20', '-o',
@@ -81,17 +88,16 @@ def generate_so_file(cipher_key: str, d: int, n: int):
8188
if ret.returncode == 0:
8289
pass
8390

84-
args = [
85-
'python',
86-
setup_file_path.as_posix(), 'build_ext', '--build-lib',
87-
temp_dir.as_posix()
88-
]
89-
ret = subprocess.run(args,
90-
shell=False,
91-
stderr=subprocess.PIPE,
92-
encoding='utf-8')
93-
if ret.returncode == 0:
94-
pass
91+
from setuptools import setup
92+
from Cython.Build import cythonize
93+
from Cython.Distutils import build_ext
94+
setup(
95+
ext_modules=cythonize(loader_file_path.as_posix(), language_level="3"),
96+
script_args=['build_ext', '--build-lib', temp_dir.as_posix()],
97+
cmdclass={'build_ext': build_ext},
98+
)
99+
100+
return True
95101

96102

97103
def encrypt_file(path: Path,

pyencrypt/generate.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,11 @@
44
from Crypto.PublicKey import RSA
55

66

7-
def generate_aes_key(size: int = 32) -> str:
7+
def generate_aes_key(size: int = 32) -> bytes:
88
return base64.b64encode(os.urandom(size))
99

1010

11-
def generate_rsa_number(bits: int):
11+
def generate_rsa_number(bits: int)-> dict:
1212
r = RSA.generate(bits)
1313
return {'p': r.p, 'q': r.q, 'n': r.n, 'e': r.e, 'd': r.d}
1414

15-
16-
if __name__ == '__main__':
17-
print(generate_aes_key(32))
18-
print(generate_rsa_number(2048))

pyencrypt/loader.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ def get_data(self, path: _Path) -> bytes:
3333
try:
3434
__n, __d = self.__private_key.split('O', 1)
3535
return decrypt_file(
36-
Path(path), decrypt_key(self.__cipher_key, int(__n), int(__d)))
36+
Path(path), decrypt_key(self.__cipher_key, int(__d), int(__n)))
3737
except Exception:
3838
traceback.print_exc()
3939
return b''
@@ -51,7 +51,10 @@ def find_spec(self,
5151
else:
5252
file_path = Path(path[0]) / f'{fullname.rsplit(".",1)[-1]}.pye'
5353
else:
54-
file_path = Path(f'{fullname}.pye')
54+
for p in sys.path:
55+
file_path = Path(p) / f'{fullname}.pye'
56+
if file_path.exists():
57+
break
5558
file_path = file_path.absolute().as_posix()
5659
if not os.path.exists(file_path):
5760
return None

pyencrypt/ntt.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ def bitreverse(x: list, length: int):
1616

1717

1818
def _ntt(arr: list, inverse=False):
19-
length = 1
20-
while length < len(arr):
21-
length *= 2
22-
x = arr + [0] * (length - len(arr))
19+
length = len(arr)
20+
if length & (length - 1) != 0:
21+
raise ValueError("The length of input must be a power of 2.")
22+
x = arr.copy()
2323
g = pow(G, (M - 1) // length, M)
2424
if inverse:
2525
g = pow(g, M - 2, M)

pyencrypt/setup.py

Lines changed: 0 additions & 8 deletions
This file was deleted.

setup.cfg

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ classifiers =
2020
Programming Language :: Python :: 3.9
2121
Programming Language :: Python :: Implementation :: CPython
2222
Environment :: Console
23-
license_file = LICENSE
23+
license_files = LICENSE
2424
description = A simple image converter for Python.
2525
long_description = file: README.md
2626
long_description_content_type = text/markdown
@@ -45,4 +45,11 @@ exclude =
4545

4646
[options.entry_points]
4747
console_scripts =
48-
pyencrypt = pyencrypt.cli:cli
48+
pyencrypt = pyencrypt.cli:cli
49+
50+
[yapf]
51+
based_on_style = pep8
52+
COLUMN_LIMIT = 119
53+
indent_width = 4
54+
coalesce_brackets = True
55+
dedent_closing_brackets = True

tests/constants.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
AES_KEY = b'tiovaZzCF/Hlx/8uw0PXCkiqxCXGosP/AKo6Kn1gECw='

0 commit comments

Comments
 (0)