iroh 0.98.0

p2p quic connections dialed by public key
Documentation
use std::sync::Arc;

use iroh_base::SecretKey;
use webpki_types::CertificateDer;

#[derive(Debug)]
pub(super) struct ResolveRawPublicKeyCert {
    key: Arc<rustls::sign::CertifiedKey>,
}

impl ResolveRawPublicKeyCert {
    pub(super) fn new(secret_key: &SecretKey) -> Self {
        let client_private_key = Arc::new(IrohSecretKey::from(secret_key.clone()));
        let client_public_key = client_private_key.spki_public_key();
        let client_public_key_as_cert = CertificateDer::from(client_public_key.to_vec());

        let certified_key =
            rustls::sign::CertifiedKey::new(vec![client_public_key_as_cert], client_private_key);

        let key = Arc::new(certified_key);

        Self { key }
    }
}

impl rustls::client::ResolvesClientCert for ResolveRawPublicKeyCert {
    fn resolve(
        &self,
        _root_hint_subjects: &[&[u8]],
        _sigschemes: &[rustls::SignatureScheme],
    ) -> Option<Arc<rustls::sign::CertifiedKey>> {
        Some(Arc::clone(&self.key))
    }

    fn only_raw_public_keys(&self) -> bool {
        true
    }

    fn has_certs(&self) -> bool {
        true
    }
}

impl rustls::server::ResolvesServerCert for ResolveRawPublicKeyCert {
    fn resolve(
        &self,
        _client_hello: rustls::server::ClientHello<'_>,
    ) -> Option<Arc<rustls::sign::CertifiedKey>> {
        Some(Arc::clone(&self.key))
    }

    fn only_raw_public_keys(&self) -> bool {
        true
    }
}

#[derive(Debug, Clone, derive_more::From)]
struct IrohSecretKey {
    #[from]
    key: SecretKey,
}

impl IrohSecretKey {
    fn spki_public_key(&self) -> webpki_types::SubjectPublicKeyInfoDer<'static> {
        rustls::sign::public_key_to_spki(
            &webpki_types::alg_id::ED25519,
            self.key.public().as_bytes(),
        )
    }
}
impl rustls::sign::SigningKey for IrohSecretKey {
    fn choose_scheme(
        &self,
        offered: &[rustls::SignatureScheme],
    ) -> Option<Box<dyn rustls::sign::Signer>> {
        if offered.contains(&rustls::SignatureScheme::ED25519) {
            Some(Box::new(self.clone()))
        } else {
            None
        }
    }

    fn algorithm(&self) -> rustls::SignatureAlgorithm {
        rustls::SignatureAlgorithm::ED25519
    }

    fn public_key(&self) -> Option<webpki_types::SubjectPublicKeyInfoDer<'_>> {
        Some(self.spki_public_key())
    }
}

impl rustls::sign::Signer for IrohSecretKey {
    fn sign(&self, message: &[u8]) -> Result<Vec<u8>, rustls::Error> {
        Ok(self.key.sign(message).to_bytes().to_vec())
    }

    fn scheme(&self) -> rustls::SignatureScheme {
        rustls::SignatureScheme::ED25519
    }
}