Merge branch 'main' of gon:Uni/CSI-ES-2324
This commit is contained in:
commit
eacfa5363f
23 changed files with 875 additions and 49 deletions
|
@ -1 +0,0 @@
|
|||
panda é fixe!!!
|
|
@ -1 +1 @@
|
|||
…[nÍ"[v©Õ·µ4ZÍ![n{Vƒ#<23>ÿì<C3BF>»
|
||||
›US9ÃhMé„(#c…™b¸ÎÙoe@]<5D>.Jµ?K.Óké<6B>|Da¡vz>Z:’‚¯"]
|
1
TPs/TP02/py/input.txt.enc.dec
Normal file
1
TPs/TP02/py/input.txt.enc.dec
Normal file
|
@ -0,0 +1 @@
|
|||
panda é fixe!!!
|
109
TPs/TP02/py/pbenc_aes_ctr.py
Normal file
109
TPs/TP02/py/pbenc_aes_ctr.py
Normal file
|
@ -0,0 +1,109 @@
|
|||
#!/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
|
||||
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=32,
|
||||
salt=salt,
|
||||
iterations=100000
|
||||
)
|
||||
|
||||
key = kdf.derive(password.encode('utf-8'))
|
||||
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)}")
|
||||
|
||||
|
||||
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:]
|
||||
|
||||
kdf = PBKDF2HMAC(
|
||||
algorithm=hashes.SHA256(),
|
||||
length=32,
|
||||
salt=salt,
|
||||
iterations=100000
|
||||
)
|
||||
|
||||
print(f"plaintext len : {len(ciphertext)}")
|
||||
print(f"iv len : {len(iv)}")
|
||||
print(f"salt len : {len(salt)}")
|
||||
|
||||
key = kdf.derive(password.encode('utf-8'))
|
||||
|
||||
# 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)
|
||||
|
||||
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()
|
8
TPs/TP03/Readme.md
Normal file
8
TPs/TP03/Readme.md
Normal file
|
@ -0,0 +1,8 @@
|
|||
# Questao 1
|
||||
|
||||
Ao utilizar o programa 'chacha20_int_attck.py' sobre um criptograma produzido por 'pbenc_chacha20_poly1305', the decrpyt function will raise the execption :
|
||||
- 'cryptography.exceptions.InvalidTag' – If the authentication tag doesn’t validate this exception will be raised. This will occur when the ciphertext has been changed, but will also occur when the key, nonce, or associated data are wrong.
|
||||
|
||||
We can try this by encrypting a message and then changing the ciphertext with the attack program:
|
||||
|
||||
![Failed Attack](https://github.com/uminho-mei-es/2324-G05/blob/main/TPs/TP03/attack_fail.png)
|
BIN
TPs/TP03/attack_fail.png
Normal file
BIN
TPs/TP03/attack_fail.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 21 KiB |
30
TPs/TP03/py/chacha20_int_attck.py
Normal file
30
TPs/TP03/py/chacha20_int_attck.py
Normal file
|
@ -0,0 +1,30 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
|
||||
def attack(fctxt, pos, plainAtPos, newPlainAtPos):
|
||||
f = open(fctxt,"rb")
|
||||
ciphertext = f.read()
|
||||
f.close()
|
||||
|
||||
plainAtPos = plainAtPos.encode()
|
||||
newPlainAtPos = newPlainAtPos.encode()
|
||||
txt_len = len(plainAtPos)
|
||||
diff = bytes([a ^ b for (a,b) in zip(plainAtPos,newPlainAtPos)])
|
||||
cipher_diff = bytes([a ^ b for (a,b) in zip(diff,ciphertext[pos:pos+txt_len])])
|
||||
|
||||
new_ciphertext = ciphertext[:pos] + cipher_diff + ciphertext[pos+txt_len:]
|
||||
|
||||
with open(fctxt+".attck","wb") as f:
|
||||
f.write(new_ciphertext)
|
||||
|
||||
def main():
|
||||
argv = sys.argv[1:]
|
||||
argc = len(argv)
|
||||
if argc < 3 or argc > 5:
|
||||
sys.exit("Needs 4 arguments <fctxt> <pos> <ptxtAtPos> <newPtxtAtPos>")
|
||||
|
||||
attack(argv[0],int(argv[1]),argv[2],argv[3])
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
128
TPs/TP03/py/pbenc_aes_ctr_hmac.py
Normal file
128
TPs/TP03/py/pbenc_aes_ctr_hmac.py
Normal file
|
@ -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()
|
76
TPs/TP03/py/pbenc_aes_gcm_hmac.py
Normal file
76
TPs/TP03/py/pbenc_aes_gcm_hmac.py
Normal file
|
@ -0,0 +1,76 @@
|
|||
import os
|
||||
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
|
||||
import argparse
|
||||
|
||||
def setup(key_file):
|
||||
key = AESGCM.generate_key(bit_length=128)
|
||||
with open(key_file, "wb") as f:
|
||||
f.write(key)
|
||||
|
||||
|
||||
def encrypt(input_file, key_file):
|
||||
with open(input_file, "rb") as f:
|
||||
plaintext = f.read()
|
||||
|
||||
with open(key_file, "rb") as f:
|
||||
key = f.read()
|
||||
|
||||
aad = b"authenticated but unencrypted data"
|
||||
aesgcm = AESGCM(key)
|
||||
nonce = os.urandom(12)
|
||||
|
||||
ct = aesgcm.encrypt(nonce, plaintext, aad)
|
||||
|
||||
with open(f"{input_file}.enc", "wb") as f:
|
||||
f.write(nonce)
|
||||
f.write(ct)
|
||||
|
||||
|
||||
def decrypt(input_file, key_file):
|
||||
with open(input_file, "rb") as f:
|
||||
nonce = f.read(12)
|
||||
ct = f.read()
|
||||
|
||||
with open(key_file, "rb") as f:
|
||||
key = f.read()
|
||||
|
||||
aad = b"authenticated but unencrypted data"
|
||||
aesgcm = AESGCM(key)
|
||||
pt = aesgcm.decrypt(nonce, ct, aad)
|
||||
|
||||
with open(f"{input_file}.dec", "wb") as f:
|
||||
f.write(pt)
|
||||
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Program to perform operations using AES-GCM 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()
|
||||
|
93
TPs/TP03/py/pbenc_chacha20_poly1305.py
Normal file
93
TPs/TP03/py/pbenc_chacha20_poly1305.py
Normal file
|
@ -0,0 +1,93 @@
|
|||
from cryptography.hazmat.primitives.ciphers.aead import ChaCha20Poly1305
|
||||
import argparse
|
||||
import os
|
||||
|
||||
|
||||
def setup(key_file):
|
||||
key = ChaCha20Poly1305.generate_key()
|
||||
with open(key_file, "wb") as f:
|
||||
f.write(key)
|
||||
|
||||
|
||||
def encrypt(input_file, key_file):
|
||||
with open(key_file, "rb") as f:
|
||||
key = f.read(32)
|
||||
|
||||
with open(input_file, "rb") as f:
|
||||
plaintext = f.read()
|
||||
|
||||
aad = b"authenticated but unencrypted data"
|
||||
nonce = os.urandom(12)
|
||||
|
||||
cipher = ChaCha20Poly1305(key)
|
||||
ciphertext = cipher.encrypt(nonce, plaintext, aad)
|
||||
|
||||
with open(f"{input_file}.enc", "wb") as f:
|
||||
f.write(nonce + ciphertext)
|
||||
|
||||
|
||||
|
||||
def decrypt(input_file, key_file):
|
||||
with open(key_file, "rb") as f:
|
||||
key = f.read(32)
|
||||
|
||||
with open(input_file, "rb") as f:
|
||||
input_bytes = f.read()
|
||||
|
||||
aad = b"authenticated but unencrypted data"
|
||||
nonce = input_bytes[:12]
|
||||
ciphertext = input_bytes[12:]
|
||||
|
||||
|
||||
cipher = ChaCha20Poly1305(key)
|
||||
try:
|
||||
plaintext = cipher.decrypt(nonce, ciphertext, aad)
|
||||
except Exception as e:
|
||||
print(f"Could not validate the authentication: {e}")
|
||||
return
|
||||
|
||||
|
||||
|
||||
with open(f"{input_file}.dec", "wb") as f:
|
||||
f.write(plaintext)
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Program to perform operations using Authenticated ChaCha20 cipher on files",
|
||||
)
|
||||
|
||||
subparsers = parser.add_subparsers(dest="operation", help="Operation to perform")
|
||||
|
||||
# Setup subcommand
|
||||
setup_parser = subparsers.add_parser("setup", help="Setup a key file")
|
||||
setup_parser.add_argument("fkey", help="File to contain the appropriate key for the ChaCha20 cipher")
|
||||
|
||||
# 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("fkey", help="File containing the key for the ChaCha20 cipher")
|
||||
|
||||
# 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("fkey", help="File containing the key for the ChaCha20 cipher")
|
||||
|
||||
args = parser.parse_args()
|
||||
match args.operation:
|
||||
case "setup":
|
||||
key_file = args.fkey
|
||||
setup(key_file)
|
||||
case "enc":
|
||||
input_file = args.fich
|
||||
key_file = args.fkey
|
||||
encrypt(input_file,key_file)
|
||||
case "dec":
|
||||
input_file = args.fich
|
||||
key_file = args.fkey
|
||||
decrypt(input_file,key_file)
|
||||
case "help":
|
||||
parser.print_help()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
1
TPs/TP03/py/plaintext.txt
Normal file
1
TPs/TP03/py/plaintext.txt
Normal file
|
@ -0,0 +1 @@
|
|||
not very safe
|
BIN
TPs/TP03/py/plaintext.txt.enc
Normal file
BIN
TPs/TP03/py/plaintext.txt.enc
Normal file
Binary file not shown.
1
TPs/TP03/py/plaintext.txt.enc.dec
Normal file
1
TPs/TP03/py/plaintext.txt.enc.dec
Normal file
|
@ -0,0 +1 @@
|
|||
not very safe
|
|
@ -1,11 +1,11 @@
|
|||
import argparse
|
||||
import os
|
||||
|
||||
import cryptography.hazmat.primitives.serialization as serialization
|
||||
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
|
||||
import cryptography.hazmat.primitives.serialization as serialization
|
||||
from cryptography.hazmat.primitives.serialization import (
|
||||
Encoding,
|
||||
NoEncryption,
|
||||
|
@ -13,106 +13,125 @@ from cryptography.hazmat.primitives.serialization import (
|
|||
PublicFormat,
|
||||
)
|
||||
|
||||
p = 0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3DC2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F83655D23DCA3AD961C62F356208552BB9ED529077096966D670C354E4ABC9804F1746C08CA18217C32905E462E36CE3BE39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9DE2BCBF6955817183995497CEA956AE515D2261898FA051015728E5A8AACAA68FFFFFFFFFFFFFFFF
|
||||
g = 2
|
||||
params = dh.DHParameterNumbers(p, g).parameters()
|
||||
|
||||
def setup(user):
|
||||
parameters = dh.generate_parameters(generator=2, key_size=512)
|
||||
private_key = parameters.generate_private_key()
|
||||
private_key = params.generate_private_key()
|
||||
public_key = private_key.public_key()
|
||||
|
||||
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))
|
||||
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
|
||||
)
|
||||
)
|
||||
skey.close()
|
||||
pkey.close()
|
||||
|
||||
|
||||
def encrypt(user,filename):
|
||||
peer_pkey_file = open(f"{user}.pk", 'rb')
|
||||
def encrypt(user, filename):
|
||||
peer_pkey_file = open(f"{user}.pk", "rb")
|
||||
if peer_pkey_file is None:
|
||||
print(f"No public key found for {user}")
|
||||
return
|
||||
|
||||
file_r = open(filename, 'rb')
|
||||
file_r = open(filename, "rb")
|
||||
if file_r is None:
|
||||
print(f"File {filename} not found")
|
||||
return
|
||||
|
||||
# FIX: Add try
|
||||
parameters = dh.generate_parameters(generator=2, key_size=512)
|
||||
skey = parameters.generate_private_key()
|
||||
peer_pkey= serialization.load_pem_public_key(peer_pkey_file.read())
|
||||
derived_key = None
|
||||
if isinstance(peer_pkey, dh.DHPublicKey):
|
||||
shared_key = skey.exchange(peer_pkey)
|
||||
derived_key = HKDF(algorithm=hashes.SHA256(), length=32, salt=None, info=b'handshake data').derive(shared_key)
|
||||
else:
|
||||
|
||||
skey = params.generate_private_key()
|
||||
peer_pkey = serialization.load_pem_public_key(peer_pkey_file.read())
|
||||
if not isinstance(peer_pkey, dh.DHPublicKey):
|
||||
print("Error: Invalid key type")
|
||||
return
|
||||
|
||||
shared_key = skey.exchange(peer_pkey)
|
||||
derived_key = HKDF(
|
||||
algorithm=hashes.SHA256(), length=32, salt=None, info=None
|
||||
).derive(shared_key)
|
||||
|
||||
message = file_r.read()
|
||||
chacha = ChaCha20Poly1305(derived_key)
|
||||
nonce = os.urandom(12)
|
||||
ciphertext = chacha.encrypt(nonce, message, None)
|
||||
file_w = open(f"{filename}.enc", 'wb')
|
||||
nonce_ciphertext = mkpair(nonce, ciphertext)
|
||||
to_send = mkpair(peer_pkey.public_bytes(Encoding.PEM, PublicFormat.SubjectPublicKeyInfo), nonce_ciphertext)
|
||||
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)
|
||||
file_w.write(to_send)
|
||||
|
||||
file_r.close()
|
||||
file_w.close()
|
||||
skey_file.close()
|
||||
peer_pkey_file.close()
|
||||
|
||||
|
||||
def decrypt(user,filename):
|
||||
skey_file = open(f"{user}.sk", 'rb')
|
||||
def decrypt(user, filename):
|
||||
skey_file = open(f"{user}.sk", "rb")
|
||||
if skey_file is None:
|
||||
print(f"No private key found for {user}")
|
||||
return
|
||||
|
||||
file_r = open(filename, 'rb')
|
||||
file_r = open(filename, "rb")
|
||||
if file_r is None:
|
||||
print(f"File {filename} not found")
|
||||
return
|
||||
|
||||
message_bytes = file_r.read()
|
||||
peer_pkey_bytes, ciphertext = unpair(message_bytes)
|
||||
# FIX: Add try
|
||||
|
||||
skey = serialization.load_pem_private_key(skey_file.read(), None)
|
||||
peer_pkey = serialization.load_pem_public_key(peer_pkey_bytes)
|
||||
derived_key = None
|
||||
if isinstance(skey, dh.DHPrivateKey) and isinstance(peer_pkey, dh.DHPublicKey):
|
||||
shared_key = skey.exchange(peer_pkey)
|
||||
derived_key = HKDF(algorithm=hashes.SHA256(), length=32, salt=None, info=b'handshake data').derive(shared_key)
|
||||
else:
|
||||
peer_pkey = serialization.load_der_public_key(peer_pkey_bytes)
|
||||
if not isinstance(skey, dh.DHPrivateKey) or not isinstance(
|
||||
peer_pkey, dh.DHPublicKey
|
||||
):
|
||||
print("Error: Invalid key type")
|
||||
return
|
||||
|
||||
nonce, encrypted_message = unpair(ciphertext)
|
||||
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:]
|
||||
chacha = ChaCha20Poly1305(derived_key)
|
||||
message = chacha.decrypt(nonce, encrypted_message, None)
|
||||
file_w = open(f"{filename}.decrypt", 'wb')
|
||||
file_w = open(f"{filename}.dec", "wb")
|
||||
file_w.write(message)
|
||||
file_r.close()
|
||||
file_w.close()
|
||||
skey_file.close()
|
||||
|
||||
|
||||
|
||||
|
||||
def mkpair(x, y):
|
||||
""" produz uma byte-string contendo o tuplo '(x,y)' ('x' e 'y' são byte-strings) """
|
||||
"""produz uma byte-string contendo o tuplo '(x,y)' ('x' e 'y' são byte-strings)"""
|
||||
len_x = len(x)
|
||||
len_x_bytes = len_x.to_bytes(2, 'little')
|
||||
len_x_bytes = len_x.to_bytes(2, "little")
|
||||
return len_x_bytes + x + y
|
||||
|
||||
|
||||
def unpair(xy):
|
||||
""" 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:]
|
||||
"""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 :]
|
||||
return x, y
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Program to perform operations using ChaCha20 cipher on files",
|
||||
|
@ -121,7 +140,9 @@ def main():
|
|||
subparsers = parser.add_subparsers(dest="operation", help="Operation to perform")
|
||||
|
||||
# Setup subcommand
|
||||
setup_parser = subparsers.add_parser("setup", help="Setup diffie helman key pair for user")
|
||||
setup_parser = subparsers.add_parser(
|
||||
"setup", help="Setup diffie helman key pair for user"
|
||||
)
|
||||
setup_parser.add_argument("user", help="User for which to setup the key pair")
|
||||
|
||||
# Encrypt subcommand
|
||||
|
@ -142,11 +163,12 @@ def main():
|
|||
case "enc":
|
||||
user = args.user
|
||||
file = args.file
|
||||
encrypt(user,file)
|
||||
encrypt(user, file)
|
||||
case "dec":
|
||||
user = args.user
|
||||
file = args.file
|
||||
decrypt(user,file)
|
||||
decrypt(user, file)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
|
8
TPs/TP04/input
Normal file
8
TPs/TP04/input
Normal file
|
@ -0,0 +1,8 @@
|
|||
As armas e os barões assinalados,
|
||||
Que da ocidental praia Lusitana,
|
||||
Por mares nunca de antes navegados,
|
||||
Passaram ainda além da Taprobana,
|
||||
Em perigos e guerras esforçados,
|
||||
Mais do que prometia a força humana,
|
||||
E entre gente remota edificaram
|
||||
Novo Reino, que tanto sublimaram;
|
23
TPs/TP05/ALICE.crt
Normal file
23
TPs/TP05/ALICE.crt
Normal file
|
@ -0,0 +1,23 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIDyzCCArOgAwIBAgIUCPhaX8nmoqG8snFrfNe+saiJ8CswDQYJKoZIhvcNAQEL
|
||||
BQAwgYoxCzAJBgNVBAYTAlBUMQ4wDAYDVQQIDAVNaW5obzEOMAwGA1UEBwwFQnJh
|
||||
Z2ExHjAcBgNVBAoMFVVuaXZlcnNpZGFkZSBkbyBNaW5obzENMAsGA1UECwwETVNH
|
||||
UzEfMB0GA1UEAwwWRW50aWRhZGUgQ2VydGlmaWNhZG9yYTELMAkGA1UEQQwCRUMw
|
||||
HhcNMjQwMzA4MjEzOTM4WhcNMjQwNjE2MjEzOTM4WjB9MQswCQYDVQQGEwJQVDEO
|
||||
MAwGA1UECAwFTWluaG8xDjAMBgNVBAcMBUJyYWdhMR4wHAYDVQQKDBVVbml2ZXJz
|
||||
aWRhZGUgZG8gTWluaG8xDTALBgNVBAsMBE1TR1MxDjAMBgNVBAMMBUFMSUNFMQ8w
|
||||
DQYDVQRBDAZDTElFTlQwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6
|
||||
dLkrGhqif05lmhTWKbRbWRtMpAqTlPs1uNTg4h0eXhvGGpWQBYiQ2lekreTtXB4U
|
||||
vJ0EjDxcTQ68SodEvoLYlotPtnDlLwP5yAeoRy96lyFwbgWMjWQY/ILCY7CtLYmo
|
||||
9ZA2ySL/6K1agDTE5Y+eRqO2WKu1kYL1O66zUs3dA+EsbWWGg6/sRvUWE+SuZV7O
|
||||
OMXKtEszeqbeD0E10O7b+wBx5CvomZb4GYDQMiZkhcP7Gg4pLakgQ4EWvM6Jqmun
|
||||
4DdMiutKxD5L2Q+MNhkYh8+1CsVg9z/MAd6OheSYyMKQD4M0MLm2EY35g+dHijL0
|
||||
S+XhRGikr0xI9jSDmFMnAgMBAAGjNTAzMAwGA1UdEwEB/wQCMAAwDgYDVR0PAQH/
|
||||
BAQDAgbAMBMGA1UdJQQMMAoGCCsGAQUFBwMCMA0GCSqGSIb3DQEBCwUAA4IBAQA8
|
||||
MHI0Ss76IPWq3fEODzLdfAQ86khHNZZ+KQEnOOb8h5UEVSciwiilISxTHltPmNPX
|
||||
7YRvBvY3LFfURPQwV0UPL7FErORXMny8epd3W4/D/sL6HOL8n/5uq442jW8rPnaA
|
||||
wFUcoLXBRxX+sTFXQisqGewpEzUpyf2MGJoneOcB3xQteQv7K0Sp3rop0LmlEV74
|
||||
/ZP6cMjW4MjxLn71J6y3tJ5FP4rTpbUmefnD1F8YVsuNNb0kj1CUsx5YMIFp4PjQ
|
||||
sruJXrAGTlqa8YuUwwjX7v6wvMv8Di95TIMgTm7bwonsjO7lmQsO261zGySfa0hF
|
||||
jMUsOA7r+H44aIyWAeNb
|
||||
-----END CERTIFICATE-----
|
30
TPs/TP05/ALICE.key
Normal file
30
TPs/TP05/ALICE.key
Normal file
|
@ -0,0 +1,30 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
Proc-Type: 4,ENCRYPTED
|
||||
DEK-Info: AES-256-CBC,5614AC7BE85EAABC3789637A31321B7F
|
||||
|
||||
HxiSg2g4b4agu05VuCQdKdiAvh7fQaBsPVYvvuGvGa3szsol9RBwdEviaOE9hIWz
|
||||
vKIJghMVEz6C6fWwHoTv6qegTT0uMK6+Z7XN6Ma7GVABE9JDCc7AvAP8or1T0+NN
|
||||
xh3iztDQvPu+EfLD0jaZDP2pmz5ymq/ibeHIf8hutrdF9dkeNuwtRhKJ9vLv+S5c
|
||||
mJ4etKwDK1un2lt3wQpWSYQoqSKBz1B4tJT+NL6Nz0ZVW3nEcjNpUdLhBK+yBusM
|
||||
s7LwiEoqG/1VxDx8gPweOVHDIeURjaOR91NOSdjwwpwOuYOWdhSkfEa/fGSVol9u
|
||||
QMLEtNN1SRAWvakAmwhNrPNlSRRcFjn2nvO4AS1dRxZuwZEkYuiWeGONGFD6S4lK
|
||||
rG1rvwYlI28p9+VKVDi7XsW+HUFJ1tG2qYC5BgAOav3S9HIFhjhvYn3sOoM/0vxt
|
||||
cSr7r94v88UFhvKJZUSLHZn/yCiSX069yYEdY0grt8ZJRhRpN5G7o2T5ejQzGj8l
|
||||
U8fyDr89DlPYEQn/2eMgxIPcSghxAQqYF5MHvnZ6/CjNMKgQFc8ymGiq/HXveTE9
|
||||
91WtuH4NQZYsXanN6ZtUQm3a2h8lJD8x/H8LDQPFtwMfHMQP1WK8FlaiKiT7242Q
|
||||
Gu98ZwEyRBY1qO9rVYX0nbsXMxLAMefdtZlAgKovl1S5xj5r6LcIvFDsVqN5K98h
|
||||
IK2aoOG023wYJ4eNkjL4dBJiwZ5+RUg3sj4wkNzidcd0cucioj7mbTl4SWJilMI+
|
||||
fSXzvJADEI4qyjZbPb3KNGqeX0tvF7bkRHwZk91b1ihvvWsK1Lc6j++aDzOraqxS
|
||||
yVT5IuBy/kd/L+qps3UipneWuUA9NmqUgtIvp20W5R8G9aAfZFFaK0uVPbOYSLum
|
||||
WNIfBZDZN0SnuiiVoLCaMkFRzK/5GL7UTKKr5JQxS4KW+1VDrdUc8NqzMBhmFwmX
|
||||
fcGZNOj7bNkckooFIIEtUVL1r2/wX8t3hRY9M4S+MYuOR6Vr2yuajEJPodFD1Hom
|
||||
BMQDrkicVUJ9yP6QL/UO7a+QNZ2wdaIjfG6zOZkf0RQ/JxJtCN5jaziV6LNE/SfX
|
||||
UPeh/EdxVqU9hcdcZw6UsLCrVBpRJCwe5UhVHzrsShFW5DqdNBB0Blfxy/9X3IP4
|
||||
tyOeLqRj7jgHrVgd11rccOiB7vyydUL8J+ilmMbFDlk8lfJYvDked7OaQ5ca3/q9
|
||||
djkJfVBzGX4s7leJKg8286FBhceKgWhlyqrmXWe9WuBZNj8M94RvoZOCzrlw7WgF
|
||||
SFf2kSNmh0yXFtsYlNO5skmJo0pgZc5qDQnkHlfXq+Hf89a62L+igsgiy5F1cShx
|
||||
lCiFa/fkLUe3/+7kJg9XR35XqbLdFS0OLTMmLyghsL+p1Iab28xvajc2jyb7ftGe
|
||||
CBDD0KT3FvEYSFiE8o0JVYgiWav5NJOML7kW0fq6/ZUm1j9oXxWBpZx8rlVs1jTK
|
||||
16vkatrUENs9xaWmDsYvuvBmOnSFFzaCFcZ/mE6ixUUim7qKZWfGGwcTs6e1UmlW
|
||||
twsdWhQEVdZF9mF3NdXqUGqWOHV5RJCHyx3sGzps+pb3DiIgp1Xu6Y8R1057sGKY
|
||||
-----END RSA PRIVATE KEY-----
|
23
TPs/TP05/BOB.crt
Normal file
23
TPs/TP05/BOB.crt
Normal file
|
@ -0,0 +1,23 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIIDyTCCArGgAwIBAgIUX4OZN6EvuWMWUD7EWgYwomRa2JswDQYJKoZIhvcNAQEL
|
||||
BQAwgYoxCzAJBgNVBAYTAlBUMQ4wDAYDVQQIDAVNaW5obzEOMAwGA1UEBwwFQnJh
|
||||
Z2ExHjAcBgNVBAoMFVVuaXZlcnNpZGFkZSBkbyBNaW5obzENMAsGA1UECwwETVNH
|
||||
UzEfMB0GA1UEAwwWRW50aWRhZGUgQ2VydGlmaWNhZG9yYTELMAkGA1UEQQwCRUMw
|
||||
HhcNMjQwMzA4MjEzOTM3WhcNMjQwNjE2MjEzOTM3WjB7MQswCQYDVQQGEwJQVDEO
|
||||
MAwGA1UECAwFTWluaG8xDjAMBgNVBAcMBUJyYWdhMR4wHAYDVQQKDBVVbml2ZXJz
|
||||
aWRhZGUgZG8gTWluaG8xDTALBgNVBAsMBE1TR1MxDDAKBgNVBAMMA0JPQjEPMA0G
|
||||
A1UEQQwGU0VSVkVSMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAljc+
|
||||
6jnrgaXhkNqTTCfi4i55Poxmj2AM3xVxlZwron1oAFFx7Uw1RoqE+bKLk3chZPTu
|
||||
I6Va4Ch9UF1lHl3YKf7+Z0I68JC/Z4mnZGnTYOZ2b9V5WqIyDWFcQlGhKfEQlPZg
|
||||
BJYZNlrnmePTJjUkniG3+t3u9rSvm/5copv+/Bp5jb9lXZAHVoYNulVY9Th5aRQZ
|
||||
8PB2bu+k3bsz/rGtF3TRpuMPu1oGoBUq6OVVWWZ6279DlKwycq+Yxl+0dd9dZD80
|
||||
X+yTyzTd8pkWwRTEtQ3cy4z+V5NsBlw7JBVOPVNz0FtRrUctZmgvW/S87yrUDOQ5
|
||||
eBXVsZwrZm6tmtHhVQIDAQABozUwMzAMBgNVHRMBAf8EAjAAMA4GA1UdDwEB/wQE
|
||||
AwIGwDATBgNVHSUEDDAKBggrBgEFBQcDATANBgkqhkiG9w0BAQsFAAOCAQEAay7j
|
||||
May5ZrUh0O/XC/n/+NpxrxtUOWy+9ioGa/EJcuPRQJbyHTBkF7jhdY5WwgEMe2e/
|
||||
qJvM9sDfx0EL6fc6S3Dku6LINvsFKGOp3ljYt5JZZGXFiNshCEXjJ5l061jWWenn
|
||||
bAo2ef8OiO0LnfNqAZLqpRD0nI+AdEdqU/O5e792IMzPVNqDVxccYGvHron63WzB
|
||||
/32gqBBby5gU0USTXffwCLlauv51wKAXCwkp7uGvU0adKp2vL9rHo5OY67N4FzaA
|
||||
2a3/SMX5YMy0fvMB5Ao8mR2Y+jmQ8Lwb1xIMBx43NOc8exZtfPoHWH6WMKNyYx4i
|
||||
ydtkrMURnOOdXcBpAQ==
|
||||
-----END CERTIFICATE-----
|
30
TPs/TP05/BOB.key
Normal file
30
TPs/TP05/BOB.key
Normal file
|
@ -0,0 +1,30 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
Proc-Type: 4,ENCRYPTED
|
||||
DEK-Info: AES-256-CBC,003D12E5CDCB087CCE0B3C7E89D2D651
|
||||
|
||||
lQirD96D/XjbbJOlZUzBQDqSmKeKICwrawMHddX6t34N414dcGuLaFPVDdvW5Aml
|
||||
W6gI43ovOLJQzF+thtHRflANehPE7ObHM+oRJn7+yyzHOv7zvFlm+8GBqRSb6H8m
|
||||
iVoupPPlFjcUfiy/6DNdRWU3iL2iIGFSwhbboZANrXMTBT+p7GGoaRTxdtwTd3hd
|
||||
kj2U73ehg9TeGSH/ftXr0dOGKIBZLXeQlIpiPTy86yn93fZ28E3EmjgOCWJXblTa
|
||||
Plv6xuLY/Y8vZUjjhoJto9IzeA5to4aI30gW90JkxaTnedk9ZL1skjMUKHCrl2Mi
|
||||
loKU0AI7wJrVlEl7ea3xZ52U+5Qe/KmkZL8GLo5MsB9Fc0jbpRhbsLrrocRW8qgy
|
||||
KYROLFb5l0s3N2WUN3zBmEO8vjm47mbZblGpPbHGpnVEvuqppNwBoWtUCiq9iptU
|
||||
0BWWcQ68QUdl0YDp+Mutl3/28ONJo9UYtBFo55PLTNG8tp9qz0Bh/i2hqoCIFoqD
|
||||
k0rVkGVaXU54IqQLZdF6yhWsKlUyehX8hy1SgukLzgpzwfHkW9DqlztKrmlcXPYl
|
||||
bHCAaQhimwufRrqSD7nq2Pn0Mq2qtdp6rn+jS9n6Spls1OPNZx4ev5zxga3v1NfA
|
||||
nIdXeevmP5VZlkIlZmkcoeMMPBKl1f4hzDL14kdA5kTBRbjasJQce4K6bqrueOxP
|
||||
qpsTGE9KF64NcD/8a2MQhnnpv7TTIFKy1eLrdrojhHUPnDWlVGJ0ihGpvn2AjmJ9
|
||||
YIFkxXhnegwbUYzabWFXk5fuX8Z2rXPXzpaKGfDTrEvpw0katlMZ/k9cfRJa0obb
|
||||
W0cwUwkgv7kH8DDRpnU2arNLtkQMviZKhNkVudWh7dD9wQwFLu46yyrocz9qbCHF
|
||||
vRA0IU5wwrHs0VxETEGm9qnfGJLHbSYaj57nybX2SI2tpwyqvdWEzCIuEvJ155Yc
|
||||
8u4HijBHI2ysEnoUycDJhZSfW/nl+R892Ppf5t29YVIgdM0yUV2nVA2D+e/buDnR
|
||||
B6ZKACBmNQIQIx9RsF3Q+EQipxUE82at48wWbTVl5iWbWJUbWK+Yoj9M1NDQZZjO
|
||||
7ytGzg9WkmuG/6HxuKJJl+0/zdn3+9BvgBGBqjEXNHTaG7OSMrIiwOCFmWzFKguh
|
||||
YLkh26+JuedrRmx1KoubR1q+gc+VDBD8owQaFz00O8virrqFC00zrC0Q0NtiEvCs
|
||||
24qkFHsvlvEwOwVAS0xL/rORmZ2GoW7hTVYKth6iOfLjJo9Df/UxNrdqFmmjtI3J
|
||||
G67ao4w93wiJnRwmgPyuvo0i5UKJqxkcwVkEzVuvYlLhgXj9IXp55atFNQ0h8NLr
|
||||
aoaHPGX/B/Fj7qisIa3925yXHeLBRDtUFsp8koY/GmY2BPuIrc+utwuJykb02puW
|
||||
+Z+FcWNeCJFxvGJgH1mVUGpcbbO4VwpuT2PoxBIeTca5ujfwJyPEBiXVgB8rfKxV
|
||||
OjzrHdGIlz3aaLX1zGmiffyEQdWI1RHTk9VwF2K6Yxl+/ARiFqju89vzHXRX7B6s
|
||||
1CqApD0x5dHmuyqywAX3KE7qyvgQKabL4K33OcLyr1G5i6V0dLKfbseQWzVImpK9
|
||||
-----END RSA PRIVATE KEY-----
|
23
TPs/TP05/EC.crt
Normal file
23
TPs/TP05/EC.crt
Normal file
|
@ -0,0 +1,23 @@
|
|||
-----BEGIN CERTIFICATE-----
|
||||
MIID3DCCAsSgAwIBAgIUTH2fOhbGuLcGi6Dy3NlUYspUr/IwDQYJKoZIhvcNAQEL
|
||||
BQAwgYoxCzAJBgNVBAYTAlBUMQ4wDAYDVQQIDAVNaW5obzEOMAwGA1UEBwwFQnJh
|
||||
Z2ExHjAcBgNVBAoMFVVuaXZlcnNpZGFkZSBkbyBNaW5obzENMAsGA1UECwwETVNH
|
||||
UzEfMB0GA1UEAwwWRW50aWRhZGUgQ2VydGlmaWNhZG9yYTELMAkGA1UEQQwCRUMw
|
||||
HhcNMjQwMzA4MjEzOTMxWhcNMjQwNjE2MjEzOTMxWjCBijELMAkGA1UEBhMCUFQx
|
||||
DjAMBgNVBAgMBU1pbmhvMQ4wDAYDVQQHDAVCcmFnYTEeMBwGA1UECgwVVW5pdmVy
|
||||
c2lkYWRlIGRvIE1pbmhvMQ0wCwYDVQQLDARNU0dTMR8wHQYDVQQDDBZFbnRpZGFk
|
||||
ZSBDZXJ0aWZpY2Fkb3JhMQswCQYDVQRBDAJFQzCCASIwDQYJKoZIhvcNAQEBBQAD
|
||||
ggEPADCCAQoCggEBAKL4muNmXblWtpkGx7/Yfd9MnF++dwVlw835qnzCftMpVtAd
|
||||
QvyTryrGGNElGQmUNhihnz9zAHQPMFaUt4M3Xx8Wfilts1jzjEpqA3dikWQNkwC8
|
||||
ao8JA6v3n8rX0mWFA4Ggee6LpoiAu9YksAr8VYqSxH/cXg5SYybraxwW/GaFkfp9
|
||||
brMM7X1rGNeTsWpPpHNUTuMDqdBsaTRw9LAfAg8bDB3JKaIuX78MxH2C2UrCuf0s
|
||||
WyoEl6mJrDHXqxJ+mFntTLizHzEN3M8AZ/vrz/14avfcuih4i4LxFw/MlvTbWlLm
|
||||
+gmgOBKmsx7JJ/O9VHg3AsBvG2XtmVc13XA3h4cCAwEAAaM4MDYwDwYDVR0TAQH/
|
||||
BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwEwYDVR0lBAwwCgYIKwYBBQUHAwIwDQYJ
|
||||
KoZIhvcNAQELBQADggEBAJCvNfm9zA8Dnk+j5qfzrMTbSbKyNSUR4Ic02Ji+Ew1h
|
||||
BsydcPMS62+yRH01I+AVLO1QX1dSJUoifQtHDbIOC2HkVaYq7mOyKPWVYkqRQT5u
|
||||
cwON88wpXqKq50ngT+0+yQMGNdT5+ON2DsL/I70O9WJ/ZE8bNPs+uYkZISvui+FW
|
||||
n0+iuuXIvB7wtdlVAB1RGvrkvi71UfXUPQXDX92rQj63oyrXuTtEDvsjWidMzPoN
|
||||
7H5VkAY4t9LTWJhosuNvKZbeHKNiZdUUiz53zTACc6WTN8k7nUyW/m1SgsYwAt1m
|
||||
AgfXmmTQqOeGFTkt5K3ElmCs3XD2ZMUnRf7w4jwb+ms=
|
||||
-----END CERTIFICATE-----
|
BIN
TPs/TP05/Images/Q1.png
Normal file
BIN
TPs/TP05/Images/Q1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
56
TPs/TP05/Readme.md
Normal file
56
TPs/TP05/Readme.md
Normal file
|
@ -0,0 +1,56 @@
|
|||
# Respostas das Questões
|
||||
## Q1
|
||||
|
||||
Para verificar que as chaves fornecidas constituem um par RSA valido, podemos extrair a chave publica do certificado e da chave privada (separadamente) e verificar se a chave publica é igual à chave publica extraída da chave privada.
|
||||
|
||||
![Verificação da chave publica](https://github.com/uminho-mei-es/2324-G05/blob/main/TPs/TP05/Images/Q1.png)
|
||||
|
||||
## Q2
|
||||
Utilizando o comando `openssl x509 -text -noout -in xxx.cert` podemos visualizar o conteúdo do certificado. Correndo o comando para o certificado `ALICE.crt` obtemos o seguinte resultado:
|
||||
|
||||
```bash
|
||||
|
||||
Certificate:
|
||||
Data:
|
||||
Version: 3 (0x2)
|
||||
Serial Number:
|
||||
08:f8:5a:5f:c9:e6:a2:a1:bc:b2:71:6b:7c:d7:be:b1:a8:89:f0:2b
|
||||
Signature Algorithm: sha256WithRSAEncryption
|
||||
Issuer: C = PT, ST = Minho, L = Braga, O = Universidade do Minho, OU = MSGS, CN = Entidade Certificadora, pseudonym = EC
|
||||
Validity
|
||||
Not Before: Mar 8 21:39:38 2024 GMT
|
||||
Not After : Jun 16 21:39:38 2024 GMT
|
||||
Subject: C = PT, ST = Minho, L = Braga, O = Universidade do Minho, OU = MSGS, CN = ALICE, pseudonym = CLIENT
|
||||
Subject Public Key Info:
|
||||
Public Key Algorithm: rsaEncryption
|
||||
Public-Key: (2048 bit)
|
||||
...
|
||||
X509v3 extensions:
|
||||
X509v3 Basic Constraints: critical
|
||||
CA:FALSE
|
||||
X509v3 Key Usage: critical
|
||||
Digital Signature, Non Repudiation
|
||||
X509v3 Extended Key Usage:
|
||||
TLS Web Client Authentication
|
||||
Signature Algorithm: sha256WithRSAEncryption
|
||||
Signature Value:
|
||||
...
|
||||
```
|
||||
Neste certificado, os campos importantes incluem:
|
||||
- **Serial Number**: Identificador único do certificado.
|
||||
- **Validity**: Indica o período durante o qual o certificado é válido.
|
||||
- **Subject**: Informações sobre a entidade a quem o certificado é emitido.
|
||||
- **Subject Public Key Info**: Detalhes sobre a chave pública, incluindo o algoritmo e o tamanho.
|
||||
- **X509v3 extensions**: Contém informações adicionais, como restrições básicas, uso de chaves e uso de chaves estendido.
|
||||
- **Signature Algorithm**: Algoritmo usado para assinar o certificado.
|
||||
- **Signature Value**: O valor de assinatura real que garante a integridade do certificado.
|
||||
|
||||
|
||||
## Q3
|
||||
|
||||
Para provocar erros do tipo de validação do certificado, podemos alterar o certificado de várias maneiras, como:
|
||||
- Alterar a data de validade para uma data anterior à data atual.
|
||||
- Alterar o nome do emissor ou do sujeito.
|
||||
- Alterar a chave pública ou privada.
|
||||
|
||||
Para provocar erros na validação da assinatura, podemos alterar a assinatura do certificado, o que invalidará a assinatura e resultará em um erro de validação.
|
165
TPs/TP05/sig_fich.py
Normal file
165
TPs/TP05/sig_fich.py
Normal file
|
@ -0,0 +1,165 @@
|
|||
import os
|
||||
import sys
|
||||
from cryptography.hazmat.primitives import serialization
|
||||
from cryptography.hazmat.primitives.asymmetric import padding
|
||||
from cryptography.hazmat.primitives import hashes
|
||||
from cryptography.hazmat.backends import default_backend
|
||||
from cryptography import x509
|
||||
from cryptography.x509.oid import NameOID
|
||||
from cryptography.exceptions import InvalidSignature
|
||||
import argparse
|
||||
import datetime
|
||||
|
||||
def mkpair(x, y):
|
||||
""" produz uma byte-string contendo o tuplo '(x,y)' ('x' e 'y' são byte-strings) """
|
||||
len_x = len(x)
|
||||
len_x_bytes = len_x.to_bytes(2, 'little')
|
||||
return len_x_bytes + x + y
|
||||
|
||||
def unpair(xy):
|
||||
""" 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:]
|
||||
return x, y
|
||||
|
||||
def cert_load(fname):
|
||||
""" lê certificado de ficheiro """
|
||||
with open(fname, "rb") as fcert:
|
||||
cert = x509.load_pem_x509_certificate(fcert.read())
|
||||
return cert
|
||||
|
||||
def cert_validtime(cert, now=None):
|
||||
""" valida que 'now' se encontra no período
|
||||
de validade do certificado. """
|
||||
if now is None:
|
||||
now = datetime.datetime.now(tz=datetime.timezone.utc)
|
||||
if now < cert.not_valid_before_utc or now > cert.not_valid_after_utc:
|
||||
raise x509.verification.VerificationError("Certificate is not valid at this time")
|
||||
|
||||
def cert_validsubject(cert, attrs=[]):
|
||||
""" verifica atributos do campo 'subject'. 'attrs'
|
||||
é uma lista de pares '(attr,value)' que condiciona
|
||||
os valores de 'attr' a 'value'. """
|
||||
print(cert.subject)
|
||||
for attr in attrs:
|
||||
if cert.subject.get_attributes_for_oid(attr[0])[0].value != attr[1]:
|
||||
raise x509.verification.VerificationError("Certificate subject does not match expected value")
|
||||
|
||||
def cert_validexts(cert, policy=[]):
|
||||
""" valida extensões do certificado. 'policy' é uma lista de pares '(ext,pred)' onde 'ext' é o OID de uma extensão e 'pred'
|
||||
o predicado responsável por verificar o conteúdo dessa extensão. """
|
||||
for check in policy:
|
||||
ext = cert.extensions.get_extension_for_oid(check[0]).value
|
||||
if not check[1](ext):
|
||||
raise x509.verification.VerificationError("Certificate extensions does not match expected value")
|
||||
|
||||
def valida_cert(cert, ca_cert, user):
|
||||
try:
|
||||
ca_cert.public_key().verify(
|
||||
cert.signature,
|
||||
cert.tbs_certificate_bytes,
|
||||
padding.PKCS1v15(),
|
||||
cert.signature_hash_algorithm
|
||||
)
|
||||
except InvalidSignature:
|
||||
raise x509.verification.VerificationError("Certificate signature is invalid")
|
||||
|
||||
cert_validtime(cert)
|
||||
|
||||
cert_validsubject(cert, [(NameOID.COMMON_NAME, user)])
|
||||
|
||||
|
||||
|
||||
"""
|
||||
sign <user> <fich> -- em que assina o conteúdo de <fich> usando a chave privada armazenada em <user>.key.
|
||||
Deve produzir o ficheiro <fich>.sig contendo o par composto pela assinatura e certificado do assinante;
|
||||
"""
|
||||
def sign(user, filename):
|
||||
|
||||
with open(user + ".key", "rb") as key_file:
|
||||
private_key = serialization.load_pem_private_key(key_file.read(), password=b'1234', backend=default_backend())
|
||||
|
||||
user_cert = cert_load(user + ".crt")
|
||||
|
||||
with open(filename, "rb") as file:
|
||||
data_to_sign = file.read()
|
||||
|
||||
|
||||
|
||||
signature = private_key.sign(data_to_sign,
|
||||
padding.PSS(mgf=padding.MGF1(hashes.SHA256()),
|
||||
salt_length=padding.PSS.MAX_LENGTH),
|
||||
hashes.SHA256())
|
||||
|
||||
|
||||
signature_and_cert = mkpair(signature, user_cert.public_bytes(serialization.Encoding.PEM))
|
||||
|
||||
with open(filename + ".sig", "wb") as sig_file:
|
||||
sig_file.write(signature_and_cert)
|
||||
|
||||
|
||||
|
||||
"""
|
||||
verify <fich>-- verifica a assinatura contida em <fich>.sig usando a
|
||||
informação do signatário contida no certificado (também incluído em <fich>.sig).
|
||||
Deve apresentar o status de validade da assinatura (Válida/Inválida) e,
|
||||
no caso de ser válida, ainda os dados do signatário.
|
||||
"""
|
||||
def verify(filename, user):
|
||||
|
||||
with open(filename + ".sig", "rb") as sig_file:
|
||||
signature_and_cert = sig_file.read()
|
||||
|
||||
signature, cert_bytes = unpair(signature_and_cert)
|
||||
|
||||
cert = x509.load_pem_x509_certificate(cert_bytes, default_backend())
|
||||
|
||||
ca_cert = cert_load("EC.crt")
|
||||
|
||||
try:
|
||||
valida_cert(cert, ca_cert, user)
|
||||
|
||||
with open(filename, "rb") as file:
|
||||
data_to_verify = file.read()
|
||||
|
||||
cert.public_key().verify(signature, data_to_verify,
|
||||
padding.PSS(mgf=padding.MGF1(hashes.SHA256()),
|
||||
salt_length=padding.PSS.MAX_LENGTH),
|
||||
hashes.SHA256())
|
||||
|
||||
print("Valid signature")
|
||||
print(cert.subject)
|
||||
|
||||
except x509.verification.VerificationError as e:
|
||||
print("Invalid signature: " + str(e))
|
||||
return
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description="Sign or verify files using X.509 certificates.")
|
||||
parser.add_argument("command", choices=["sign", "verify"], help="Command to execute: 'sign' or 'verify'")
|
||||
parser.add_argument("user", help="Username")
|
||||
parser.add_argument("filename", help="File name")
|
||||
parser.add_argument("--test", action="store_true", help="Perform testing (simulate errors)")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
match args.command:
|
||||
case "sign" if os.path.exists(args.user + ".crt") and os.path.exists(args.user + ".key"):
|
||||
sign(args.user, args.filename)
|
||||
print("File signed successfully.")
|
||||
case "sign":
|
||||
print("User certificate or private key not found.")
|
||||
case "verify" if os.path.exists(args.filename + ".sig"):
|
||||
verify(args.filename, args.user)
|
||||
case "verify":
|
||||
print("Signature file not found.")
|
||||
case _:
|
||||
parser.print_help()
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
Loading…
Reference in a new issue