radicle/device: `impl Keypair for BoxedSigner`

Most consumers of `Device` are interested in the public key of the
device, and `Keypair` is the trait from `signature` which captures
this, so implement it.

Further, for boxing a signer, introduce a new trait `BoxableSigner`
(to remain dyn-compatible) which additionally requires `Keypair`.
This commit is contained in:
Lorenz Leutgeb 2026-03-08 09:49:32 +01:00
parent 74fa4425a1
commit f4495e92bc
No known key found for this signature in database
1 changed files with 35 additions and 3 deletions

View File

@ -2,7 +2,7 @@ use std::fmt;
use std::ops::Deref;
use crypto::{
signature::{Signer, Verifier},
signature::{Keypair, KeypairRef, Signer, Verifier},
ssh::ExtendedSignature,
Signature,
};
@ -81,7 +81,7 @@ impl Device<crypto::test::signer::MockSigner> {
}
}
impl<S: Signer<Signature> + 'static> Device<S> {
impl<S: BoxableSigner + 'static> Device<S> {
/// Construct a [`BoxedDevice`] from a given `Device`.
pub fn boxed(self) -> BoxedDevice {
BoxedDevice(Device {
@ -91,6 +91,16 @@ impl<S: Signer<Signature> + 'static> Device<S> {
}
}
impl<S> AsRef<NodeId> for Device<S> {
fn as_ref(&self) -> &NodeId {
&self.node
}
}
impl<S> KeypairRef for Device<S> {
type VerifyingKey = NodeId;
}
impl<S> Verifier<Signature> for Device<S> {
fn verify(&self, msg: &[u8], signature: &Signature) -> Result<(), crypto::signature::Error> {
self.node
@ -129,8 +139,12 @@ impl<S: Signer<Signature>> Signer<ExtendedSignature> for Device<S> {
}
}
pub trait BoxableSigner: Signer<Signature> + Keypair<VerifyingKey = crypto::PublicKey> {}
impl<S: Signer<Signature> + Keypair<VerifyingKey = crypto::PublicKey>> BoxableSigner for S {}
/// A `Signer<Signature>` that is packed in a [`Box`] for dynamic dispatch.
pub struct BoxedSigner(Box<dyn Signer<Signature> + 'static>);
pub struct BoxedSigner(Box<dyn BoxableSigner + 'static>);
impl Signer<Signature> for BoxedSigner {
fn try_sign(&self, msg: &[u8]) -> Result<Signature, crypto::signature::Error> {
@ -138,6 +152,14 @@ impl Signer<Signature> for BoxedSigner {
}
}
impl Keypair for BoxedSigner {
type VerifyingKey = crypto::PublicKey;
fn verifying_key(&self) -> Self::VerifyingKey {
self.0.verifying_key()
}
}
/// A `Device` where the signer is a dynamic `Signer<Signature>`, in the form of
/// a [`BoxedSigner`].
///
@ -172,3 +194,13 @@ impl Signer<ExtendedSignature> for BoxedDevice {
})
}
}
impl AsRef<crypto::PublicKey> for BoxedDevice {
fn as_ref(&self) -> &crypto::PublicKey {
&self.0.node
}
}
impl KeypairRef for BoxedDevice {
type VerifyingKey = crypto::PublicKey;
}