devolutions_crypto/signing_key/
mod.rs1mod signing_key_v1;
25
26use super::DataType;
27use super::Error;
28use super::Header;
29use super::HeaderType;
30use super::KeySubtype;
31use super::Result;
32pub use super::SigningKeyVersion;
33
34use signing_key_v1::{SigningKeyV1Pair, SigningKeyV1Public};
35
36use std::borrow::Borrow;
37use std::convert::TryFrom;
38
39#[cfg(feature = "fuzz")]
40use arbitrary::Arbitrary;
41
42#[cfg(feature = "wbindgen")]
43use wasm_bindgen::prelude::*;
44
45#[cfg_attr(feature = "wbindgen", wasm_bindgen(inspectable))]
47#[cfg_attr(feature = "fuzz", derive(Arbitrary))]
48#[derive(Clone, Debug)]
49pub struct SigningPublicKey {
50 pub(crate) header: Header<SigningPublicKey>,
51 payload: SigningPublicKeyPayload,
52}
53
54#[cfg_attr(feature = "wbindgen", wasm_bindgen(inspectable))]
57#[cfg_attr(feature = "fuzz", derive(Arbitrary))]
58#[derive(Clone, Debug)]
59pub struct SigningKeyPair {
60 pub(crate) header: Header<SigningKeyPair>,
61 payload: SigningKeyPairPayload,
62}
63
64impl HeaderType for SigningPublicKey {
65 type Version = SigningKeyVersion;
66 type Subtype = KeySubtype;
67
68 fn data_type() -> DataType {
69 DataType::SigningKey
70 }
71
72 fn subtype() -> Self::Subtype {
73 KeySubtype::Public
74 }
75}
76
77impl HeaderType for SigningKeyPair {
78 type Version = SigningKeyVersion;
79 type Subtype = KeySubtype;
80
81 fn data_type() -> DataType {
82 DataType::SigningKey
83 }
84
85 fn subtype() -> Self::Subtype {
86 KeySubtype::Private
87 }
88}
89
90#[derive(Clone, Debug)]
91#[cfg_attr(feature = "fuzz", derive(Arbitrary))]
92enum SigningKeyPairPayload {
93 V1(SigningKeyV1Pair),
94}
95
96#[derive(Clone, Debug)]
97#[cfg_attr(feature = "fuzz", derive(Arbitrary))]
98enum SigningPublicKeyPayload {
99 V1(SigningKeyV1Public),
100}
101
102pub fn generate_signing_keypair(version: SigningKeyVersion) -> SigningKeyPair {
114 let mut header = Header::default();
115
116 let payload = match version {
117 SigningKeyVersion::V1 | SigningKeyVersion::Latest => {
118 header.version = SigningKeyVersion::V1;
119
120 let keypair = signing_key_v1::generate_signing_keypair();
121 SigningKeyPairPayload::V1(keypair)
122 }
123 };
124
125 SigningKeyPair { header, payload }
126}
127
128impl SigningKeyPair {
129 pub fn get_public_key(&self) -> SigningPublicKey {
140 let mut header = Header::default();
141
142 let payload = match &self.payload {
143 SigningKeyPairPayload::V1(x) => {
144 header.version = SigningKeyVersion::V1;
145
146 SigningPublicKeyPayload::V1(x.get_public_key())
147 }
148 };
149
150 SigningPublicKey { header, payload }
151 }
152}
153
154impl From<SigningPublicKey> for Vec<u8> {
155 fn from(data: SigningPublicKey) -> Self {
157 let mut header: Self = data.header.borrow().into();
158 let mut payload: Self = data.payload.into();
159 header.append(&mut payload);
160 header
161 }
162}
163
164impl TryFrom<&[u8]> for SigningPublicKey {
165 type Error = Error;
166
167 fn try_from(data: &[u8]) -> Result<Self> {
169 if data.len() < Header::len() {
170 return Err(Error::InvalidLength);
171 };
172
173 let header = Header::try_from(&data[0..Header::len()])?;
174
175 if header.data_subtype != KeySubtype::Public {
176 return Err(Error::InvalidDataType);
177 }
178
179 let payload = match header.version {
180 SigningKeyVersion::V1 => {
181 SigningPublicKeyPayload::V1(SigningKeyV1Public::try_from(&data[Header::len()..])?)
182 }
183 _ => return Err(Error::UnknownVersion),
184 };
185
186 Ok(Self { header, payload })
187 }
188}
189
190impl From<SigningKeyPair> for Vec<u8> {
191 fn from(data: SigningKeyPair) -> Self {
193 let mut header: Self = data.header.borrow().into();
194 let mut payload: Self = data.payload.into();
195 header.append(&mut payload);
196 header
197 }
198}
199
200impl TryFrom<&[u8]> for SigningKeyPair {
201 type Error = Error;
202
203 fn try_from(data: &[u8]) -> Result<Self> {
205 if data.len() < Header::len() {
206 return Err(Error::InvalidLength);
207 };
208
209 let header = Header::try_from(&data[0..Header::len()])?;
210
211 if header.data_subtype != KeySubtype::Private {
212 return Err(Error::InvalidDataType);
213 }
214
215 let payload = match header.version {
216 SigningKeyVersion::V1 => {
217 SigningKeyPairPayload::V1(SigningKeyV1Pair::try_from(&data[Header::len()..])?)
218 }
219 _ => return Err(Error::UnknownVersion),
220 };
221
222 Ok(Self { header, payload })
223 }
224}
225
226impl From<SigningKeyPairPayload> for Vec<u8> {
227 fn from(data: SigningKeyPairPayload) -> Self {
228 match data {
229 SigningKeyPairPayload::V1(x) => x.into(),
230 }
231 }
232}
233
234impl From<SigningPublicKeyPayload> for Vec<u8> {
235 fn from(data: SigningPublicKeyPayload) -> Self {
236 match data {
237 SigningPublicKeyPayload::V1(x) => x.into(),
238 }
239 }
240}
241
242impl From<&SigningPublicKey> for ed25519_dalek::VerifyingKey {
243 fn from(data: &SigningPublicKey) -> Self {
244 match &data.payload {
245 SigningPublicKeyPayload::V1(x) => Self::from(x),
246 }
248 }
249}
250
251impl From<&SigningKeyPair> for ed25519_dalek::SigningKey {
252 fn from(data: &SigningKeyPair) -> Self {
253 match &data.payload {
254 SigningKeyPairPayload::V1(x) => Self::from(x),
255 }
257 }
258}
259
260#[test]
261fn test_signing_keypair_v1() {
262 use std::convert::TryInto;
263
264 let keypair = generate_signing_keypair(SigningKeyVersion::V1);
265 let public = keypair.get_public_key();
266
267 let keypair_bytes: Vec<u8> = keypair.into();
268 let public_bytes: Vec<u8> = public.into();
269
270 let _: SigningKeyPair = (keypair_bytes.as_slice()).try_into().unwrap();
271 let _: SigningPublicKey = (public_bytes.as_slice()).try_into().unwrap();
272}