1use std::convert::TryInto;
5
6use base64::URL_SAFE_NO_PAD;
7use ed25519_dalek::{
8 Keypair as Ed25519DalekKeyPair, PublicKey as Ed25519DalekPublicKey,
9 SecretKey as Ed25519DalekSecretKey, Signer, Verifier,
10};
11use serde::{Deserialize, Serialize};
12
13use crate::protocol::{KeyUse, PrivateKey, PublicKey};
14
15mod ed25519_sign;
16
17pub use ed25519_sign::EddsaKeyGen;
18
19pub const EDDSA_ALGORITHM: &str = "EdDSA";
21
22#[derive(Serialize, Deserialize)]
24#[serde(into = "JWK", try_from = "JWK")]
25pub struct Ed25519PrivateKey {
26 key_id: String,
27 private_key: Ed25519DalekKeyPair,
28}
29
30impl Clone for Ed25519PrivateKey {
31 fn clone(&self) -> Self {
32 Self {
33 key_id: self.key_id.clone(),
34 private_key: Ed25519DalekKeyPair::from_bytes(&self.private_key.to_bytes()).unwrap(),
35 }
36 }
37}
38
39impl PartialEq for Ed25519PrivateKey {
40 fn eq(&self, other: &Self) -> bool {
41 self.key_id == other.key_id
42 && self.private_key.secret.as_bytes() == other.private_key.secret.as_bytes()
43 }
45}
46
47impl Eq for Ed25519PrivateKey {}
48
49impl std::fmt::Debug for Ed25519PrivateKey {
50 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
51 f.debug_struct("Ed25519PrivateKey")
52 .field("key_id", &self.key_id)
53 .field("private_key", &"***")
54 .finish()
55 }
56}
57
58impl Ed25519PrivateKey {
59 fn new(key_id: String, private_key: Ed25519DalekKeyPair) -> Self {
61 Self {
62 key_id,
63 private_key,
64 }
65 }
66}
67
68impl PrivateKey for Ed25519PrivateKey {
69 fn key_id(&self) -> &str {
70 &self.key_id
71 }
72
73 fn algorithm(&self) -> &str {
74 EDDSA_ALGORITHM
75 }
76
77 fn sign(&self, message: &[u8]) -> crate::sign::Result<Vec<u8>> {
78 Ok(self
79 .private_key
80 .try_sign(message)
81 .map_err(|_| crate::sign::Error::CryptoError)?
82 .to_bytes()
83 .to_vec())
84 }
85}
86
87#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Eq)]
89#[serde(into = "JWK", try_from = "JWK")]
90pub struct Ed25519PublicKey {
91 key_id: String,
92 public_key: Ed25519DalekPublicKey,
93}
94
95impl PublicKey for Ed25519PublicKey {
96 fn key_id(&self) -> &str {
97 &self.key_id
98 }
99
100 fn algorithm(&self) -> &str {
101 EDDSA_ALGORITHM
102 }
103
104 fn key_use(&self) -> KeyUse {
105 KeyUse::Signing
106 }
107
108 fn verify(&self, message: &[u8], signature: &[u8]) -> bool {
109 let res = signature
110 .try_into()
111 .and_then(|signature| self.public_key.verify(message, &signature));
112 res.is_ok()
113 }
114}
115
116impl Ed25519PublicKey {
117 fn new(public_key: Ed25519DalekPublicKey) -> Self {
119 Self {
120 key_id: "aky".to_owned(),
121 public_key,
122 }
123 }
124}
125
126#[derive(Clone, Serialize, Deserialize, PartialEq, Eq)]
128pub struct JWK {
129 pub kid: String,
131 #[serde(rename = "use")]
133 pub key_use: KeyUse,
134 pub key_ops: Vec<KeyOp>,
136 pub alg: String,
138 pub kty: String,
140 pub crv: String,
142 pub x: String,
144 #[serde(skip_serializing_if = "Option::is_none")]
146 pub d: Option<String>,
147}
148
149impl std::fmt::Debug for JWK {
150 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
151 f.debug_struct("JWK")
152 .field("kid", &self.kid)
153 .field("key_use", &self.key_use)
154 .field("key_ops", &self.key_ops)
155 .field("alg", &self.alg)
156 .field("kty", &self.kty)
157 .field("crv", &self.crv)
158 .field("x", &self.x)
159 .field("d", &self.d.as_ref().map(|_| "***"))
160 .finish()
161 }
162}
163
164#[derive(Clone, Serialize, Deserialize, PartialEq, Eq, Debug)]
166pub enum KeyOp {
167 #[serde(rename = "sign")]
169 Sign,
170 #[serde(rename = "verify")]
172 Verify,
173}
174
175impl From<Ed25519PublicKey> for JWK {
176 fn from(k: Ed25519PublicKey) -> Self {
177 Self::from(&k)
178 }
179}
180
181impl From<&Ed25519PublicKey> for JWK {
182 fn from(k: &Ed25519PublicKey) -> Self {
183 JWK {
184 kid: k.key_id.clone(),
185 key_use: KeyUse::Signing,
186 key_ops: vec![KeyOp::Verify],
187 kty: "OKP".to_owned(),
188 crv: "Ed25519".to_owned(),
189 alg: "EdDSA".to_owned(),
190 x: base64::encode_config(k.public_key.as_bytes(), URL_SAFE_NO_PAD),
191 d: None,
192 }
193 }
194}
195
196impl From<Ed25519PrivateKey> for JWK {
197 fn from(k: Ed25519PrivateKey) -> Self {
198 Self::from(&k)
199 }
200}
201
202impl From<&Ed25519PrivateKey> for JWK {
203 fn from(k: &Ed25519PrivateKey) -> Self {
204 JWK {
205 kid: k.key_id.to_owned(),
206 key_use: KeyUse::Signing,
207 key_ops: vec![KeyOp::Sign],
208 kty: "OKP".to_owned(),
209 crv: "Ed25519".to_owned(),
210 alg: "EdDSA".to_owned(),
211 x: base64::encode_config(k.private_key.public.as_bytes(), URL_SAFE_NO_PAD),
212 d: Some(base64::encode_config(
213 k.private_key.secret.as_bytes(),
214 URL_SAFE_NO_PAD,
215 )),
216 }
217 }
218}
219
220impl TryFrom<JWK> for Ed25519PublicKey {
221 type Error = crate::verify::Error;
222
223 fn try_from(value: JWK) -> Result<Self, Self::Error> {
224 Ed25519PublicKey::try_from(&value)
225 }
226}
227
228impl TryFrom<&JWK> for Ed25519PublicKey {
229 type Error = crate::verify::Error;
230
231 fn try_from(jwk: &JWK) -> std::result::Result<Self, Self::Error> {
232 let x_bytes = base64::decode_config(&jwk.x, URL_SAFE_NO_PAD)
233 .map_err(|_| crate::verify::Error::MalformedAttenuationKeyJWK)?;
234 let public_key = Ed25519DalekPublicKey::from_bytes(&x_bytes)
235 .map_err(|_| crate::verify::Error::MalformedAttenuationKeyJWK)?;
236 Ok(Ed25519PublicKey {
237 key_id: jwk.kid.clone(),
238 public_key,
239 })
240 }
241}
242
243impl TryFrom<JWK> for Ed25519PrivateKey {
244 type Error = crate::verify::Error;
245
246 fn try_from(jwk: JWK) -> std::result::Result<Self, Self::Error> {
247 Ed25519PrivateKey::try_from(&jwk)
248 }
249}
250
251impl TryFrom<&JWK> for Ed25519PrivateKey {
252 type Error = crate::verify::Error;
253
254 fn try_from(jwk: &JWK) -> std::result::Result<Self, Self::Error> {
255 if let Some(d) = &jwk.d {
256 let x_bytes = base64::decode_config(&jwk.x, URL_SAFE_NO_PAD)
257 .map_err(|_| crate::verify::Error::MalformedAttenuationKeyJWK)?;
258 let public = Ed25519DalekPublicKey::from_bytes(&x_bytes)
259 .map_err(|_| crate::verify::Error::MalformedAttenuationKeyJWK)?;
260 let d_bytes = base64::decode_config(d, URL_SAFE_NO_PAD)
261 .map_err(|_| crate::verify::Error::MalformedAttenuationKeyJWK)?;
262 let secret = Ed25519DalekSecretKey::from_bytes(&d_bytes)
263 .map_err(|_| crate::verify::Error::MalformedAttenuationKeyJWK)?;
264 let keypair = Ed25519DalekKeyPair { public, secret };
265 Ok(Ed25519PrivateKey {
266 key_id: jwk.kid.clone(),
267 private_key: keypair,
268 })
269 } else {
270 Err(crate::verify::Error::InvalidKey)
271 }
272 }
273}
274
275#[cfg(test)]
276mod test {
277 use crate::{ed25519::Ed25519PrivateKey, protocol::AttenuationKeyGenerator};
278
279 use super::{Ed25519PublicKey, EddsaKeyGen, JWK};
280
281 #[test]
282 fn test_private_key_jwk() -> Result<(), Box<dyn std::error::Error>> {
283 let kg = EddsaKeyGen::new_with_std_rng();
284 let (_, priv_key) = kg.generate_attenuation_key()?;
285 let jwk = JWK::from(&priv_key);
286 let round_trip = Ed25519PrivateKey::try_from(&jwk)?;
287 assert_eq!(
288 priv_key.private_key.to_bytes(),
289 round_trip.private_key.to_bytes()
290 );
291 assert_eq!(&priv_key.key_id, &round_trip.key_id);
292 Ok(())
293 }
294
295 #[test]
296 fn test_public_key_jwk() -> Result<(), Box<dyn std::error::Error>> {
297 let kg = EddsaKeyGen::new_with_std_rng();
298 let (pub_key, _) = kg.generate_attenuation_key()?;
299 let jwk = JWK::from(&pub_key);
300 let round_trip = Ed25519PublicKey::try_from(&jwk)?;
301 assert_eq!(
302 pub_key.public_key.as_bytes(),
303 round_trip.public_key.as_bytes()
304 );
305 assert_eq!(&pub_key.key_id, &round_trip.key_id);
306 Ok(())
307 }
308}