1use std::fmt;
2use std::ops::Deref;
3
4use crypto::{
5 signature::{Signer, Verifier},
6 ssh::ExtendedSignature,
7 Signature,
8};
9
10use crate::crypto;
11
12use super::NodeId;
13
14#[derive(Clone)]
23pub struct Device<S> {
24 node: NodeId,
25 signer: S,
26}
27
28impl<S> fmt::Debug for Device<S> {
29 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
30 f.debug_struct("Device")
31 .field("node", &self.node.to_human())
32 .finish()
33 }
34}
35
36impl<S: crypto::Signer + Default> Default for Device<S> {
37 fn default() -> Self {
38 Self::from(S::default())
39 }
40}
41
42impl<S> Device<S> {
43 pub fn new(node: NodeId, signer: S) -> Self {
45 Self { node, signer }
46 }
47
48 pub fn node_id(&self) -> &NodeId {
50 &self.node
51 }
52
53 pub fn public_key(&self) -> &crypto::PublicKey {
55 &self.node
56 }
57
58 pub fn into_inner(self) -> S {
62 self.signer
63 }
64}
65
66#[cfg(any(test, feature = "test"))]
67impl Device<crypto::test::signer::MockSigner> {
68 pub fn mock() -> Self {
70 Device::from(crypto::test::signer::MockSigner::default())
71 }
72
73 pub fn mock_rng(rng: &mut fastrand::Rng) -> Self {
75 Device::from(crypto::test::signer::MockSigner::new(rng))
76 }
77
78 pub fn mock_from_seed(seed: [u8; 32]) -> Self {
80 Device::from(crypto::test::signer::MockSigner::from_seed(seed))
81 }
82}
83
84impl<S: Signer<Signature> + 'static> Device<S> {
85 pub fn boxed(self) -> BoxedDevice {
87 BoxedDevice(Device {
88 node: self.node,
89 signer: BoxedSigner(Box::new(self.signer)),
90 })
91 }
92}
93
94impl<S> Verifier<Signature> for Device<S> {
95 fn verify(&self, msg: &[u8], signature: &Signature) -> Result<(), crypto::signature::Error> {
96 self.node
97 .verify(msg, signature)
98 .map_err(crypto::signature::Error::from_source)
99 }
100}
101
102impl<S: crypto::Signer> From<S> for Device<S> {
103 fn from(signer: S) -> Self {
104 Self {
105 node: *signer.public_key(),
106 signer,
107 }
108 }
109}
110
111impl<S: crypto::Signer + Clone> From<&S> for Device<S> {
112 fn from(signer: &S) -> Self {
113 Self::from(signer.clone())
114 }
115}
116
117impl<S: Signer<Signature>> Signer<Signature> for Device<S> {
118 fn try_sign(&self, msg: &[u8]) -> Result<Signature, crypto::signature::Error> {
119 self.signer.try_sign(msg)
120 }
121}
122
123impl<S: Signer<Signature>> Signer<ExtendedSignature> for Device<S> {
124 fn try_sign(&self, msg: &[u8]) -> Result<ExtendedSignature, crypto::signature::Error> {
125 Ok(ExtendedSignature {
126 key: *self.public_key(),
127 sig: self.signer.try_sign(msg)?,
128 })
129 }
130}
131
132pub struct BoxedSigner(Box<dyn Signer<Signature> + 'static>);
134
135impl Signer<Signature> for BoxedSigner {
136 fn try_sign(&self, msg: &[u8]) -> Result<Signature, crypto::signature::Error> {
137 self.0.try_sign(msg)
138 }
139}
140
141pub struct BoxedDevice(Device<BoxedSigner>);
146
147impl AsRef<Device<BoxedSigner>> for BoxedDevice {
148 fn as_ref(&self) -> &Device<BoxedSigner> {
149 &self.0
150 }
151}
152
153impl Deref for BoxedDevice {
154 type Target = Device<BoxedSigner>;
155
156 fn deref(&self) -> &Self::Target {
157 &self.0
158 }
159}
160
161impl Signer<Signature> for BoxedDevice {
162 fn try_sign(&self, msg: &[u8]) -> Result<Signature, crypto::signature::Error> {
163 self.0.signer.try_sign(msg)
164 }
165}
166
167impl Signer<ExtendedSignature> for BoxedDevice {
168 fn try_sign(&self, msg: &[u8]) -> Result<ExtendedSignature, crypto::signature::Error> {
169 Ok(ExtendedSignature {
170 key: *self.0.public_key(),
171 sig: self.0.signer.try_sign(msg)?,
172 })
173 }
174}