use crate::ImportError;
pub trait DhProvider {
type Algorithm: DhAlgorithm;
type VisibleSecretKey: Sized + Into<Self::SecretKey>;
type SecretKey: Sized;
type PublicKey: Sized;
type SharedSecret: Sized;
fn generate_visible(&mut self, alg: Self::Algorithm) -> Self::VisibleSecretKey;
fn generate(&mut self, alg: Self::Algorithm) -> Self::SecretKey {
self.generate_visible(alg).into()
}
fn export_secretkey_bytes<'s>(
&mut self,
secretkey: &'s Self::VisibleSecretKey,
) -> impl AsRef<[u8]> + use<'s, Self>;
fn import_secretkey_bytes(
&mut self,
alg: Self::Algorithm,
secret: &[u8],
) -> Result<Self::VisibleSecretKey, ImportError>;
fn export_publickey_bytes<'p>(
&mut self,
public: &'p Self::PublicKey,
) -> impl AsRef<[u8]> + use<'p, Self>;
fn import_publickey_bytes(
&mut self,
alg: Self::Algorithm,
data: &[u8],
) -> Result<Self::PublicKey, ImportError>;
fn shared_secret(
&mut self,
private: &Self::SecretKey,
public: &Self::PublicKey,
) -> Result<Self::SharedSecret, IncompatibleKeys>;
fn public_key(&mut self, private: &Self::SecretKey) -> Self::PublicKey;
fn raw_secret_bytes<'s>(
&mut self,
secret: &'s Self::SharedSecret,
) -> impl AsRef<[u8]> + use<'s, Self>;
}
#[derive(Debug)]
pub struct IncompatibleKeys;
impl core::fmt::Display for IncompatibleKeys {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
f.write_str("keys are incompatible")
}
}
impl core::error::Error for IncompatibleKeys {}
pub trait DhAlgorithm: Sized + PartialEq + Eq + core::fmt::Debug + Clone {
fn output_length(&self) -> usize;
#[inline]
#[allow(
unused_variables,
reason = "Argument names are part of the documentation"
)]
fn from_cose_ecdh(curve: impl Into<i128>) -> Option<Self> {
None
}
}
pub fn test_dh_algorithm_ecdh_p256<DP: DhProvider>() {
let cose_ecdh_1 = DP::Algorithm::from_cose_ecdh(1i8).expect(
"test for type claiming ECDH on P-256 compatibility did not recognize COSE curve 1",
);
assert_eq!(cose_ecdh_1.output_length(), 32)
}
pub fn test_dh_selftest<C: crate::Cal + rand_core::CryptoRng>(
cal: &mut C,
alg: <C::DhProvider as DhProvider>::Algorithm,
) {
let cal = cal.dh();
let my_secret = cal.generate(alg.clone());
let peer_secret = cal.generate(alg);
let my_public = cal.public_key(&my_secret);
let peer_public = cal.public_key(&peer_secret);
let my_shared_secret = cal.shared_secret(&my_secret, &peer_public).unwrap();
let peer_shared_secret = cal.shared_secret(&peer_secret, &my_public).unwrap();
let my_raw_bytes = cal.raw_secret_bytes(&my_shared_secret);
let peer_raw_bytes = cal.raw_secret_bytes(&peer_shared_secret);
assert_eq!(my_raw_bytes.as_ref(), peer_raw_bytes.as_ref());
}