Skip to content

Instantly share code, notes, and snippets.

@birb007
Last active August 1, 2022 08:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save birb007/2a1e7f3adbab34a41530037417f782d0 to your computer and use it in GitHub Desktop.
Save birb007/2a1e7f3adbab34a41530037417f782d0 to your computer and use it in GitHub Desktop.
from cryptography.hazmat.primitives import hashes, hmac
from cryptography.hazmat.primitives.kdf.hkdf import HKDF
from cryptography.hazmat.primitives.asymmetric import x25519
from cryptography.hazmat.primitives.serialization import (
load_pem_public_key,
load_pem_private_key
)
def main():
sk_path = ...
pk_path = ...
source_sk = load_pem_private_key(sk_path.read_bytes(), password=None)
target_pk = load_pem_public_key(pk_path.read_bytes())
# Generate 256-bit ECDHE keys, encoded with x509 SubjectPublicKeyInfo
ecdhe_sk = x25519.X25519PrivateKey.generate()
ecdhe_pk = ecdhe_sk.public_key()
# Send ECDHE public key and recieve peer public key to derive shared secret
send(ecdhe_pk)
peer_pk = recv()
# X25519 key exchange
shared_key = ecdhe_sk.exchange(peer_pk)
# Generate handshake secret material
def make_key(info, length):
salt = ... # current message context for caller protocol state
return HKDF(hashes.SHA256(), length, salt, info).derive(shared_key)
source_mac_key = make_key(b"initiator mac key", 32)
target_mac_key = make_key(b"responder mac key", 32)
# Provide proof of posession using the secret material
mac = hmac.HMAC(source_mac_key, hashes.SHA256()).update(source_pk).finalize()
signature = source_pk.sign(..., ecdhe_pk + peer_pk + mac)
send(source_pk + signature)
proof = recv()
# Ensure identity matches our target (assume target_pk != source_pk)
assert proof.identity == target_pk
mac = hmac.HMAC(target_mac_key, hashes.SHA256()).update(target_pk).finalize()
assert target_pk.verify(proof.signature, peer_pk + ecdhe_pk + mac)
# Generate a consistent key or have independent keys
source_session_key = make_key(b"initiator session key", 32)
target_session_key = make_key(b"responder session key", 32)
# Encrypt all further communication with ChaCha20-Poly1305 or other suitable cipher
pass
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment