diff --git a/src/collection.py b/src/collection.py index 603163f..130ae74 100644 --- a/src/collection.py +++ b/src/collection.py @@ -1,8 +1,8 @@ from pathlib import Path -from os import walk, chmod +from os import chmod from Crypto.PublicKey import RSA -class ssh_key: +class SshKey: """ Object class for a ssh key """ @@ -38,25 +38,23 @@ class Collection: public class to generate a ssh key """ key = RSA.generate(2048) - sshKey = ssh_key(name=name, key_type=key_type, private=key.exportKey('PEM'), public=key.publickey().exportKey('OpenSSH')) - self.save_ssh_key(sshKey=sshKey) + my_ssh_key = SshKey(name=name, key_type=key_type, private=key.exportKey('PEM'), public=key.publickey().exportKey('OpenSSH')) + self.save_ssh_key(my_ssh_key=my_ssh_key) - def save_ssh_key(self, sshKey: ssh_key): + def save_ssh_key(self, my_ssh_key: SshKey): """ - Function to save the sshkey + Function to save the ssh key """ - key_file_path = self.collection_path.joinpath(sshKey.get_name()) + key_file_path = self.collection_path.joinpath(my_ssh_key.get_name()) + ## Info File with open(f"{key_file_path}.txt", "w+", encoding="utf-8") as info_file: - info_file.write(f"name: {sshKey.get_name()}\nKey_type: {sshKey.get_type()}") + info_file.write(f"name: {my_ssh_key.get_name()}\nKey_type: {my_ssh_key.get_type()}") + + ## Private Key with open(key_file_path, "wb") as private_file: - private_file.write(sshKey.get_private()) + private_file.write(my_ssh_key.get_private()) + chmod(key_file_path, 0o600) + + ## Public Key with open(f"{key_file_path}.pub", "wb") as public_file: - public_file.write(sshKey.get_public()) - - - - - - - - + public_file.write(my_ssh_key.get_public()) diff --git a/src/encryptor.py b/src/encryptor.py new file mode 100644 index 0000000..eb27ca5 --- /dev/null +++ b/src/encryptor.py @@ -0,0 +1,57 @@ +import base64 +import os +from Crypto.Cipher import AES +from Crypto.Protocol.KDF import PBKDF2 +from Crypto.Random import get_random_bytes + +class Encryptor: + def __init__(self, password: str): + self.password = password.encode() + self.salt_size = 16 + self.iv_size = 16 + self.key_size = 32 + self.iterations = 100_000 + + def _derive_key(self, salt: bytes) -> bytes: + """ + Dérive une clé à partir du mot de passe et du sel. + """ + return PBKDF2(self.password, salt, dkLen=self.key_size, count=self.iterations) + + def encrypt(self, plaintext: str) -> str: + """ + Encrypte une chaîne de texte en base64. + """ + salt = get_random_bytes(self.salt_size) + key = self._derive_key(salt) + iv = get_random_bytes(self.iv_size) + + # Padding (PKCS7) + pad_len = AES.block_size - (len(plaintext.encode()) % AES.block_size) + padded = plaintext + chr(pad_len) * pad_len + + cipher = AES.new(key, AES.MODE_CBC, iv) + ciphertext = cipher.encrypt(padded.encode()) + + # Encodage final : salt + iv + ciphertext + encrypted_data = base64.b64encode(salt + iv + ciphertext).decode() + return encrypted_data + + def decrypt(self, encrypted_text: str) -> str: + """ + Décrypte une chaîne encodée en base64. + """ + data = base64.b64decode(encrypted_text) + salt = data[:self.salt_size] + iv = data[self.salt_size:self.salt_size + self.iv_size] + ciphertext = data[self.salt_size + self.iv_size:] + + key = self._derive_key(salt) + cipher = AES.new(key, AES.MODE_CBC, iv) + padded_plaintext = cipher.decrypt(ciphertext) + + # Retrait du padding + pad_len = padded_plaintext[-1] + plaintext = padded_plaintext[:-pad_len].decode() + + return plaintext