ave_identity/keys/
public_key.rs1use crate::common::{AlgorithmIdentifiedBytes, base64_encoding};
34use crate::error::CryptoError;
35use borsh::{BorshDeserialize, BorshSerialize};
36use serde::{Deserialize, Serialize};
37use std::fmt;
38
39use super::{DSAlgorithm, SignatureIdentifier};
40
41#[derive(
80 Clone,
81 PartialEq,
82 Eq,
83 Hash,
84 BorshSerialize,
85 BorshDeserialize,
86 Ord,
87 PartialOrd,
88)]
89pub struct PublicKey {
90 inner: AlgorithmIdentifiedBytes<DSAlgorithm>,
91}
92
93impl PublicKey {
94 pub fn new(
96 algorithm: DSAlgorithm,
97 key_bytes: Vec<u8>,
98 ) -> Result<Self, CryptoError> {
99 let expected_len = algorithm.public_key_length();
100 Ok(Self {
101 inner: AlgorithmIdentifiedBytes::new(
102 algorithm,
103 key_bytes,
104 expected_len,
105 )?,
106 })
107 }
108
109 #[inline]
111 pub fn algorithm(&self) -> DSAlgorithm {
112 self.inner.algorithm
113 }
114
115 #[inline]
117 pub fn as_bytes(&self) -> &[u8] {
118 self.inner.as_bytes()
119 }
120
121 #[inline]
123 pub fn to_bytes(&self) -> Vec<u8> {
124 self.inner
125 .to_bytes_with_prefix(self.inner.algorithm.identifier())
126 }
127
128 pub fn from_bytes(bytes: &[u8]) -> Result<Self, CryptoError> {
130 if bytes.is_empty() {
131 return Err(CryptoError::InvalidPublicKey(
132 "Empty bytes".to_string(),
133 ));
134 }
135
136 let algorithm = DSAlgorithm::from_identifier(bytes[0])?;
137 let expected_len = algorithm.public_key_length();
138
139 let inner = AlgorithmIdentifiedBytes::from_bytes_with_prefix(
140 bytes,
141 DSAlgorithm::from_identifier,
142 expected_len,
143 "PublicKey",
144 )?;
145
146 Ok(Self { inner })
147 }
148
149 #[inline]
151 fn to_base64(&self) -> String {
152 if self.is_empty() {
154 String::new()
155 } else {
156 let algorithm_char = self.inner.algorithm.identifier() as char;
159 let data_base64 = base64_encoding::encode(&self.inner.bytes);
160 format!("{}{}", algorithm_char, data_base64)
161 }
162 }
163
164 pub fn verify(
166 &self,
167 message: &[u8],
168 signature: &SignatureIdentifier,
169 ) -> Result<(), CryptoError> {
170 if self.inner.algorithm != signature.algorithm() {
171 return Err(CryptoError::InvalidSignatureFormat(format!(
172 "Algorithm mismatch: key is {}, signature is {}",
173 self.inner.algorithm,
174 signature.algorithm()
175 )));
176 }
177 signature.verify(message, &self.inner.bytes)
178 }
179
180 #[inline]
185 pub fn is_empty(&self) -> bool {
186 self.inner.bytes.is_empty()
187 }
188}
189
190impl Default for PublicKey {
191 fn default() -> Self {
192 Self {
193 inner: AlgorithmIdentifiedBytes {
194 algorithm: DSAlgorithm::Ed25519,
195 bytes: Vec::new(),
196 },
197 }
198 }
199}
200
201impl fmt::Debug for PublicKey {
202 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
203 f.debug_struct("PublicKey")
204 .field("algorithm", &self.inner.algorithm)
205 .field("key", &base64_encoding::encode(&self.inner.bytes))
206 .finish()
207 }
208}
209
210impl fmt::Display for PublicKey {
211 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
212 write!(f, "{}", self.to_base64())
213 }
214}
215
216impl Serialize for PublicKey {
217 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
218 where
219 S: serde::Serializer,
220 {
221 serializer.serialize_str(&self.to_base64())
222 }
223}
224
225impl<'de> Deserialize<'de> for PublicKey {
226 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
227 where
228 D: serde::Deserializer<'de>,
229 {
230 let s = <String as Deserialize>::deserialize(deserializer)?;
231 s.parse().map_err(serde::de::Error::custom)
232 }
233}
234
235impl std::str::FromStr for PublicKey {
236 type Err = CryptoError;
237
238 fn from_str(s: &str) -> Result<Self, Self::Err> {
239 if s.is_empty() {
241 return Ok(Self::default());
242 }
243
244 let mut chars = s.chars();
247 let algorithm_char = chars.next().ok_or_else(|| {
248 CryptoError::InvalidPublicKey("Empty string".to_string())
249 })?;
250
251 let algorithm = DSAlgorithm::from_identifier(algorithm_char as u8)?;
252
253 let data_str: String = chars.collect();
255 let key_bytes = base64_encoding::decode(&data_str)
256 .map_err(|e| CryptoError::Base64DecodeError(e.to_string()))?;
257
258 let expected_len = algorithm.public_key_length();
260 if key_bytes.len() != expected_len {
261 return Err(CryptoError::InvalidDataLength {
262 expected: expected_len,
263 actual: key_bytes.len(),
264 });
265 }
266
267 Ok(Self {
268 inner: AlgorithmIdentifiedBytes {
269 algorithm,
270 bytes: key_bytes,
271 },
272 })
273 }
274}
275
276#[cfg(test)]
277mod tests {
278 use super::*;
279 use crate::keys::{DSA, Ed25519Signer};
280
281 #[test]
282 fn test_public_key_wrapper() {
283 let signer = Ed25519Signer::generate().unwrap();
284 let message = b"Test message";
285
286 let signature = signer.sign(message).unwrap();
287
288 let public_key =
290 PublicKey::new(DSAlgorithm::Ed25519, signer.public_key_bytes())
291 .unwrap();
292
293 assert!(public_key.verify(message, &signature).is_ok());
295
296 let key_str = public_key.to_string();
298
299 assert!(
301 key_str.starts_with('E'),
302 "Ed25519 public key should start with 'E', got: {}",
303 key_str
304 );
305
306 let parsed: PublicKey = key_str.parse().unwrap();
307 assert_eq!(public_key, parsed);
308 }
309
310 #[test]
311 fn test_public_key_serde() {
312 let signer = Ed25519Signer::generate().unwrap();
313
314 let public_key =
315 PublicKey::new(DSAlgorithm::Ed25519, signer.public_key_bytes())
316 .unwrap();
317
318 let json = serde_json::to_string(&public_key).unwrap();
320
321 let deserialized: PublicKey = serde_json::from_str(&json).unwrap();
323
324 assert_eq!(public_key, deserialized);
325 }
326
327 #[test]
328 fn test_default_public_key() {
329 let default_key = PublicKey::default();
330
331 assert_eq!(default_key.algorithm(), DSAlgorithm::Ed25519);
333
334 assert_eq!(default_key.as_bytes().len(), 0);
336
337 assert!(default_key.is_empty());
339 }
340
341 #[test]
342 fn test_is_empty() {
343 let empty_key = PublicKey::default();
345 assert!(empty_key.is_empty());
346
347 let signer = Ed25519Signer::generate().unwrap();
349 let real_key =
350 PublicKey::new(DSAlgorithm::Ed25519, signer.public_key_bytes())
351 .unwrap();
352 assert!(!real_key.is_empty());
353 }
354}