Skip to main content

ave_identity/keys/
signature_identifier.rs

1//! Digital signature identifier with algorithm identification
2
3use crate::common::{AlgorithmIdentifiedBytes, base64_encoding};
4use crate::error::CryptoError;
5use borsh::{BorshDeserialize, BorshSerialize};
6use ed25519_dalek::{Signature as Ed25519Signature, Verifier, VerifyingKey};
7use serde::{Deserialize, Serialize};
8use std::fmt;
9
10use super::{DSAlgorithm, ED25519_PUBLIC_KEY_LENGTH, ED25519_SIGNATURE_LENGTH};
11
12/// Digital signature identifier with algorithm identification
13///
14/// The output contains:
15/// - 1 byte: algorithm identifier
16/// - N bytes: actual signature value (length depends on algorithm)
17#[derive(
18    Clone,
19    PartialEq,
20    Eq,
21    Hash,
22    BorshSerialize,
23    BorshDeserialize,
24    Ord,
25    PartialOrd,
26)]
27pub struct SignatureIdentifier {
28    inner: AlgorithmIdentifiedBytes<DSAlgorithm>,
29}
30
31impl SignatureIdentifier {
32    /// Create a new signature identifier
33    pub fn new(
34        algorithm: DSAlgorithm,
35        signature: Vec<u8>,
36    ) -> Result<Self, CryptoError> {
37        let expected_len = algorithm.signature_length();
38        Ok(Self {
39            inner: AlgorithmIdentifiedBytes::new(
40                algorithm,
41                signature,
42                expected_len,
43            )?,
44        })
45    }
46
47    /// Get the algorithm used
48    #[inline]
49    pub fn algorithm(&self) -> DSAlgorithm {
50        self.inner.algorithm
51    }
52
53    /// Get the signature bytes (without identifier)
54    #[inline]
55    pub fn signature_bytes(&self) -> &[u8] {
56        self.inner.as_bytes()
57    }
58
59    /// Get the full bytes including algorithm identifier
60    #[inline]
61    pub fn to_bytes(&self) -> Vec<u8> {
62        self.inner
63            .to_bytes_with_prefix(self.inner.algorithm.identifier())
64    }
65
66    /// Parse from bytes (includes algorithm identifier)
67    pub fn from_bytes(bytes: &[u8]) -> Result<Self, CryptoError> {
68        if bytes.is_empty() {
69            return Err(CryptoError::InvalidSignatureFormat(
70                "Empty bytes".to_string(),
71            ));
72        }
73
74        let algorithm = DSAlgorithm::from_identifier(bytes[0])?;
75        let expected_len = algorithm.signature_length();
76
77        let inner = AlgorithmIdentifiedBytes::from_bytes_with_prefix(
78            bytes,
79            DSAlgorithm::from_identifier,
80            expected_len,
81            "SignatureIdentifier",
82        )?;
83
84        Ok(Self { inner })
85    }
86
87    // Internal method for Base64 encoding
88    #[inline]
89    fn to_base64(&self) -> String {
90        // Format: algorithm_char + base64(signature_bytes)
91        // Example: "E" + base64(signature) for Ed25519
92        let algorithm_char = self.inner.algorithm.identifier() as char;
93        let data_base64 = base64_encoding::encode(&self.inner.bytes);
94        format!("{}{}", algorithm_char, data_base64)
95    }
96
97    /// Verify the signature against the message and public key
98    pub fn verify(
99        &self,
100        message: &[u8],
101        public_key: &[u8],
102    ) -> Result<(), CryptoError> {
103        match self.inner.algorithm {
104            DSAlgorithm::Ed25519 => {
105                // Verify public key length
106                if public_key.len() != ED25519_PUBLIC_KEY_LENGTH {
107                    return Err(CryptoError::InvalidPublicKey(format!(
108                        "Invalid public key length: expected {} bytes, got {}",
109                        ED25519_PUBLIC_KEY_LENGTH,
110                        public_key.len()
111                    )));
112                }
113
114                // Verify signature length
115                if self.inner.bytes.len() != ED25519_SIGNATURE_LENGTH {
116                    return Err(CryptoError::InvalidSignatureFormat(format!(
117                        "Invalid signature length: expected {} bytes, got {}",
118                        ED25519_SIGNATURE_LENGTH,
119                        self.inner.bytes.len()
120                    )));
121                }
122
123                let verifying_key = VerifyingKey::from_bytes(
124                    public_key.try_into().map_err(|_| {
125                        CryptoError::InvalidPublicKey(
126                            "Invalid length".to_string(),
127                        )
128                    })?,
129                )
130                .map_err(|e| CryptoError::InvalidPublicKey(e.to_string()))?;
131
132                let signature = Ed25519Signature::from_bytes(
133                    self.inner.bytes.as_slice().try_into().map_err(|_| {
134                        CryptoError::InvalidSignatureFormat(
135                            "Invalid length".to_string(),
136                        )
137                    })?,
138                );
139
140                verifying_key
141                    .verify(message, &signature)
142                    .map_err(|_| CryptoError::SignatureVerificationFailed)
143            }
144        }
145    }
146}
147
148impl fmt::Debug for SignatureIdentifier {
149    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
150        f.debug_struct("SignatureIdentifier")
151            .field("algorithm", &self.inner.algorithm)
152            .field("signature", &base64_encoding::encode(&self.inner.bytes))
153            .finish()
154    }
155}
156
157impl fmt::Display for SignatureIdentifier {
158    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
159        write!(f, "{}", self.to_base64())
160    }
161}
162
163impl Serialize for SignatureIdentifier {
164    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
165    where
166        S: serde::Serializer,
167    {
168        serializer.serialize_str(&self.to_base64())
169    }
170}
171
172impl<'de> Deserialize<'de> for SignatureIdentifier {
173    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
174    where
175        D: serde::Deserializer<'de>,
176    {
177        let s = <String as Deserialize>::deserialize(deserializer)?;
178        s.parse().map_err(serde::de::Error::custom)
179    }
180}
181
182impl std::str::FromStr for SignatureIdentifier {
183    type Err = CryptoError;
184
185    fn from_str(s: &str) -> Result<Self, Self::Err> {
186        // Format: algorithm_char + base64(signature_bytes)
187        // First character is the algorithm identifier
188        let mut chars = s.chars();
189        let algorithm_char = chars.next().ok_or_else(|| {
190            CryptoError::InvalidSignatureFormat("Empty string".to_string())
191        })?;
192
193        let algorithm = DSAlgorithm::from_identifier(algorithm_char as u8)?;
194
195        // Rest is base64-encoded signature data
196        let data_str: String = chars.collect();
197        let signature_bytes = base64_encoding::decode(&data_str)
198            .map_err(|e| CryptoError::Base64DecodeError(e.to_string()))?;
199
200        // Validate length
201        let expected_len = algorithm.signature_length();
202        if signature_bytes.len() != expected_len {
203            return Err(CryptoError::InvalidDataLength {
204                expected: expected_len,
205                actual: signature_bytes.len(),
206            });
207        }
208
209        Ok(Self {
210            inner: AlgorithmIdentifiedBytes {
211                algorithm,
212                bytes: signature_bytes,
213            },
214        })
215    }
216}
217
218#[cfg(test)]
219mod tests {
220    use super::*;
221    use crate::keys::{DSA, Ed25519Signer};
222
223    #[test]
224    fn test_signature_to_string() {
225        let signer = Ed25519Signer::generate().unwrap();
226        let message = b"Hello, World!";
227
228        let signature = signer.sign(message).unwrap();
229        let sig_str = signature.to_string();
230
231        // Should be able to parse back
232        let parsed: SignatureIdentifier = sig_str.parse().unwrap();
233        assert_eq!(signature, parsed);
234    }
235
236    #[test]
237    fn test_signature_verify_wrong_message() {
238        let signer = Ed25519Signer::generate().unwrap();
239        let message = b"Hello, World!";
240
241        let signature = signer.sign(message).unwrap();
242        let public_key = signer.public_key();
243
244        // Should fail with wrong message
245        let result = signature.verify(b"Wrong message", public_key.as_bytes());
246        assert!(result.is_err());
247    }
248
249    #[test]
250    fn test_signature_bytes_roundtrip() {
251        let signer = Ed25519Signer::generate().unwrap();
252        let message = b"Test data";
253
254        let signature = signer.sign(message).unwrap();
255        let bytes = signature.to_bytes();
256
257        // First byte should be algorithm identifier 'E'
258        assert_eq!(bytes[0], b'E');
259
260        // Should parse back correctly
261        let parsed = SignatureIdentifier::from_bytes(&bytes).unwrap();
262        assert_eq!(signature, parsed);
263    }
264
265    #[test]
266    fn test_algorithm_detection() {
267        let signer = Ed25519Signer::generate().unwrap();
268        let message = b"Test data";
269
270        let signature = signer.sign(message).unwrap();
271        let sig_str = signature.to_string();
272
273        // Parse should automatically detect Ed25519
274        let parsed: SignatureIdentifier = sig_str.parse().unwrap();
275        assert_eq!(parsed.algorithm(), DSAlgorithm::Ed25519);
276    }
277
278    #[test]
279    fn test_serde_serialization() {
280        let signer = Ed25519Signer::generate().unwrap();
281        let message = b"Test serialization";
282
283        let signature = signer.sign(message).unwrap();
284
285        // Serialize to JSON
286        let json = serde_json::to_string(&signature).unwrap();
287
288        // Deserialize back
289        let deserialized: SignatureIdentifier =
290            serde_json::from_str(&json).unwrap();
291
292        assert_eq!(signature, deserialized);
293    }
294
295    #[test]
296    fn test_invalid_signature_length() {
297        // Create an invalid signature with wrong length
298        let invalid_sig = SignatureIdentifier::new(
299            DSAlgorithm::Ed25519,
300            vec![0u8; 32], // Only 32 bytes instead of 64
301        );
302
303        // SignatureIdentifier::new should catch this
304        assert!(invalid_sig.is_err());
305    }
306}