Last active
August 14, 2024 05:57
-
-
Save PageotD/0d49cd2b2947b6cd17d31b059ce7deb6 to your computer and use it in GitHub Desktop.
simple file encryption/decrytion in python
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
import argparse | |
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes | |
from cryptography.hazmat.primitives import hashes | |
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC | |
from cryptography.hazmat.backends import default_backend | |
import os | |
# Constants | |
SALT_SIZE = 16 | |
IV_SIZE = 16 | |
KEY_SIZE = 32 | |
ITERATIONS = 100000 | |
def derive_key(passphrase: str, salt: bytes) -> bytes: | |
"""Derives a key from the passphrase and salt.""" | |
kdf = PBKDF2HMAC( | |
algorithm=hashes.SHA256(), | |
length=KEY_SIZE, | |
salt=salt, | |
iterations=ITERATIONS, | |
backend=default_backend() | |
) | |
return kdf.derive(passphrase.encode()) | |
def encrypt_data(passphrase: str, data: str) -> bytes: | |
"""Encrypts data using AES encryption.""" | |
salt = os.urandom(SALT_SIZE) | |
key = derive_key(passphrase, salt) | |
iv = os.urandom(IV_SIZE) | |
cipher = Cipher(algorithms.AES(key), modes.CFB(iv), backend=default_backend()) | |
encryptor = cipher.encryptor() | |
data_bytes = data.encode() | |
padding_length = (16 - len(data_bytes) % 16) % 16 | |
padded_data = data_bytes + bytes([padding_length] * padding_length) | |
encrypted_data = encryptor.update(padded_data) + encryptor.finalize() | |
return salt + iv + encrypted_data | |
def decrypt_data(passphrase: str, encrypted_data: bytes) -> str: | |
"""Decrypts data using AES encryption.""" | |
salt = encrypted_data[:SALT_SIZE] | |
iv = encrypted_data[SALT_SIZE:SALT_SIZE+IV_SIZE] | |
encrypted_data = encrypted_data[SALT_SIZE+IV_SIZE:] | |
key = derive_key(passphrase, salt) | |
cipher = Cipher(algorithms.AES(key), modes.CFB(iv), backend=default_backend()) | |
decryptor = cipher.decryptor() | |
decrypted_data = decryptor.update(encrypted_data) + decryptor.finalize() | |
padding_length = decrypted_data[-1] | |
return decrypted_data[:-padding_length].decode() | |
def save_encrypted_file(filepath: str, passphrase: str, data: str): | |
"""Encrypts data and saves it to a file.""" | |
encrypted_data = encrypt_data(passphrase, data) | |
with open(filepath, 'wb') as file: | |
file.write(encrypted_data) | |
def load_decrypted_file(filepath: str, passphrase: str) -> str: | |
"""Loads and decrypts data from a file.""" | |
with open(filepath, 'rb') as file: | |
encrypted_data = file.read() | |
return decrypt_data(passphrase, encrypted_data) | |
def change_passphrase(filepath: str, old_passphrase: str, new_passphrase: str): | |
"""Change the passphrase for an encrypted file.""" | |
# Load and decrypt the data with the old passphrase | |
decrypted_data = load_decrypted_file(filepath, old_passphrase) | |
# Encrypt the data with the new passphrase | |
save_encrypted_file(filepath, new_passphrase, decrypted_data) | |
def main(): | |
parser = argparse.ArgumentParser(description="Encrypt, decrypt, or change passphrase of files.") | |
subparsers = parser.add_subparsers(dest='command') | |
# Encrypt command | |
encrypt_parser = subparsers.add_parser('encrypt', help='Encrypt a file') | |
encrypt_parser.add_argument('filepath', help='Path to the file to encrypt') | |
# Decrypt command | |
decrypt_parser = subparsers.add_parser('decrypt', help='Decrypt a file') | |
decrypt_parser.add_argument('filepath', help='Path to the file to decrypt') | |
# Change passphrase command | |
change_passphrase_parser = subparsers.add_parser('changepass', help='Change the passphrase of a file') | |
change_passphrase_parser.add_argument('filepath', help='Path to the file to update') | |
change_passphrase_parser.add_argument('old_passphrase', help='Current passphrase') | |
change_passphrase_parser.add_argument('new_passphrase', help='New passphrase') | |
args = parser.parse_args() | |
if args.command == 'encrypt': | |
passphrase = input("Enter passphrase: ") | |
with open(args.filepath, 'r') as file: | |
data = file.read() | |
save_encrypted_file(args.filepath + '.enc', passphrase, data) | |
print(f"File encrypted and saved as {args.filepath}.enc") | |
elif args.command == 'decrypt': | |
passphrase = input("Enter passphrase: ") | |
decrypted_data = load_decrypted_file(args.filepath, passphrase) | |
with open(args.filepath + '.dec', 'w') as file: | |
file.write(decrypted_data) | |
print(f"File decrypted and saved as {args.filepath}.dec") | |
elif args.command == 'changepass': | |
change_passphrase(args.filepath, args.old_passphrase, args.new_passphrase) | |
print(f"Passphrase changed for {args.filepath}") | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment