use super::*;
use ::ring::{
agreement::{agree_ephemeral, EphemeralPrivateKey, UnparsedPublicKey, ECDH_P256},
rand::SystemRandom,
};
pub struct RingProvider {
rng: SystemRandom,
}
impl RingProvider {
pub fn new() -> Self {
Self {
rng: SystemRandom::new(),
}
}
}
impl EcdhProvider for RingProvider {
type SecretKey = RingSecretKey;
fn generate_keypair<R>(&mut self, _: &mut R) -> (Self::SecretKey, PublicKey)
where
R: RngCore + CryptoRng,
{
let secret = EphemeralPrivateKey::generate(&ECDH_P256, &self.rng).unwrap();
let public = secret.compute_public_key().unwrap();
let mut pub_bytes = [0; 64];
pub_bytes.copy_from_slice(&public.as_ref()[1..]);
let secret = RingSecretKey(secret);
let public = PublicKey(pub_bytes);
(secret, public)
}
}
pub struct RingSecretKey(EphemeralPrivateKey);
impl SecretKey for RingSecretKey {
fn agree(self, foreign_key: &PublicKey) -> Result<SharedSecret, InvalidPublicKey> {
let mut encoded = [0; 65];
encoded[0] = 0x04; encoded[1..].copy_from_slice(&foreign_key.0);
let public = UnparsedPublicKey::new(&ECDH_P256, &encoded[..]);
let mut shared_secret = [0; 32];
agree_ephemeral(self.0, &public, InvalidPublicKey::new(), |b| {
shared_secret.copy_from_slice(b);
Ok(())
})?;
Ok(SharedSecret(shared_secret))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn testsuite() {
run_tests(RingProvider::new());
}
}