Skip to main content

ave_identity/keys/
public_key.rs

1//! Public key wrapper with algorithm identification
2//!
3//! This module provides a generic public key wrapper that can hold keys from any
4//! supported digital signature algorithm. The public key includes a 1-byte algorithm
5//! identifier prefix, enabling automatic algorithm detection when parsing.
6//!
7//! ## Example
8//!
9//! ```
10//! use ave_identity::keys::{KeyPair, KeyPairAlgorithm, PublicKey};
11//!
12//! // Generate a key pair
13//! let keypair = KeyPair::generate(KeyPairAlgorithm::Ed25519).unwrap();
14//!
15//! // Get the public key
16//! let public_key = keypair.public_key();
17//!
18//! // Sign a message
19//! let message = b"Hello, World!";
20//! let signature = keypair.sign(message).unwrap();
21//!
22//! // Verify with the public key
23//! assert!(public_key.verify(message, &signature).is_ok());
24//!
25//! // Serialize to string (includes algorithm identifier)
26//! let key_str = public_key.to_string();
27//!
28//! // Parse from string (automatically detects algorithm)
29//! let parsed: PublicKey = key_str.parse().unwrap();
30//! assert_eq!(public_key, parsed);
31//! ```
32
33use 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/// Public key wrapper with algorithm identification
42///
43/// This structure provides a generic wrapper for public keys from any supported
44/// digital signature algorithm (currently Ed25519). The key includes a 1-byte
45/// algorithm identifier prefix that enables automatic algorithm detection.
46///
47/// ## Structure
48///
49/// - **1 byte**: Algorithm identifier (e.g., 'E' for Ed25519)
50/// - **N bytes**: Public key bytes (length depends on algorithm)
51///
52/// ## Features
53///
54/// - **Algorithm agnostic**: Works with any DSA implementation
55/// - **Automatic detection**: Algorithm is detected from the identifier byte
56/// - **Serialization**: Supports Base64, Borsh, and Serde JSON serialization
57/// - **Verification**: Direct signature verification without needing the algorithm type
58///
59/// ## Example
60///
61/// ```
62/// use ave_identity::keys::{KeyPair, KeyPairAlgorithm, DSAlgorithm};
63///
64/// // Generate a keypair and extract public key
65/// let keypair = KeyPair::generate(KeyPairAlgorithm::Ed25519).unwrap();
66/// let public_key = keypair.public_key();
67///
68/// // Check the algorithm
69/// assert_eq!(public_key.algorithm(), DSAlgorithm::Ed25519);
70///
71/// // Get raw bytes (32 bytes for Ed25519)
72/// let key_bytes = public_key.as_bytes();
73/// assert_eq!(key_bytes.len(), 32);
74///
75/// // Serialize to string with algorithm identifier
76/// let key_str = public_key.to_string();
77/// println!("Public key: {}", key_str);
78/// ```
79#[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    /// Create a new public key
95    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    /// Get the algorithm
110    #[inline]
111    pub fn algorithm(&self) -> DSAlgorithm {
112        self.inner.algorithm
113    }
114
115    /// Get the key bytes (without identifier)
116    #[inline]
117    pub fn as_bytes(&self) -> &[u8] {
118        self.inner.as_bytes()
119    }
120
121    /// Get the full bytes including algorithm identifier
122    #[inline]
123    pub fn to_bytes(&self) -> Vec<u8> {
124        self.inner
125            .to_bytes_with_prefix(self.inner.algorithm.identifier())
126    }
127
128    /// Parse from bytes (includes algorithm identifier)
129    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    // Internal method for Base64 encoding
150    #[inline]
151    fn to_base64(&self) -> String {
152        // Special case: empty key serializes as empty string
153        if self.is_empty() {
154            String::new()
155        } else {
156            // Format: algorithm_char + base64(key_bytes)
157            // Example: "E" + base64(public_key) for Ed25519
158            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    /// Verify a signature with this public key
165    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    /// Check if this is an empty public key (created via Default)
181    ///
182    /// Returns `true` if the key bytes are empty, which indicates
183    /// this public key was created using `Default::default()`.
184    #[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        // Special case: empty string deserializes to default (empty) key
240        if s.is_empty() {
241            return Ok(Self::default());
242        }
243
244        // Format: algorithm_char + base64(key_bytes)
245        // First character is the algorithm identifier
246        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        // Rest is base64-encoded key data
254        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        // Validate length
259        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        // Create public key wrapper
289        let public_key =
290            PublicKey::new(DSAlgorithm::Ed25519, signer.public_key_bytes())
291                .unwrap();
292
293        // Verify using wrapper
294        assert!(public_key.verify(message, &signature).is_ok());
295
296        // Test serialization
297        let key_str = public_key.to_string();
298
299        // Ed25519 public key should start with 'E'
300        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        // Serialize to JSON
319        let json = serde_json::to_string(&public_key).unwrap();
320
321        // Deserialize back
322        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        // Should have Ed25519 algorithm
332        assert_eq!(default_key.algorithm(), DSAlgorithm::Ed25519);
333
334        // Should have empty bytes
335        assert_eq!(default_key.as_bytes().len(), 0);
336
337        // Should be marked as empty
338        assert!(default_key.is_empty());
339    }
340
341    #[test]
342    fn test_is_empty() {
343        // Default key should be empty
344        let empty_key = PublicKey::default();
345        assert!(empty_key.is_empty());
346
347        // Real key should not be empty
348        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}