wildland_crypto/identity/
signing_keypair.rs1use ed25519_dalek::{Keypair, PublicKey, SecretKey, Signer};
19use rand::{CryptoRng, RngCore};
20use serde::{Deserialize, Serialize};
21
22use super::bytes_key_from_str;
23use crate::error::CryptoError;
24use crate::signature::Signature;
25
26pub type PubKey = [u8; 32];
27pub type SecKey = [u8; 32];
28
29#[derive(Debug)]
30pub struct SigningKeypair(ed25519_dalek::Keypair);
31
32impl<'de> Deserialize<'de> for SigningKeypair {
33 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
34 where
35 D: serde::Deserializer<'de>,
36 {
37 let hex_encoded_str = String::deserialize(deserializer)?;
38 let bytes = hex::decode(hex_encoded_str).map_err(serde::de::Error::custom)?;
39 Ok(Self(
40 ed25519_dalek::Keypair::from_bytes(&bytes).map_err(serde::de::Error::custom)?,
41 ))
42 }
43}
44
45impl Serialize for SigningKeypair {
46 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
47 where
48 S: serde::Serializer,
49 {
50 let hex = hex::encode(self.0.to_bytes());
51 String::serialize(&hex, serializer)
52 }
53}
54
55impl TryFrom<Vec<u8>> for SigningKeypair {
56 type Error = CryptoError;
57
58 fn try_from(value: Vec<u8>) -> Result<Self, Self::Error> {
59 Ok(Self(
60 ed25519_dalek::Keypair::from_bytes(value.as_slice())
61 .map_err(|e| CryptoError::InvalidSignatureBytesError(e.to_string()))?,
62 ))
63 }
64}
65
66impl PartialEq for SigningKeypair {
67 fn eq(&self, other: &Self) -> bool {
68 self.public() == other.public() && self.secret() == other.secret()
69 }
70}
71
72impl From<&SigningKeypair> for SigningKeypair {
73 fn from(other: &SigningKeypair) -> Self {
74 Self(ed25519_dalek::Keypair {
75 public: PublicKey::from_bytes(&other.public()).unwrap(),
76 secret: SecretKey::from_bytes(&other.secret()).unwrap(),
77 })
78 }
79}
80
81impl SigningKeypair {
82 pub fn generate<R>(csprng: &mut R) -> Self
83 where
84 R: CryptoRng + RngCore,
85 {
86 let mut bytes = [0u8; 32];
89 csprng.fill_bytes(&mut bytes);
90
91 let sk = SecretKey::from_bytes(bytes.as_ref()).unwrap();
92
93 Self(Keypair {
94 public: (&sk).into(),
95 secret: sk,
96 })
97 }
98
99 pub fn try_from_bytes_slices(pubkey: PubKey, seckey: SecKey) -> Result<Self, CryptoError> {
100 Ok(Self(
101 ed25519_dalek::Keypair::from_bytes([seckey, pubkey].concat().as_slice())
102 .map_err(|e| CryptoError::InvalidSignatureBytesError(e.to_string()))?,
103 ))
104 }
105
106 pub fn try_from_str(public_key: &str, secret_key: &str) -> Result<Self, CryptoError> {
107 let pubkey = bytes_key_from_str(public_key)?;
108 let seckey = bytes_key_from_str(secret_key)?;
109 Self::try_from_bytes_slices(pubkey, seckey)
110 }
111
112 pub fn try_from_secret_bytes(secret_key_bytes: &SecKey) -> Result<Self, CryptoError> {
113 let sec_key = ed25519_dalek::SecretKey::from_bytes(secret_key_bytes)
114 .map_err(|e| CryptoError::InvalidSignatureBytesError(e.to_string()))?;
115 let pub_key = ed25519_dalek::PublicKey::from(&sec_key);
116 Ok(Self(ed25519_dalek::Keypair {
117 secret: sec_key,
118 public: pub_key,
119 }))
120 }
121
122 pub fn public(&self) -> PubKey {
123 self.0.public.to_bytes()
124 }
125
126 pub fn secret(&self) -> SecKey {
127 self.0.secret.to_bytes()
128 }
129
130 pub fn to_bytes(&self) -> Vec<u8> {
131 Vec::from(self.0.to_bytes())
132 }
133
134 pub fn sign(&self, msg: &[u8]) -> Signature {
135 Signature(self.0.sign(msg))
136 }
137}
138
139#[cfg(test)]
140mod tests {
141 use crate::common::test_utilities::{SIGNING_PUBLIC_KEY, SIGNING_SECRET_KEY};
142 use crate::identity::signing_keypair::SigningKeypair;
143
144 #[test]
145 fn should_create_keypair_when_keys_have_proper_length() {
146 let keypair = SigningKeypair::try_from_str(SIGNING_PUBLIC_KEY, SIGNING_SECRET_KEY);
148
149 assert!(keypair.is_ok());
151 }
152
153 #[test]
154 fn should_not_create_keypair_when_pub_key_is_too_short() {
155 let keypair = SigningKeypair::try_from_str("", SIGNING_SECRET_KEY);
157
158 assert!(keypair.is_err());
160 }
161
162 #[test]
163 fn should_not_create_keypair_when_pub_key_is_too_long() {
164 let keypair = SigningKeypair::try_from_str(
166 "1234567890123456789012345678901234567890123456789012345678901234567890",
167 SIGNING_SECRET_KEY,
168 );
169
170 assert!(keypair.is_err());
172 }
173
174 #[test]
175 fn should_not_create_keypair_when_sec_key_is_too_short() {
176 let keypair = SigningKeypair::try_from_str(SIGNING_PUBLIC_KEY, "");
178
179 assert!(keypair.is_err());
181 }
182
183 #[test]
184 fn should_not_create_keypair_when_sec_key_is_too_long() {
185 let keypair = SigningKeypair::try_from_str(
187 SIGNING_PUBLIC_KEY,
188 "1234567890123456789012345678901234567890123456789012345678901234567890",
189 );
190
191 assert!(keypair.is_err());
193 }
194}