From 4826f2fe7526c2ef9d61adc2dd68b151db73483e Mon Sep 17 00:00:00 2001 From: LucasVerdelho Date: Tue, 5 Mar 2024 11:18:24 +0000 Subject: [PATCH] TP03 pbenc_aes_ctr_hmac in python --- TPs/TP03/py/pbenc_aes_ctr_hmac.py | 128 ++++++++++++++++++++++++++++++ TPs/TP03/py/plaintext.txt | 1 + TPs/TP03/py/plaintext.txt.enc | Bin 0 -> 77 bytes TPs/TP03/py/plaintext.txt.enc.dec | 1 + 4 files changed, 130 insertions(+) create mode 100644 TPs/TP03/py/pbenc_aes_ctr_hmac.py create mode 100644 TPs/TP03/py/plaintext.txt create mode 100644 TPs/TP03/py/plaintext.txt.enc create mode 100644 TPs/TP03/py/plaintext.txt.enc.dec diff --git a/TPs/TP03/py/pbenc_aes_ctr_hmac.py b/TPs/TP03/py/pbenc_aes_ctr_hmac.py new file mode 100644 index 0000000..76a0fbf --- /dev/null +++ b/TPs/TP03/py/pbenc_aes_ctr_hmac.py @@ -0,0 +1,128 @@ +#!/usr/bin/env python3 + +from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes +from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC +from cryptography.hazmat.primitives import hashes +from cryptography.hazmat.primitives import hmac +import os +import argparse + + + +def encrypt(input_file, password): + inp = open(input_file,"rb") + out = open(f"{input_file}.enc","wb") + + plaintext = inp.read() + print(f"plaintext len : {len(plaintext)}") + + + # Derive the key from the password using PBKDF2 + salt = os.urandom(16) + kdf = PBKDF2HMAC( + algorithm=hashes.SHA256(), + length=64, + salt=salt, + iterations=100000 + ) + # FIX: key length must be 32 bytes + derived_key = kdf.derive(password.encode('utf-8')) + + key = derived_key[:32] + hmac_key = derived_key[32:] + + iv = os.urandom(16) + + cipher = Cipher(algorithms.AES(key),modes.CTR(iv)) + encryptor = cipher.encryptor() + ciphertext = encryptor.update(plaintext) + + ciphertext = salt + iv + ciphertext + + print(f"plaintext len : {len(plaintext)}") + print(f"ciphertext len : {len(ciphertext)}") + print(f"iv len : {len(iv)}") + + h = hmac.HMAC(hmac_key,hashes.SHA256()) + h.update(ciphertext) + tag = h.finalize() + ciphertext = ciphertext + tag + + out.write(ciphertext) + + inp.close() + out.close() + +def decrypt(input_file,password): + inp = open(f"{input_file}","rb") + out = open(f"{input_file}.dec","wb") + + input_bytes = inp.read() + salt = input_bytes[:16] + iv = input_bytes[16:32] + ciphertext = input_bytes[32:-32] + tag = input_bytes[-32:] + + kdf = PBKDF2HMAC( + algorithm=hashes.SHA256(), + length=64, + salt=salt, + iterations=100000 + ) + + print(f"plaintext len : {len(ciphertext)}") + print(f"iv len : {len(iv)}") + print(f"salt len : {len(salt)}") + + derived_key = kdf.derive(password.encode('utf-8')) + hmac_key = derived_key[32:] + key = derived_key[:32] + + # FIX: block size for aes must be 16 bytes + # plaintext needs padding + cipher = Cipher(algorithms.AES(key),modes.CTR(iv)) + decryptor = cipher.decryptor() + plaintext = decryptor.update(ciphertext) + + h = hmac.HMAC(hmac_key,hashes.SHA256()) + h.update(salt + iv + ciphertext) + if (h.finalize() != tag): + print("Error: HMAC verification failed") + return + + + out.write(plaintext) + + inp.close() + out.close() + +def main(): + parser = argparse.ArgumentParser( + description="Program to perform operations using AES cipher on files", + ) + + subparsers = parser.add_subparsers(dest="operation", help="Operation to perform") + + # Encrypt subcommand + enc_parser = subparsers.add_parser("enc", help="Encrypt a file") + enc_parser.add_argument("fich", help="File to be encrypted") + enc_parser.add_argument("password", help="Pass-phrase to derive the key") + + # Decrypt subcommand + dec_parser = subparsers.add_parser("dec", help="Decrypt a file") + dec_parser.add_argument("fich", help="File to be decrypted") + dec_parser.add_argument("password", help="Pass-phrase to derive the key") + + args = parser.parse_args() + match args.operation: + case "enc": + input_file = args.fich + password = args.password + encrypt(input_file,password) + case "dec": + input_file = args.fich + password = args.password + decrypt(input_file,password) + +if __name__ == "__main__": + main() diff --git a/TPs/TP03/py/plaintext.txt b/TPs/TP03/py/plaintext.txt new file mode 100644 index 0000000..549938f --- /dev/null +++ b/TPs/TP03/py/plaintext.txt @@ -0,0 +1 @@ +not very safe \ No newline at end of file diff --git a/TPs/TP03/py/plaintext.txt.enc b/TPs/TP03/py/plaintext.txt.enc new file mode 100644 index 0000000000000000000000000000000000000000..dfd60ebb9ae6f7fcbe9d9d94b446cf21286c482e GIT binary patch literal 77 zcmV-T0J8t8xPVM*C7L+n!;KhNA~6H%mG{D7W(&tt^o3ZOo{Ep8Rj0@m@JYpflWH(p jX`@B`#tYcjy8@l8xd1>^{xOyLzk>j>7yP(s%GSX7