2024-03-05 12:05:12 +00:00
|
|
|
import argparse
|
|
|
|
import os
|
|
|
|
|
2024-03-16 17:11:11 +00:00
|
|
|
import cryptography.hazmat.primitives.serialization as serialization
|
2024-03-05 12:05:12 +00:00
|
|
|
from cryptography.hazmat.primitives import hashes
|
|
|
|
from cryptography.hazmat.primitives.asymmetric import dh
|
|
|
|
from cryptography.hazmat.primitives.ciphers.aead import ChaCha20Poly1305
|
|
|
|
from cryptography.hazmat.primitives.kdf.hkdf import HKDF
|
|
|
|
from cryptography.hazmat.primitives.serialization import (
|
|
|
|
Encoding,
|
|
|
|
NoEncryption,
|
|
|
|
PrivateFormat,
|
|
|
|
PublicFormat,
|
|
|
|
)
|
|
|
|
|
2024-03-16 17:11:11 +00:00
|
|
|
p = 0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF
|
|
|
|
g = 2
|
|
|
|
params = dh.DHParameterNumbers(p, g).parameters()
|
|
|
|
|
2024-03-05 12:05:12 +00:00
|
|
|
def setup(user):
|
2024-03-16 17:11:11 +00:00
|
|
|
private_key = params.generate_private_key()
|
2024-03-05 12:05:12 +00:00
|
|
|
public_key = private_key.public_key()
|
|
|
|
|
2024-03-16 17:11:11 +00:00
|
|
|
skey = open(f"{user}.sk", "wb")
|
|
|
|
pkey = open(f"{user}.pk", "wb")
|
|
|
|
skey.write(
|
|
|
|
private_key.private_bytes(
|
|
|
|
encoding=Encoding.PEM,
|
|
|
|
format=PrivateFormat.PKCS8,
|
|
|
|
encryption_algorithm=NoEncryption(),
|
|
|
|
)
|
|
|
|
)
|
|
|
|
pkey.write(
|
|
|
|
public_key.public_bytes(
|
|
|
|
encoding=Encoding.PEM, format=PublicFormat.SubjectPublicKeyInfo
|
|
|
|
)
|
|
|
|
)
|
2024-03-05 12:05:12 +00:00
|
|
|
skey.close()
|
|
|
|
pkey.close()
|
|
|
|
|
|
|
|
|
2024-03-16 17:11:11 +00:00
|
|
|
def encrypt(user, filename):
|
|
|
|
peer_pkey_file = open(f"{user}.pk", "rb")
|
2024-03-05 12:05:12 +00:00
|
|
|
if peer_pkey_file is None:
|
|
|
|
print(f"No public key found for {user}")
|
|
|
|
return
|
|
|
|
|
2024-03-16 17:11:11 +00:00
|
|
|
file_r = open(filename, "rb")
|
2024-03-05 12:05:12 +00:00
|
|
|
if file_r is None:
|
|
|
|
print(f"File {filename} not found")
|
|
|
|
return
|
|
|
|
|
2024-03-16 17:11:11 +00:00
|
|
|
|
|
|
|
skey = params.generate_private_key()
|
|
|
|
peer_pkey = serialization.load_pem_public_key(peer_pkey_file.read())
|
|
|
|
if not isinstance(peer_pkey, dh.DHPublicKey):
|
2024-03-05 12:05:12 +00:00
|
|
|
print("Error: Invalid key type")
|
|
|
|
return
|
|
|
|
|
2024-03-16 17:11:11 +00:00
|
|
|
shared_key = skey.exchange(peer_pkey)
|
|
|
|
derived_key = HKDF(
|
|
|
|
algorithm=hashes.SHA256(), length=32, salt=None, info=None
|
|
|
|
).derive(shared_key)
|
|
|
|
|
2024-03-05 12:05:12 +00:00
|
|
|
message = file_r.read()
|
|
|
|
chacha = ChaCha20Poly1305(derived_key)
|
|
|
|
nonce = os.urandom(12)
|
|
|
|
ciphertext = chacha.encrypt(nonce, message, None)
|
2024-03-16 17:11:11 +00:00
|
|
|
file_w = open(f"{filename}.enc", "wb")
|
|
|
|
nonce_ciphertext = nonce + ciphertext
|
|
|
|
pkey_bytes = skey.public_key().public_bytes(
|
|
|
|
Encoding.DER, PublicFormat.SubjectPublicKeyInfo
|
|
|
|
)
|
|
|
|
to_send = mkpair(pkey_bytes, nonce_ciphertext)
|
2024-03-05 12:05:12 +00:00
|
|
|
file_w.write(to_send)
|
|
|
|
|
|
|
|
file_r.close()
|
|
|
|
file_w.close()
|
|
|
|
peer_pkey_file.close()
|
|
|
|
|
|
|
|
|
2024-03-16 17:11:11 +00:00
|
|
|
def decrypt(user, filename):
|
|
|
|
skey_file = open(f"{user}.sk", "rb")
|
2024-03-05 12:05:12 +00:00
|
|
|
if skey_file is None:
|
|
|
|
print(f"No private key found for {user}")
|
|
|
|
return
|
|
|
|
|
2024-03-16 17:11:11 +00:00
|
|
|
file_r = open(filename, "rb")
|
2024-03-05 12:05:12 +00:00
|
|
|
if file_r is None:
|
|
|
|
print(f"File {filename} not found")
|
|
|
|
return
|
|
|
|
|
|
|
|
message_bytes = file_r.read()
|
|
|
|
peer_pkey_bytes, ciphertext = unpair(message_bytes)
|
2024-03-16 17:11:11 +00:00
|
|
|
|
|
|
|
skey = serialization.load_pem_private_key(skey_file.read(), None)
|
|
|
|
peer_pkey = serialization.load_der_public_key(peer_pkey_bytes)
|
|
|
|
if not isinstance(skey, dh.DHPrivateKey) or not isinstance(
|
|
|
|
peer_pkey, dh.DHPublicKey
|
|
|
|
):
|
2024-03-05 12:05:12 +00:00
|
|
|
print("Error: Invalid key type")
|
|
|
|
return
|
|
|
|
|
2024-03-16 17:11:11 +00:00
|
|
|
shared_key = skey.exchange(peer_pkey)
|
|
|
|
derived_key = HKDF(
|
|
|
|
algorithm=hashes.SHA256(), length=32, salt=None, info=None
|
|
|
|
).derive(shared_key)
|
|
|
|
|
|
|
|
nonce = ciphertext[:12]
|
|
|
|
encrypted_message = ciphertext[12:]
|
2024-03-05 12:05:12 +00:00
|
|
|
chacha = ChaCha20Poly1305(derived_key)
|
|
|
|
message = chacha.decrypt(nonce, encrypted_message, None)
|
2024-03-16 17:11:11 +00:00
|
|
|
file_w = open(f"{filename}.dec", "wb")
|
2024-03-05 12:05:12 +00:00
|
|
|
file_w.write(message)
|
|
|
|
file_r.close()
|
|
|
|
file_w.close()
|
|
|
|
skey_file.close()
|
|
|
|
|
|
|
|
|
|
|
|
def mkpair(x, y):
|
2024-03-16 17:11:11 +00:00
|
|
|
"""produz uma byte-string contendo o tuplo '(x,y)' ('x' e 'y' são byte-strings)"""
|
2024-03-05 12:05:12 +00:00
|
|
|
len_x = len(x)
|
2024-03-16 17:11:11 +00:00
|
|
|
len_x_bytes = len_x.to_bytes(2, "little")
|
2024-03-05 12:05:12 +00:00
|
|
|
return len_x_bytes + x + y
|
|
|
|
|
2024-03-16 17:11:11 +00:00
|
|
|
|
2024-03-05 12:05:12 +00:00
|
|
|
def unpair(xy):
|
2024-03-16 17:11:11 +00:00
|
|
|
"""extrai componentes de um par codificado com 'mkpair'"""
|
|
|
|
len_x = int.from_bytes(xy[:2], "little")
|
|
|
|
x = xy[2 : len_x + 2]
|
|
|
|
y = xy[len_x + 2 :]
|
2024-03-05 12:05:12 +00:00
|
|
|
return x, y
|
|
|
|
|
2024-03-16 17:11:11 +00:00
|
|
|
|
2024-03-05 12:05:12 +00:00
|
|
|
def main():
|
|
|
|
parser = argparse.ArgumentParser(
|
|
|
|
description="Program to perform operations using ChaCha20 cipher on files",
|
|
|
|
)
|
|
|
|
|
|
|
|
subparsers = parser.add_subparsers(dest="operation", help="Operation to perform")
|
|
|
|
|
|
|
|
# Setup subcommand
|
2024-03-16 17:11:11 +00:00
|
|
|
setup_parser = subparsers.add_parser(
|
|
|
|
"setup", help="Setup diffie helman key pair for user"
|
|
|
|
)
|
2024-03-05 12:05:12 +00:00
|
|
|
setup_parser.add_argument("user", help="User for which to setup the key pair")
|
|
|
|
|
|
|
|
# Encrypt subcommand
|
|
|
|
enc_parser = subparsers.add_parser("enc", help="Encrypt a file")
|
|
|
|
enc_parser.add_argument("user", help="User for which to encrypt the file")
|
|
|
|
enc_parser.add_argument("file", help="File to encrypt")
|
|
|
|
|
|
|
|
# Decrypt subcommand
|
|
|
|
decrypt_parser = subparsers.add_parser("dec", help="Decrypt a file")
|
|
|
|
decrypt_parser.add_argument("user", help="Target user for the decryption")
|
|
|
|
decrypt_parser.add_argument("file", help="File to be decrypted")
|
|
|
|
|
|
|
|
args = parser.parse_args()
|
|
|
|
match args.operation:
|
|
|
|
case "setup":
|
|
|
|
user = args.user
|
|
|
|
setup(user)
|
|
|
|
case "enc":
|
|
|
|
user = args.user
|
|
|
|
file = args.file
|
2024-03-16 17:11:11 +00:00
|
|
|
encrypt(user, file)
|
2024-03-05 12:05:12 +00:00
|
|
|
case "dec":
|
|
|
|
user = args.user
|
|
|
|
file = args.file
|
2024-03-16 17:11:11 +00:00
|
|
|
decrypt(user, file)
|
|
|
|
|
2024-03-05 12:05:12 +00:00
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
main()
|