1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
use super::local_key::LocalKey;
use crate::{
crypto::{alg::AnyKey, buffer::SecretBytes, jwk::FromJwk},
error::Error,
storage::{Entry, EntryTag},
};
#[derive(Clone, Debug, PartialEq, Eq, Deserialize, Serialize)]
pub struct KeyParams {
#[serde(default, rename = "meta", skip_serializing_if = "Option::is_none")]
pub metadata: Option<String>,
#[serde(default, rename = "ref", skip_serializing_if = "Option::is_none")]
pub reference: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub data: Option<SecretBytes>,
}
impl KeyParams {
pub(crate) fn to_bytes(&self) -> Result<SecretBytes, Error> {
serde_cbor::to_vec(self)
.map(SecretBytes::from)
.map_err(|e| err_msg!(Unexpected, "Error serializing key params: {}", e))
}
pub(crate) fn from_slice(params: &[u8]) -> Result<KeyParams, Error> {
let result = serde_cbor::from_slice(params)
.map_err(|e| err_msg!(Unexpected, "Error deserializing key params: {}", e));
result
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct KeyEntry {
pub(crate) name: String,
pub(crate) params: KeyParams,
pub(crate) alg: Option<String>,
pub(crate) thumbprints: Vec<String>,
pub(crate) tags: Vec<EntryTag>,
}
impl KeyEntry {
pub fn algorithm(&self) -> Option<&str> {
self.alg.as_ref().map(String::as_ref)
}
pub fn metadata(&self) -> Option<&str> {
self.params.metadata.as_ref().map(String::as_ref)
}
pub fn name(&self) -> &str {
self.name.as_str()
}
pub fn is_local(&self) -> bool {
self.params.reference.is_none()
}
pub(crate) fn from_entry(entry: Entry) -> Result<Self, Error> {
let params = KeyParams::from_slice(&entry.value)?;
let mut alg = None;
let mut thumbprints = Vec::new();
let mut tags = entry.tags;
let mut idx = 0;
while idx < tags.len() {
let tag = &mut tags[idx];
let name = tag.name();
if name.starts_with("user:") {
tag.update_name(|tag| tag.replace_range(0..5, ""));
idx += 1;
} else if name == "alg" {
alg.replace(tags.remove(idx).into_value());
} else if name == "thumb" {
thumbprints.push(tags.remove(idx).into_value());
} else {
tags.remove(idx).into_value();
}
}
thumbprints.sort();
tags.sort();
Ok(Self {
name: entry.name,
params,
alg,
thumbprints,
tags,
})
}
pub fn load_local_key(&self) -> Result<LocalKey, Error> {
if let Some(key_data) = self.params.data.as_ref() {
let inner = Box::<AnyKey>::from_jwk_slice(key_data.as_ref())?;
Ok(LocalKey {
inner,
ephemeral: false,
})
} else {
Err(err_msg!("Missing key data"))
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn key_params_roundtrip() {
let params = KeyParams {
metadata: Some("meta".to_string()),
reference: None,
data: Some(SecretBytes::from(vec![0, 0, 0, 0])),
};
let enc_params = params.to_bytes().unwrap();
let p2 = KeyParams::from_slice(&enc_params).unwrap();
assert_eq!(p2, params);
}
}