encrypt.py
Raw
1from cryptography.hazmat.primitives import hashes
2from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
3from cryptography.hazmat.primitives.ciphers.aead import AESGCM
4from cryptography.hazmat.backends import default_backend
5import os
6import sys
7
8def encrypt(content: bytes, password: str) -> bytes:
9 """
10 Encrypts the given content using the provided password.
11
12 Uses AES-256-GCM with a PBKDF2-HMAC-SHA512 derived key, matching the
13 server/browser implementation in src/crypto.ts.
14
15 Args:
16 content (bytes): The content to be encrypted.
17 password (str): The password used for encryption.
18
19 Returns:
20 bytes: salt[16] | iv[12] | ciphertext+tag
21 """
22
23 # Generate a random initialization vector (IV) and salt
24 iv = os.urandom(12)
25 salt = os.urandom(16)
26
27 # Derive a key from the password using PBKDF2
28 kdf = PBKDF2HMAC(
29 algorithm=hashes.SHA512(),
30 length=32,
31 salt=salt,
32 iterations=210000,
33 backend=default_backend()
34 )
35 key = kdf.derive(password.encode())
36
37 # Encrypt with AES-256-GCM (the authentication tag is appended to the ciphertext)
38 encrypted_content = AESGCM(key).encrypt(iv, content, None)
39
40 # Return the salt, IV, and encrypted content concatenated
41 return salt + iv + encrypted_content
42if __name__ == "__main__":
43 if len(sys.argv) != 4:
44 print("Usage: encrypt.py <file> <password> <outfile>")
45 sys.exit(1)
46 data = encrypt(open(sys.argv[1], "rb").read(), sys.argv[2])
47 open(sys.argv[3], "wb").write(data)
48