Skip to content

Commit 315b785

Browse files
authored
Merge pull request #1 from phong1202/feature-security
Add encrypt and decrypt for file or folder
2 parents 16139ce + 3ed3d77 commit 315b785

2 files changed

Lines changed: 79 additions & 0 deletions

File tree

pyproject.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,9 @@ image = [
4040
"pillow",
4141
"opencv-python-headless"
4242
]
43+
security = [
44+
"cryptography"
45+
]
4346

4447
[project.urls]
4548
"Homepage" = "https://github.com/rabiloo/python-data-helper"

src/data_helper/security.py

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
"""Security file."""
2+
3+
import os
4+
5+
from cryptography.hazmat.backends import default_backend
6+
from cryptography.hazmat.primitives import hashes, padding
7+
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
8+
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
9+
10+
11+
def derive_key(key: str, salt: bytes) -> bytes:
12+
kdf = PBKDF2HMAC(algorithm=hashes.SHA256(), length=32, salt=salt, iterations=100_000, backend=default_backend())
13+
return kdf.derive(key.encode())
14+
15+
16+
def file_encrypt(input_file_path: str, output_file_path: str, secret_key: str):
17+
"""Encrypt content with aes."""
18+
with open(input_file_path, "rb") as file:
19+
content = file.read()
20+
21+
salt = os.urandom(16)
22+
iv = os.urandom(16)
23+
24+
aes_key = derive_key(secret_key, salt=salt)
25+
cipher = Cipher(algorithms.AES(aes_key), modes.CBC(iv), backend=default_backend())
26+
27+
encryptor = cipher.encryptor()
28+
padder = padding.PKCS7(algorithms.AES.block_size).padder()
29+
padder_plaintext = padder.update(content) + padder.finalize()
30+
31+
ciphertext = encryptor.update(padder_plaintext) + encryptor.finalize()
32+
encrypted_data = salt + iv + ciphertext
33+
34+
os.makedirs(os.path.dirname(output_file_path), exist_ok=True)
35+
with open(output_file_path, "wb") as file:
36+
file.write(encrypted_data)
37+
38+
39+
def file_decrypt(input_file_path: str, output_file_path: str, secret_key: str):
40+
"""Decrypt content with aes."""
41+
with open(input_file_path, "rb") as file:
42+
content = file.read()
43+
44+
salt = content[:16]
45+
iv = content[16:32]
46+
ciphertext = content[32:]
47+
48+
aes_key = derive_key(secret_key, salt=salt)
49+
cipher = Cipher(algorithms.AES(aes_key), modes.CBC(iv), backend=default_backend())
50+
51+
decryptor = cipher.decryptor()
52+
unpadder = padding.PKCS7(algorithms.AES.block_size).unpadder()
53+
decrypted_data = decryptor.update(ciphertext) + decryptor.finalize()
54+
decrypted_data = unpadder.update(decrypted_data) + unpadder.finalize()
55+
56+
os.makedirs(os.path.dirname(output_file_path), exist_ok=True)
57+
with open(output_file_path, "wb") as file:
58+
file.write(decrypted_data)
59+
60+
61+
def folder_encrypt(input_folder_path: str, output_folder_path: str, secret_key: str):
62+
"""Encrypt folder content with aes."""
63+
for root, _, files in os.walk(input_folder_path):
64+
for file in files:
65+
input_file_path = os.path.join(root, file)
66+
output_file_path = os.path.join(root.replace(input_folder_path, output_folder_path), file)
67+
file_encrypt(input_file_path, output_file_path, secret_key)
68+
69+
70+
def folder_decrypt(input_folder_path: str, output_folder_path: str, secret_key: str):
71+
"""Decrypt folder content with aes."""
72+
for root, _, files in os.walk(input_folder_path):
73+
for file in files:
74+
input_file_path = os.path.join(root, file)
75+
output_file_path = os.path.join(root.replace(input_folder_path, output_folder_path), file)
76+
file_decrypt(input_file_path, output_file_path, secret_key)

0 commit comments

Comments
 (0)