85 lines
2.8 KiB
Python
85 lines
2.8 KiB
Python
import os
|
|
import pickle
|
|
import string
|
|
from cryptography.hazmat.primitives import hashes, serialization
|
|
from cryptography.hazmat.primitives.asymmetric import ec
|
|
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
|
|
from cryptography.hazmat.primitives.kdf.hkdf import HKDF
|
|
|
|
CURVE = ec.SECP256R1()
|
|
|
|
def GENERATE_DH():
|
|
return ec.generate_private_key(CURVE)
|
|
|
|
def DH(dh_pair, dh_pub):
|
|
return dh_pair.exchange(ec.ECDH(), dh_pub)
|
|
|
|
class MessengerServer:
|
|
def __init__(self, server_signing_key, server_decryption_key):
|
|
self.server_signing_key = server_signing_key
|
|
self.server_decryption_key = server_decryption_key
|
|
|
|
def decryptReport(self, ct):
|
|
raise Exception("not implemented!")
|
|
return
|
|
|
|
def signCert(self, cert):
|
|
return self.server_signing_key.sign(cert, ec.ECDSA(hashes.SHA256()))
|
|
|
|
class MessengerClient:
|
|
|
|
def __init__(self, name, server_signing_pk, server_encryption_pk):
|
|
self.name = name
|
|
self.server_signing_pk = server_signing_pk
|
|
self.server_encryption_pk = server_encryption_pk
|
|
self.conns = {}
|
|
self.certs = {}
|
|
self.dh = GENERATE_DH()
|
|
self.certificate = None
|
|
|
|
def generateCertificate(self):
|
|
self.certificate = pickle.dumps((self.name, self.dh.public_key().public_bytes(serialization.Encoding.X962,
|
|
serialization.PublicFormat.UncompressedPoint)))
|
|
return self.certificate
|
|
|
|
def receiveCertificate(self, certificate, signature):
|
|
self.server_signing_pk.verify(signature, certificate, ec.ECDSA(hashes.SHA256()))
|
|
name, public_bytes = pickle.loads(certificate)
|
|
public_key = ec.EllipticCurvePublicKey.from_encoded_point(CURVE, public_bytes)
|
|
self.certs[name] = public_key
|
|
|
|
def sendMessage(self, name, message):
|
|
raise Exception("not implemented!")
|
|
return
|
|
|
|
def receiveMessage(self, name, header, ciphertext):
|
|
raise Exception("not implemented!")
|
|
return
|
|
|
|
def report(self, name, message):
|
|
report = (name, message)
|
|
plaintext = pickle.dumps(report)
|
|
temp_key = GENERATE_DH()
|
|
temp_bytes = temp_key.public_key().public_bytes(
|
|
serialization.Encoding.X962,
|
|
serialization.PublicFormat.UncompressedPoint,
|
|
)
|
|
shared_secret = DH(temp_key, self.server_encryption_pk)
|
|
hkdf = HKDF(
|
|
algorithm=hashes.SHA256(),
|
|
length=32,
|
|
salt=None,
|
|
info=b""
|
|
)
|
|
key = hkdf.derive(shared_secret)
|
|
nonce = os.urandom(12)
|
|
aesgcm = AESGCM(key)
|
|
ciphertext = aesgcm.encrypt(nonce, plaintext, temp_bytes) # not sure if passing in temp_bytes is correct, but it seems like it should be
|
|
data = {
|
|
"bytes": temp_bytes,
|
|
"nonce": nonce,
|
|
"ciphertext": ciphertext
|
|
}
|
|
return plaintext.decode("latin1"), pickle.dumps(data)
|
|
|