use hpke::{
aead::{AeadTag, ChaCha20Poly1305},
kdf::HkdfSha384,
kem::X25519HkdfSha256,
Deserializable, Kem as KemTrait, OpModeR, OpModeS, Serializable,
};
use rand::{rngs::StdRng, SeedableRng};
const INFO_STR: &[u8] = b"example session";
type Kem = X25519HkdfSha256;
type Aead = ChaCha20Poly1305;
type Kdf = HkdfSha384;
fn server_init() -> (<Kem as KemTrait>::PrivateKey, <Kem as KemTrait>::PublicKey) {
let mut csprng = StdRng::from_entropy();
Kem::gen_keypair(&mut csprng)
}
fn client_encrypt_msg(
msg: &[u8],
associated_data: &[u8],
server_pk: &<Kem as KemTrait>::PublicKey,
) -> (<Kem as KemTrait>::EncappedKey, Vec<u8>, AeadTag<Aead>) {
let mut csprng = StdRng::from_entropy();
let (encapped_key, mut sender_ctx) =
hpke::setup_sender::<Aead, Kdf, Kem, _>(&OpModeS::Base, server_pk, INFO_STR, &mut csprng)
.expect("invalid server pubkey!");
let mut msg_copy = msg.to_vec();
let tag = sender_ctx
.seal_in_place_detached(&mut msg_copy, associated_data)
.expect("encryption failed!");
let ciphertext = msg_copy;
(encapped_key, ciphertext, tag)
}
fn server_decrypt_msg(
server_sk_bytes: &[u8],
encapped_key_bytes: &[u8],
ciphertext: &[u8],
associated_data: &[u8],
tag_bytes: &[u8],
) -> Vec<u8> {
let server_sk = <Kem as KemTrait>::PrivateKey::from_bytes(server_sk_bytes)
.expect("could not deserialize server privkey!");
let tag = AeadTag::<Aead>::from_bytes(tag_bytes).expect("could not deserialize AEAD tag!");
let encapped_key = <Kem as KemTrait>::EncappedKey::from_bytes(encapped_key_bytes)
.expect("could not deserialize the encapsulated pubkey!");
let mut receiver_ctx =
hpke::setup_receiver::<Aead, Kdf, Kem>(&OpModeR::Base, &server_sk, &encapped_key, INFO_STR)
.expect("failed to set up receiver!");
let mut ciphertext_copy = ciphertext.to_vec();
receiver_ctx
.open_in_place_detached(&mut ciphertext_copy, associated_data, &tag)
.expect("invalid ciphertext!");
#[allow(clippy::let_and_return)]
let plaintext = ciphertext_copy;
plaintext
}
fn main() {
let (server_privkey, server_pubkey) = server_init();
let msg = b"Kat Branchman";
let associated_data = b"Mr. Meow";
let (encapped_key, ciphertext, tag) = client_encrypt_msg(msg, associated_data, &server_pubkey);
let encapped_key_bytes = encapped_key.to_bytes();
let tag_bytes = tag.to_bytes();
let server_privkey_bytes = server_privkey.to_bytes();
let decrypted_msg = server_decrypt_msg(
server_privkey_bytes.as_slice(),
encapped_key_bytes.as_slice(),
&ciphertext,
associated_data,
tag_bytes.as_slice(),
);
assert_eq!(decrypted_msg, msg);
println!("MESSAGE SUCCESSFULLY SENT AND RECEIVED");
}