1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
|
use pqcrypto_hqc::hqc256;
use pqcrypto_traits::kem::{Ciphertext as _, PublicKey as _, SharedSecret as _};
use sha2::{Digest as _, Sha256};
const ALGORITHM_NAME: &str = "HQC-256";
pub struct Keypair {
public_key: hqc256::PublicKey,
secret_key: hqc256::SecretKey,
}
impl Keypair {
/// Returns the encapsulation key. This is sometimes called the public key.
///
/// This is the key to send to the peer you want to negotiate a shared secret with.
pub fn encapsulation_key(&self) -> Vec<u8> {
self.public_key.as_bytes().to_vec()
}
pub fn algorithm_name(&self) -> &'static str {
ALGORITHM_NAME
}
/// Decapsulates a shared secret that was encapsulated to our encapsulation key.
///
// Always inline in order to try to avoid potential copies of `shared_secret` to multiple places
// on the stack. This is almost pointless as with optimization all bets are off regarding where
// the shared secrets will end up in memory. In the future we can try to do better, by
// cleaning the stack. But this is not trivial. Please see:
// https://github.com/RustCrypto/KEMs/issues/70
#[inline(always)]
pub fn decapsulate(&self, ciphertext_slice: &[u8]) -> Result<[u8; 32], super::Error> {
let ciphertext = hqc256::Ciphertext::from_bytes(ciphertext_slice).map_err(|_| {
super::Error::InvalidCiphertextLength {
algorithm: self.algorithm_name(),
actual: ciphertext_slice.len(),
expected: hqc256::ciphertext_bytes(),
}
})?;
let shared_secret = hqc256::decapsulate(&ciphertext, &self.secret_key);
// HQC outputs a 64 byte shared secret. But we need 32 bytes for the WireGuard PSK.
// Our ephemeral peer API says shared secrets with a length other than 32 bytes should
// be passed through sha256 in order to squash the entropy into 32 bytes.
let output_shared_secret = Sha256::digest(shared_secret.as_bytes());
Ok(output_shared_secret.into())
}
}
pub fn keypair() -> Keypair {
let (public_key, secret_key) = hqc256::keypair();
Keypair {
public_key,
secret_key,
}
}
|