File size: 4,470 Bytes
136c0f7 3e0b7ff 136c0f7 3e0b7ff 136c0f7 3e0b7ff 136c0f7 3e0b7ff 136c0f7 3e0b7ff 136c0f7 3e0b7ff 136c0f7 3e0b7ff 136c0f7 3e0b7ff 136c0f7 3e0b7ff 136c0f7 3e0b7ff 136c0f7 3e0b7ff 136c0f7 3e0b7ff 136c0f7 3e0b7ff 136c0f7 3e0b7ff 136c0f7 3e0b7ff 136c0f7 3e0b7ff 136c0f7 3e0b7ff 136c0f7 3e0b7ff 136c0f7 3e0b7ff 136c0f7 3e0b7ff 136c0f7 3e0b7ff | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 | import os
import json
import base64
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
# --- Helper: Generate AES Key ---
def generate_key(password: str, salt: bytes) -> bytes:
kdf = PBKDF2HMAC(
algorithm=hashes.SHA256(),
length=32,
salt=salt,
iterations=100000,
)
return kdf.derive(password.encode())
# --- Encrypt password with AES-GCM ---
def encrypt_password(password: str, key: bytes):
# AES-GCM uses a 12-byte Nonce instead of a 16-byte IV
nonce = os.urandom(12)
aesgcm = AESGCM(key)
# The encrypt method returns: ciphertext + 16-byte authentication tag
ciphertext = aesgcm.encrypt(nonce, password.encode(), None)
# We store Nonce + Ciphertext (which includes the Tag)
return base64.b64encode(nonce + ciphertext).decode()
# --- Decrypt password with AES-GCM ---
def decrypt_password(encrypted_password: str, key: bytes):
raw = base64.b64decode(encrypted_password)
nonce, ciphertext = raw[:12], raw[12:]
aesgcm = AESGCM(key)
# Decrypt will automatically verify the Tag. If tampered with, it throws an InvalidTag exception.
return aesgcm.decrypt(nonce, ciphertext, None).decode()
# --- Store password ---
def store_password(account: str, username: str, password: str, master_password: str):
salt = os.urandom(16)
key = generate_key(master_password, salt)
encrypted_pw = encrypt_password(password, key)
data = {"account": account, "username": username, "password": encrypted_pw, "salt": base64.b64encode(salt).decode()}
try:
with open("passwords.json", "r") as f:
records = json.load(f)
except FileNotFoundError:
records = []
records = [r for r in records if r["account"] != account]
records.append(data)
with open("passwords.json", "w") as f:
json.dump(records, f, indent=4)
print(f"[+] Authenticated GCM password stored for: {account}")
# --- Retrieve password ---
def retrieve_password(account: str, master_password: str):
try:
with open("passwords.json", "r") as f:
records = json.load(f)
except FileNotFoundError:
return None
for r in records:
if r["account"] == account:
salt = base64.b64decode(r["salt"])
key = generate_key(master_password, salt)
try:
return decrypt_password(r["password"], key)
except Exception:
print("[-] Master password incorrect or data tampered with!")
return None
return None
# --- Encrypt file ---
def encrypt_file(file_path: str, account: str, master_password: str):
password = retrieve_password(account, master_password)
if not password: return
try:
with open(file_path, "rb") as f:
content = f.read()
except FileNotFoundError: return
salt = os.urandom(16)
nonce = os.urandom(12)
key = generate_key(password, salt)
aesgcm = AESGCM(key)
ciphertext = aesgcm.encrypt(nonce, content, None)
enc_file = file_path + ".enc"
with open(enc_file, "wb") as f:
f.write(ciphertext)
meta = {
"salt": base64.b64encode(salt).decode(),
"nonce": base64.b64encode(nonce).decode(), # Now storing Nonce instead of IV
"account": account
}
with open(enc_file + ".meta", "w") as f:
json.dump(meta, f)
print(f"[+] File encrypted with AES-GCM: {enc_file}")
# --- Decrypt file ---
def decrypt_file(enc_file: str, master_password: str):
meta_file = enc_file + ".meta"
if not os.path.exists(meta_file): return
with open(meta_file, "r") as f:
meta = json.load(f)
account = meta["account"]
salt = base64.b64decode(meta["salt"])
nonce = base64.b64decode(meta["nonce"])
password = retrieve_password(account, master_password)
if not password: return
key = generate_key(password, salt)
with open(enc_file, "rb") as f:
ciphertext = f.read()
aesgcm = AESGCM(key)
try:
data = aesgcm.decrypt(nonce, ciphertext, None)
dec_file = enc_file.replace(".enc", "_decrypted")
with open(dec_file, "wb") as f:
f.write(data)
print(f"[+] Authenticated decryption successful: {dec_file}")
except Exception:
print("[-] Decryption failed: Invalid password or corrupted data.") |