def encrypt(message: bytes, pk_receiver: EncryptionPublicKey) -> bytes: """ Encrypts a string message under a ec25519 public key by using a custom dhaes-based scheme. See: https://eprint.iacr.org/1999/007 """ assert \ len(message) == NOTE_LENGTH_BYTES, \ f"expected message length {NOTE_LENGTH_BYTES}, saw {len(message)}" # Generate ephemeral keypair eph_keypair = generate_encryption_keypair() # Compute shared secret and eph key shared_key = _exchange(eph_keypair.k_sk, pk_receiver) pk_sender_bytes = encode_encryption_public_key(eph_keypair.k_pk) # Generate key material sym_key, mac_key = _kdf(pk_sender_bytes, shared_key) # Generate symmetric ciphertext # Chacha encryption algorithm = algorithms.ChaCha20(sym_key, _SYM_NONCE_VALUE) cipher = Cipher(algorithm, mode=None, backend=default_backend()) encryptor = cipher.encryptor() sym_ciphertext = encryptor.update(message) # Generate mac mac = poly1305.Poly1305(mac_key) mac.update(sym_ciphertext) tag = mac.finalize() # Arrange ciphertext return pk_sender_bytes + sym_ciphertext + tag
def generate_poly1305(key, nonce_or_iv): p = poly1305.Poly1305(key) def do_computation(msg: bytes): p.update(msg) # p.finalize() return do_computation
def decrypt(encrypted_message: bytes, sk_receiver: EncryptionSecretKey) -> bytes: """ Decrypts a NOTE_LENGTH-byte message by using valid ec25519 private key objects. See: https://pynacl.readthedocs.io/en/stable/public/ """ assert \ len(encrypted_message) == ENCRYPTED_NOTE_LENGTH_BYTES, \ "encrypted_message byte-length must be: "+str(ENCRYPTED_NOTE_LENGTH_BYTES) assert(isinstance(sk_receiver, X25519PrivateKey)), \ f"PrivateKey: {sk_receiver} ({type(sk_receiver)})" # Compute shared secret pk_sender_bytes = encrypted_message[:EC_PUBLIC_KEY_LENGTH_BYTES] pk_sender = decode_encryption_public_key(pk_sender_bytes) shared_key = _exchange(sk_receiver, pk_sender) # Generate key material and recover keys sym_key, mac_key = _kdf(pk_sender_bytes, shared_key) # ct_sym and mac ct_sym = encrypted_message[ EC_PUBLIC_KEY_LENGTH_BYTES:EC_PUBLIC_KEY_LENGTH_BYTES + NOTE_LENGTH_BYTES] tag = encrypted_message[EC_PUBLIC_KEY_LENGTH_BYTES + NOTE_LENGTH_BYTES:EC_PUBLIC_KEY_LENGTH_BYTES + NOTE_LENGTH_BYTES + _TAG_LENGTH_BYTES] # Verify the mac mac = poly1305.Poly1305(mac_key) mac.update(ct_sym) mac.verify(tag) # Decrypt sym ciphertext algorithm = algorithms.ChaCha20(sym_key, _SYM_NONCE_VALUE) cipher = Cipher(algorithm, mode=None, backend=default_backend()) decryptor = cipher.decryptor() message = decryptor.update(ct_sym) return message