cardano_crypto/cbor/
mod.rs

1//! CBOR serialization support for Cardano cryptographic types
2//!
3//! This module provides CBOR (Concise Binary Object Representation) encoding and decoding
4//! that is fully compatible with Cardano's `Cardano.Binary` module from cardano-base.
5//!
6//! # Cardano CBOR Format
7//!
8//! Cardano uses CBOR for all on-chain data serialization. The format follows RFC 8949
9//! with specific conventions:
10//!
11//! - **Verification keys**: CBOR byte string (major type 2) wrapping raw key bytes
12//! - **Signatures**: CBOR byte string (major type 2) wrapping raw signature bytes
13//! - **Signing keys**: Typically NOT serialized via CBOR to protect key material
14//!
15//! # Compatibility
16//!
17//! This implementation matches `encodeBytes`/`decodeBytes` from Haskell's `Cardano.Binary`:
18//! - Proper CBOR major type 2 headers with length encoding
19//! - Big-endian length fields for multi-byte lengths
20//! - Canonical encoding (minimal length headers)
21//!
22//! # Examples
23//!
24//! Basic CBOR encoding/decoding:
25//!
26//! ```rust
27//! use cardano_crypto::cbor::{encode_bytes, decode_bytes};
28//!
29//! # fn main() -> Result<(), cardano_crypto::cbor::CborError> {
30//! // Encode data as CBOR byte string
31//! let data = b"verification key data";
32//! let cbor_encoded = encode_bytes(data);
33//!
34//! // Decode CBOR byte string
35//! let decoded = decode_bytes(&cbor_encoded)?;
36//! assert_eq!(data, &decoded[..]);
37//! # Ok(())
38//! # }
39//! ```
40//!
41//! KES verification key serialization:
42//!
43//! ```rust
44//! use cardano_crypto::cbor::{encode_verification_key, decode_verification_key};
45//!
46//! # fn main() -> Result<(), cardano_crypto::cbor::CborError> {
47//! let vkey_raw = [0x42u8; 32]; // 32-byte Ed25519 verification key
48//! let cbor = encode_verification_key(&vkey_raw);
49//! let recovered = decode_verification_key(&cbor)?;
50//! assert_eq!(&vkey_raw[..], &recovered[..]);
51//! # Ok(())
52//! # }
53//! ```
54
55#[cfg(feature = "alloc")]
56use alloc::vec::Vec;
57
58// ============================================================================
59// Error Types
60// ============================================================================
61
62/// CBOR serialization errors
63///
64/// These errors correspond to failure modes in Cardano's CBOR processing.
65///
66/// # Example
67///
68/// ```rust
69/// use cardano_crypto::cbor::CborError;
70///
71/// let err = CborError::BufferTooSmall;
72/// let s = format!("{}", err);
73/// assert!(s.len() > 0);
74/// ```
75#[derive(Debug, Clone, Copy, PartialEq, Eq)]
76#[cfg_attr(feature = "thiserror", derive(thiserror::Error))]
77pub enum CborError {
78    /// Invalid CBOR encoding (malformed header or structure)
79    #[cfg_attr(feature = "thiserror", error("Invalid CBOR encoding"))]
80    InvalidEncoding,
81
82    /// Unexpected CBOR structure (wrong major type)
83    #[cfg_attr(feature = "thiserror", error("Unexpected CBOR structure"))]
84    UnexpectedStructure,
85
86    /// Serialization failed
87    #[cfg_attr(feature = "thiserror", error("Serialization failed"))]
88    SerializationFailed,
89
90    /// Deserialization failed
91    #[cfg_attr(feature = "thiserror", error("Deserialization failed"))]
92    DeserializationFailed,
93
94    /// Invalid byte length for the expected type
95    #[cfg_attr(feature = "thiserror", error("Invalid byte length"))]
96    InvalidLength,
97
98    /// Buffer too small to hold the data
99    #[cfg_attr(feature = "thiserror", error("Buffer too small"))]
100    BufferTooSmall,
101
102    /// Invalid UTF-8 in text string
103    #[cfg_attr(feature = "thiserror", error("Invalid UTF-8 encoding"))]
104    InvalidUtf8,
105
106    /// Unsupported CBOR feature or extension
107    #[cfg_attr(feature = "thiserror", error("Unsupported CBOR feature"))]
108    Unsupported,
109}
110
111#[cfg(not(feature = "thiserror"))]
112impl core::fmt::Display for CborError {
113    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
114        match self {
115            CborError::InvalidEncoding => write!(f, "Invalid CBOR encoding"),
116            CborError::UnexpectedStructure => write!(f, "Unexpected CBOR structure"),
117            CborError::SerializationFailed => write!(f, "Serialization failed"),
118            CborError::DeserializationFailed => write!(f, "Deserialization failed"),
119            CborError::InvalidLength => write!(f, "Invalid byte length"),
120            CborError::BufferTooSmall => write!(f, "Buffer too small"),
121            CborError::InvalidUtf8 => write!(f, "Invalid UTF-8 encoding"),
122            CborError::Unsupported => write!(f, "Unsupported CBOR feature"),
123        }
124    }
125}
126
127#[cfg(all(not(feature = "thiserror"), feature = "std"))]
128impl std::error::Error for CborError {}
129
130/// Encode bytes as CBOR byte string (major type 2)
131///
132/// This matches the behavior of `encodeBytes` from Haskell's Cardano.Binary module.
133///
134/// CBOR byte strings use major type 2:
135/// - For length < 24: single byte header
136/// - For length < 256: header + 1 byte length
137/// - For length < 65536: header + 2 bytes length
138/// - For length < 2^32: header + 4 bytes length
139///
140/// # Example
141///
142/// ```
143/// use cardano_crypto::cbor::encode_bytes;
144///
145/// let data = b"short data";
146/// let cbor = encode_bytes(data);
147/// assert!(cbor.len() > data.len()); // Has CBOR header
148/// ```
149#[cfg(feature = "alloc")]
150pub fn encode_bytes(bytes: &[u8]) -> Vec<u8> {
151    let len = bytes.len();
152    let mut result = Vec::new();
153
154    // Encode CBOR header based on length
155    if len < 24 {
156        // Short form: header byte contains length directly
157        result.push(0x40 | len as u8); // Major type 2, additional info = length
158    } else if len < 256 {
159        // 1-byte length
160        result.push(0x58); // Major type 2, additional info = 24 (1-byte uint follows)
161        result.push(len as u8);
162    } else if len < 65536 {
163        // 2-byte length
164        result.push(0x59); // Major type 2, additional info = 25 (2-byte uint follows)
165        result.extend_from_slice(&(len as u16).to_be_bytes());
166    } else {
167        // 4-byte length (for very large keys/signatures)
168        result.push(0x5a); // Major type 2, additional info = 26 (4-byte uint follows)
169        result.extend_from_slice(&(len as u32).to_be_bytes());
170    }
171
172    result.extend_from_slice(bytes);
173    result
174}
175
176/// Decode CBOR byte string (major type 2)
177///
178/// This matches the behavior of `decodeBytes` from Haskell's Cardano.Binary module.
179///
180/// # Example
181///
182/// ```
183/// use cardano_crypto::cbor::{encode_bytes, decode_bytes};
184///
185/// let original = b"test data";
186/// let cbor = encode_bytes(original);
187/// let decoded = decode_bytes(&cbor).unwrap();
188/// assert_eq!(original, &decoded[..]);
189/// ```
190#[cfg(feature = "alloc")]
191pub fn decode_bytes(cbor: &[u8]) -> Result<Vec<u8>, CborError> {
192    if cbor.is_empty() {
193        return Err(CborError::InvalidEncoding);
194    }
195
196    let header = cbor[0];
197    let major_type = (header >> 5) & 0x07;
198
199    // Must be major type 2 (byte string)
200    if major_type != 2 {
201        return Err(CborError::UnexpectedStructure);
202    }
203
204    let additional_info = header & 0x1f;
205
206    let (length, offset) = if additional_info < 24 {
207        // Short form: length encoded in header
208        (additional_info as usize, 1)
209    } else if additional_info == 24 {
210        // 1-byte length follows
211        if cbor.len() < 2 {
212            return Err(CborError::BufferTooSmall);
213        }
214        (cbor[1] as usize, 2)
215    } else if additional_info == 25 {
216        // 2-byte length follows
217        if cbor.len() < 3 {
218            return Err(CborError::BufferTooSmall);
219        }
220        let len = u16::from_be_bytes([cbor[1], cbor[2]]) as usize;
221        (len, 3)
222    } else if additional_info == 26 {
223        // 4-byte length follows
224        if cbor.len() < 5 {
225            return Err(CborError::BufferTooSmall);
226        }
227        let len = u32::from_be_bytes([cbor[1], cbor[2], cbor[3], cbor[4]]) as usize;
228        (len, 5)
229    } else {
230        return Err(CborError::InvalidEncoding);
231    };
232
233    // Check if we have enough bytes
234    if cbor.len() < offset + length {
235        return Err(CborError::BufferTooSmall);
236    }
237
238    // Extract the byte string
239    Ok(cbor[offset..offset + length].to_vec())
240}
241
242/// Encode verification key to CBOR format
243///
244/// Wraps the raw serialized verification key in CBOR byte string encoding.
245///
246/// # Example
247///
248/// ```
249/// use cardano_crypto::cbor::encode_verification_key;
250///
251/// let vkey_bytes = b"32-byte-verification-key-data!!!";
252/// let cbor = encode_verification_key(vkey_bytes);
253/// assert!(cbor.len() >= 32);
254/// ```
255#[cfg(feature = "alloc")]
256#[inline]
257pub fn encode_verification_key(raw_bytes: &[u8]) -> Vec<u8> {
258    encode_bytes(raw_bytes)
259}
260
261/// Decode verification key from CBOR format
262///
263/// Extracts raw bytes from CBOR byte string encoding.
264///
265/// # Example
266///
267/// ```
268/// use cardano_crypto::cbor::{encode_verification_key, decode_verification_key};
269///
270/// let vkey_bytes = b"verification-key-data-32-bytes!!";
271/// let cbor = encode_verification_key(vkey_bytes);
272/// let decoded = decode_verification_key(&cbor).unwrap();
273/// assert_eq!(vkey_bytes, &decoded[..]);
274/// ```
275#[cfg(feature = "alloc")]
276#[inline]
277pub fn decode_verification_key(cbor: &[u8]) -> Result<Vec<u8>, CborError> {
278    decode_bytes(cbor)
279}
280
281/// Encode signature to CBOR format
282///
283/// Wraps the raw serialized signature in CBOR byte string encoding.
284///
285/// # Example
286///
287/// ```
288/// use cardano_crypto::cbor::encode_signature;
289///
290/// // Use a 64-byte signature (common for Ed25519)
291/// let sig_bytes = vec![0u8; 64];
292/// let cbor = encode_signature(&sig_bytes);
293/// // CBOR wrapper adds at least a small header, so encoded length should be >= raw length
294/// assert!(cbor.len() >= sig_bytes.len());
295/// ```
296#[cfg(feature = "alloc")]
297#[inline]
298pub fn encode_signature(raw_bytes: &[u8]) -> Vec<u8> {
299    encode_bytes(raw_bytes)
300}
301
302/// Decode signature from CBOR format
303///
304/// Extracts raw bytes from CBOR byte string encoding.
305#[cfg(feature = "alloc")]
306#[inline]
307pub fn decode_signature(cbor: &[u8]) -> Result<Vec<u8>, CborError> {
308    decode_bytes(cbor)
309}
310
311// ============================================================================
312// CBOR Encoding/Decoding for KES Types
313// ============================================================================
314
315/// Encode KES verification key to CBOR format
316///
317/// Matches `encodeVerKeyKES` from Cardano.Crypto.KES.Class
318#[cfg(feature = "alloc")]
319#[inline]
320pub fn encode_verification_key_kes(raw_bytes: &[u8]) -> Vec<u8> {
321    encode_bytes(raw_bytes)
322}
323
324/// Decode KES verification key from CBOR format
325///
326/// Matches `decodeVerKeyKES` from Cardano.Crypto.KES.Class
327#[cfg(feature = "alloc")]
328#[inline]
329pub fn decode_verification_key_kes(cbor: &[u8]) -> Result<Vec<u8>, CborError> {
330    decode_bytes(cbor)
331}
332
333/// Encode KES signature to CBOR format
334///
335/// Matches `encodeSigKES` from Cardano.Crypto.KES.Class
336#[cfg(feature = "alloc")]
337#[inline]
338pub fn encode_signature_kes(raw_bytes: &[u8]) -> Vec<u8> {
339    encode_bytes(raw_bytes)
340}
341
342/// Decode KES signature from CBOR format
343///
344/// Matches `decodeSigKES` from Cardano.Crypto.KES.Class
345#[cfg(feature = "alloc")]
346#[inline]
347pub fn decode_signature_kes(cbor: &[u8]) -> Result<Vec<u8>, CborError> {
348    decode_bytes(cbor)
349}
350
351// ============================================================================
352// CBOR Encoding/Decoding for VRF Types
353// ============================================================================
354
355/// Encode VRF verification key to CBOR format
356///
357/// Matches `encodeVerKeyVRF` from Cardano.Crypto.VRF.Class
358#[cfg(feature = "alloc")]
359#[inline]
360pub fn encode_verification_key_vrf(raw_bytes: &[u8]) -> Vec<u8> {
361    encode_bytes(raw_bytes)
362}
363
364/// Decode VRF verification key from CBOR format
365///
366/// Matches `decodeVerKeyVRF` from Cardano.Crypto.VRF.Class
367#[cfg(feature = "alloc")]
368#[inline]
369pub fn decode_verification_key_vrf(cbor: &[u8]) -> Result<Vec<u8>, CborError> {
370    decode_bytes(cbor)
371}
372
373/// Encode VRF signing key to CBOR format
374///
375/// Matches `encodeSignKeyVRF` from Cardano.Crypto.VRF.Class
376///
377/// # Security Warning
378///
379/// VRF signing keys should be handled with extreme care.
380/// Consider whether CBOR serialization is truly necessary.
381#[cfg(feature = "alloc")]
382#[inline]
383pub fn encode_signing_key_vrf(raw_bytes: &[u8]) -> Vec<u8> {
384    encode_bytes(raw_bytes)
385}
386
387/// Decode VRF signing key from CBOR format
388///
389/// Matches `decodeSignKeyVRF` from Cardano.Crypto.VRF.Class
390#[cfg(feature = "alloc")]
391#[inline]
392pub fn decode_signing_key_vrf(cbor: &[u8]) -> Result<Vec<u8>, CborError> {
393    decode_bytes(cbor)
394}
395
396/// Encode VRF proof/certificate to CBOR format
397///
398/// Matches `encodeCertVRF` from Cardano.Crypto.VRF.Class
399#[cfg(feature = "alloc")]
400#[inline]
401pub fn encode_proof_vrf(raw_bytes: &[u8]) -> Vec<u8> {
402    encode_bytes(raw_bytes)
403}
404
405/// Decode VRF proof/certificate from CBOR format
406///
407/// Matches `decodeCertVRF` from Cardano.Crypto.VRF.Class
408#[cfg(feature = "alloc")]
409#[inline]
410pub fn decode_proof_vrf(cbor: &[u8]) -> Result<Vec<u8>, CborError> {
411    decode_bytes(cbor)
412}
413
414// ============================================================================
415// CBOR Encoding/Decoding for DSIGN Types
416// ============================================================================
417
418/// Encode DSIGN verification key to CBOR format
419///
420/// Matches `encodeVerKeyDSIGN` from Cardano.Crypto.DSIGN.Class
421#[cfg(feature = "alloc")]
422#[inline]
423pub fn encode_verification_key_dsign(raw_bytes: &[u8]) -> Vec<u8> {
424    encode_bytes(raw_bytes)
425}
426
427/// Decode DSIGN verification key from CBOR format
428///
429/// Matches `decodeVerKeyDSIGN` from Cardano.Crypto.DSIGN.Class
430#[cfg(feature = "alloc")]
431#[inline]
432pub fn decode_verification_key_dsign(cbor: &[u8]) -> Result<Vec<u8>, CborError> {
433    decode_bytes(cbor)
434}
435
436/// Encode DSIGN signing key to CBOR format
437///
438/// Matches `encodeSignKeyDSIGN` from Cardano.Crypto.DSIGN.Class
439///
440/// # Security Warning
441///
442/// DSIGN signing keys should be handled with extreme care.
443/// Consider whether CBOR serialization is truly necessary.
444#[cfg(feature = "alloc")]
445#[inline]
446pub fn encode_signing_key_dsign(raw_bytes: &[u8]) -> Vec<u8> {
447    encode_bytes(raw_bytes)
448}
449
450/// Decode DSIGN signing key from CBOR format
451///
452/// Matches `decodeSignKeyDSIGN` from Cardano.Crypto.DSIGN.Class
453#[cfg(feature = "alloc")]
454#[inline]
455pub fn decode_signing_key_dsign(cbor: &[u8]) -> Result<Vec<u8>, CborError> {
456    decode_bytes(cbor)
457}
458
459/// Encode DSIGN signature to CBOR format
460///
461/// Matches `encodeSigDSIGN` from Cardano.Crypto.DSIGN.Class
462#[cfg(feature = "alloc")]
463#[inline]
464pub fn encode_signature_dsign(raw_bytes: &[u8]) -> Vec<u8> {
465    encode_bytes(raw_bytes)
466}
467
468/// Decode DSIGN signature from CBOR format
469///
470/// Matches `decodeSigDSIGN` from Cardano.Crypto.DSIGN.Class
471#[cfg(feature = "alloc")]
472#[inline]
473pub fn decode_signature_dsign(cbor: &[u8]) -> Result<Vec<u8>, CborError> {
474    decode_bytes(cbor)
475}
476
477// ============================================================================
478// CBOR Encoding/Decoding for Hash Types
479// ============================================================================
480
481/// Encode a hash digest to CBOR format
482#[cfg(feature = "alloc")]
483#[inline]
484pub fn encode_hash(raw_bytes: &[u8]) -> Vec<u8> {
485    encode_bytes(raw_bytes)
486}
487
488/// Decode a hash digest from CBOR format
489#[cfg(feature = "alloc")]
490#[inline]
491pub fn decode_hash(cbor: &[u8]) -> Result<Vec<u8>, CborError> {
492    decode_bytes(cbor)
493}
494
495// ============================================================================
496// CBOR Encoding/Decoding for VRF Output Types
497// ============================================================================
498
499/// Encode VRF output to CBOR format
500///
501/// Matches `encodeOutputVRF` from Cardano.Crypto.VRF.Class
502#[cfg(feature = "alloc")]
503#[inline]
504pub fn encode_output_vrf(raw_bytes: &[u8]) -> Vec<u8> {
505    encode_bytes(raw_bytes)
506}
507
508/// Decode VRF output from CBOR format
509///
510/// Matches `decodeOutputVRF` from Cardano.Crypto.VRF.Class
511#[cfg(feature = "alloc")]
512#[inline]
513pub fn decode_output_vrf(cbor: &[u8]) -> Result<Vec<u8>, CborError> {
514    decode_bytes(cbor)
515}
516
517// ============================================================================
518// CBOR Encoding/Decoding for KES Signing Keys
519// ============================================================================
520
521/// Encode KES signing key to CBOR format
522///
523/// Matches `encodeSignKeyKES` from Cardano.Crypto.KES.Class
524///
525/// # Security Warning
526///
527/// KES signing keys should be handled with extreme care.
528/// Consider whether CBOR serialization is truly necessary.
529#[cfg(feature = "alloc")]
530#[inline]
531pub fn encode_signing_key_kes(raw_bytes: &[u8]) -> Vec<u8> {
532    encode_bytes(raw_bytes)
533}
534
535/// Decode KES signing key from CBOR format
536///
537/// Matches `decodeSignKeyKES` from Cardano.Crypto.KES.Class
538#[cfg(feature = "alloc")]
539#[inline]
540pub fn decode_signing_key_kes(cbor: &[u8]) -> Result<Vec<u8>, CborError> {
541    decode_bytes(cbor)
542}
543
544// ============================================================================
545// Size Calculation Utilities
546// ============================================================================
547
548/// Calculate CBOR encoded size for a byte string
549///
550/// Returns the total number of bytes needed to encode a byte string of the given length.
551/// This is useful for pre-allocating buffers.
552///
553/// # Example
554///
555/// ```rust
556/// use cardano_crypto::cbor::encoded_size_bytes;
557///
558/// assert_eq!(encoded_size_bytes(5), 6);   // 1 byte header + 5 bytes data
559/// assert_eq!(encoded_size_bytes(100), 102); // 2 byte header + 100 bytes data
560/// assert_eq!(encoded_size_bytes(300), 303); // 3 byte header + 300 bytes data
561/// ```
562#[must_use]
563pub const fn encoded_size_bytes(len: usize) -> usize {
564    if len < 24 {
565        1 + len
566    } else if len < 256 {
567        2 + len
568    } else if len < 65536 {
569        3 + len
570    } else {
571        5 + len
572    }
573}
574
575/// Size expression for CBOR verification key encoding
576///
577/// Matches `encodedVerKeyDSIGNSizeExpr` pattern from cardano-base
578#[must_use]
579pub const fn encoded_verification_key_size(raw_size: usize) -> usize {
580    encoded_size_bytes(raw_size)
581}
582
583/// Size expression for CBOR signature encoding
584///
585/// Matches `encodedSigDSIGNSizeExpr` pattern from cardano-base
586#[must_use]
587pub const fn encoded_signature_size(raw_size: usize) -> usize {
588    encoded_size_bytes(raw_size)
589}
590
591// ============================================================================
592// DSIGN Size Expressions (matching cardano-crypto-class)
593// ============================================================================
594
595/// Size expression for encoded DSIGN verification key
596///
597/// Returns the CBOR encoded size for an Ed25519 verification key (32 bytes).
598/// Matches `encodedVerKeyDSIGNSizeExpr` from cardano-crypto-class.
599///
600/// # Example
601///
602/// ```rust
603/// use cardano_crypto::cbor::encoded_verification_key_dsign_size;
604///
605/// // Ed25519 verification key is 32 bytes
606/// assert_eq!(encoded_verification_key_dsign_size(), 34); // 2-byte header + 32 bytes
607/// ```
608#[must_use]
609pub const fn encoded_verification_key_dsign_size() -> usize {
610    // Ed25519 verification key: 32 bytes
611    encoded_size_bytes(32)
612}
613
614/// Size expression for encoded DSIGN signing key
615///
616/// Returns the CBOR encoded size for an Ed25519 signing key (64 bytes - includes seed + pubkey).
617/// Matches `encodedSignKeyDSIGNSizeExpr` from cardano-crypto-class.
618///
619/// # Example
620///
621/// ```rust
622/// use cardano_crypto::cbor::encoded_signing_key_dsign_size;
623///
624/// // Ed25519 signing key is 64 bytes (seed + public key)
625/// assert_eq!(encoded_signing_key_dsign_size(), 66); // 2-byte header + 64 bytes
626/// ```
627#[must_use]
628pub const fn encoded_signing_key_dsign_size() -> usize {
629    // Ed25519 signing key: 64 bytes (seed || public_key)
630    encoded_size_bytes(64)
631}
632
633/// Size expression for encoded DSIGN signature
634///
635/// Returns the CBOR encoded size for an Ed25519 signature (64 bytes).
636/// Matches `encodedSigDSIGNSizeExpr` from cardano-crypto-class.
637///
638/// # Example
639///
640/// ```rust
641/// use cardano_crypto::cbor::encoded_signature_dsign_size;
642///
643/// // Ed25519 signature is 64 bytes
644/// assert_eq!(encoded_signature_dsign_size(), 66); // 2-byte header + 64 bytes
645/// ```
646#[must_use]
647pub const fn encoded_signature_dsign_size() -> usize {
648    // Ed25519 signature: 64 bytes
649    encoded_size_bytes(64)
650}
651
652// ============================================================================
653// VRF Size Expressions (matching cardano-crypto-class)
654// ============================================================================
655
656/// Size expression for encoded VRF verification key
657///
658/// Returns the CBOR encoded size for a VRF verification key (32 bytes).
659/// Matches `encodedVerKeyVRFSizeExpr` from cardano-crypto-class.
660///
661/// # Example
662///
663/// ```rust
664/// use cardano_crypto::cbor::encoded_verification_key_vrf_size;
665///
666/// // VRF verification key is 32 bytes
667/// assert_eq!(encoded_verification_key_vrf_size(), 34); // 2-byte header + 32 bytes
668/// ```
669#[must_use]
670pub const fn encoded_verification_key_vrf_size() -> usize {
671    // VRF verification key: 32 bytes (Ed25519 point)
672    encoded_size_bytes(32)
673}
674
675/// Size expression for encoded VRF signing key
676///
677/// Returns the CBOR encoded size for a VRF signing key (64 bytes).
678/// Matches `encodedSignKeyVRFSizeExpr` from cardano-crypto-class.
679///
680/// # Example
681///
682/// ```rust
683/// use cardano_crypto::cbor::encoded_signing_key_vrf_size;
684///
685/// // VRF signing key is 64 bytes
686/// assert_eq!(encoded_signing_key_vrf_size(), 66); // 2-byte header + 64 bytes
687/// ```
688#[must_use]
689pub const fn encoded_signing_key_vrf_size() -> usize {
690    // VRF signing key: 64 bytes
691    encoded_size_bytes(64)
692}
693
694/// Size expression for encoded VRF proof (Draft-03)
695///
696/// Returns the CBOR encoded size for a VRF Draft-03 proof (80 bytes).
697/// Matches `encodedCertVRFSizeExpr` from cardano-crypto-class.
698///
699/// # Example
700///
701/// ```rust
702/// use cardano_crypto::cbor::encoded_proof_vrf_draft03_size;
703///
704/// // VRF Draft-03 proof is 80 bytes
705/// assert_eq!(encoded_proof_vrf_draft03_size(), 82); // 2-byte header + 80 bytes
706/// ```
707#[must_use]
708pub const fn encoded_proof_vrf_draft03_size() -> usize {
709    // VRF Draft-03 proof: 80 bytes
710    encoded_size_bytes(80)
711}
712
713/// Size expression for encoded VRF proof (Draft-13)
714///
715/// Returns the CBOR encoded size for a VRF Draft-13 proof (128 bytes).
716///
717/// # Example
718///
719/// ```rust
720/// use cardano_crypto::cbor::encoded_proof_vrf_draft13_size;
721///
722/// // VRF Draft-13 proof is 128 bytes
723/// assert_eq!(encoded_proof_vrf_draft13_size(), 130); // 2-byte header + 128 bytes
724/// ```
725#[must_use]
726pub const fn encoded_proof_vrf_draft13_size() -> usize {
727    // VRF Draft-13 proof: 128 bytes
728    encoded_size_bytes(128)
729}
730
731/// Size expression for encoded VRF output
732///
733/// Returns the CBOR encoded size for a VRF output (64 bytes SHA-512 hash).
734/// Matches `encodedOutputVRFSizeExpr` from cardano-crypto-class.
735///
736/// # Example
737///
738/// ```rust
739/// use cardano_crypto::cbor::encoded_output_vrf_size;
740///
741/// // VRF output is 64 bytes (SHA-512 hash)
742/// assert_eq!(encoded_output_vrf_size(), 66); // 2-byte header + 64 bytes
743/// ```
744#[must_use]
745pub const fn encoded_output_vrf_size() -> usize {
746    // VRF output: 64 bytes (SHA-512)
747    encoded_size_bytes(64)
748}
749
750// ============================================================================
751// KES Size Expressions (matching cardano-crypto-class)
752// ============================================================================
753
754/// Size expression for encoded KES verification key
755///
756/// KES verification keys are 32 bytes (Ed25519 verification key).
757/// Matches `encodedVerKeyKESSizeExpr` from cardano-crypto-class.
758///
759/// # Example
760///
761/// ```rust
762/// use cardano_crypto::cbor::encoded_verification_key_kes_size;
763///
764/// assert_eq!(encoded_verification_key_kes_size(), 34); // 2-byte header + 32 bytes
765/// ```
766#[must_use]
767pub const fn encoded_verification_key_kes_size() -> usize {
768    // KES verification key: 32 bytes
769    encoded_size_bytes(32)
770}
771
772/// Size expression for encoded Sum6KES signing key
773///
774/// Sum6KES signing key size varies but is typically large.
775/// This returns the size for a freshly generated Sum6KES key.
776///
777/// # Example
778///
779/// ```rust
780/// use cardano_crypto::cbor::encoded_signing_key_sum6kes_size;
781///
782/// let size = encoded_signing_key_sum6kes_size();
783/// assert!(size > 100); // Sum6KES keys are large
784/// ```
785#[must_use]
786pub const fn encoded_signing_key_sum6kes_size() -> usize {
787    // Sum6KES signing key: 2112 bytes -> 2115 bytes CBOR (3 byte header + 2112 bytes)
788    encoded_size_bytes(2112)
789}
790
791/// Size expression for encoded Sum6KES signature
792///
793/// Returns the CBOR encoded size for a Sum6KES signature.
794/// Matches `encodedSigKESSizeExpr` from cardano-crypto-class.
795///
796/// # Example
797///
798/// ```rust
799/// use cardano_crypto::cbor::encoded_signature_sum6kes_size;
800///
801/// let size = encoded_signature_sum6kes_size();
802/// assert!(size > 400); // Sum6KES signatures are 448 bytes
803/// ```
804#[must_use]
805pub const fn encoded_signature_sum6kes_size() -> usize {
806    // Sum6KES signature: 448 bytes
807    encoded_size_bytes(448)
808}
809
810// ============================================================================
811// Hash Size Expressions
812// ============================================================================
813
814/// Size expression for encoded Blake2b-224 hash
815///
816/// # Example
817///
818/// ```rust
819/// use cardano_crypto::cbor::encoded_hash_blake2b224_size;
820///
821/// assert_eq!(encoded_hash_blake2b224_size(), 30); // 2-byte header + 28 bytes
822/// ```
823#[must_use]
824pub const fn encoded_hash_blake2b224_size() -> usize {
825    encoded_size_bytes(28)
826}
827
828/// Size expression for encoded Blake2b-256 hash
829///
830/// # Example
831///
832/// ```rust
833/// use cardano_crypto::cbor::encoded_hash_blake2b256_size;
834///
835/// assert_eq!(encoded_hash_blake2b256_size(), 34); // 2-byte header + 32 bytes
836/// ```
837#[must_use]
838pub const fn encoded_hash_blake2b256_size() -> usize {
839    encoded_size_bytes(32)
840}
841
842// ============================================================================
843// Traits for CBOR Serialization (matching Cardano.Binary)
844// ============================================================================
845
846/// Trait for types that can be encoded to CBOR
847///
848/// This trait matches the `ToCBOR` typeclass from Cardano.Binary.
849/// Types implementing this trait can be serialized to CBOR format.
850pub trait ToCbor {
851    /// Encode this value to CBOR bytes
852    #[cfg(feature = "alloc")]
853    fn to_cbor(&self) -> Vec<u8>;
854
855    /// Returns the encoded size in bytes
856    fn encoded_size(&self) -> usize;
857}
858
859/// Trait for types that can be decoded from CBOR
860///
861/// This trait matches the `FromCBOR` typeclass from Cardano.Binary.
862/// Types implementing this trait can be deserialized from CBOR format.
863pub trait FromCbor: Sized {
864    /// Decode this value from CBOR bytes
865    fn from_cbor(bytes: &[u8]) -> Result<Self, CborError>;
866}
867
868// ============================================================================
869// ToCbor/FromCbor implementations for primitive arrays
870// ============================================================================
871
872impl ToCbor for [u8; 32] {
873    #[cfg(feature = "alloc")]
874    fn to_cbor(&self) -> Vec<u8> {
875        encode_bytes(self)
876    }
877
878    fn encoded_size(&self) -> usize {
879        encoded_size_bytes(32)
880    }
881}
882
883impl FromCbor for [u8; 32] {
884    fn from_cbor(bytes: &[u8]) -> Result<Self, CborError> {
885        let decoded = decode_bytes(bytes)?;
886        if decoded.len() != 32 {
887            return Err(CborError::InvalidLength);
888        }
889        let mut arr = [0u8; 32];
890        arr.copy_from_slice(&decoded);
891        Ok(arr)
892    }
893}
894
895impl ToCbor for [u8; 64] {
896    #[cfg(feature = "alloc")]
897    fn to_cbor(&self) -> Vec<u8> {
898        encode_bytes(self)
899    }
900
901    fn encoded_size(&self) -> usize {
902        encoded_size_bytes(64)
903    }
904}
905
906impl FromCbor for [u8; 64] {
907    fn from_cbor(bytes: &[u8]) -> Result<Self, CborError> {
908        let decoded = decode_bytes(bytes)?;
909        if decoded.len() != 64 {
910            return Err(CborError::InvalidLength);
911        }
912        let mut arr = [0u8; 64];
913        arr.copy_from_slice(&decoded);
914        Ok(arr)
915    }
916}
917
918impl ToCbor for [u8; 80] {
919    #[cfg(feature = "alloc")]
920    fn to_cbor(&self) -> Vec<u8> {
921        encode_bytes(self)
922    }
923
924    fn encoded_size(&self) -> usize {
925        encoded_size_bytes(80)
926    }
927}
928
929impl FromCbor for [u8; 80] {
930    fn from_cbor(bytes: &[u8]) -> Result<Self, CborError> {
931        let decoded = decode_bytes(bytes)?;
932        if decoded.len() != 80 {
933            return Err(CborError::InvalidLength);
934        }
935        let mut arr = [0u8; 80];
936        arr.copy_from_slice(&decoded);
937        Ok(arr)
938    }
939}
940
941#[cfg(feature = "alloc")]
942impl ToCbor for Vec<u8> {
943    fn to_cbor(&self) -> Vec<u8> {
944        encode_bytes(self)
945    }
946
947    fn encoded_size(&self) -> usize {
948        encoded_size_bytes(self.len())
949    }
950}
951
952#[cfg(feature = "alloc")]
953impl FromCbor for Vec<u8> {
954    fn from_cbor(bytes: &[u8]) -> Result<Self, CborError> {
955        decode_bytes(bytes)
956    }
957}
958
959#[cfg(test)]
960mod tests {
961    use super::*;
962
963    #[test]
964    fn test_cbor_encode_decode_short() {
965        // Test with short byte string (< 24 bytes)
966        let data = vec![0x01, 0x02, 0x03, 0x04, 0x05];
967        let encoded = encode_bytes(&data);
968
969        // Should be: header (0x45 = major type 2, length 5) + data
970        assert_eq!(encoded[0], 0x45);
971        assert_eq!(&encoded[1..], &data[..]);
972
973        let decoded = decode_bytes(&encoded).unwrap();
974        assert_eq!(decoded, data);
975    }
976
977    #[test]
978    fn test_cbor_encode_decode_medium() {
979        // Test with medium byte string (< 256 bytes)
980        let data = vec![0xAB; 200];
981        let encoded = encode_bytes(&data);
982
983        // Should be: header (0x58) + length byte (200) + data
984        assert_eq!(encoded[0], 0x58);
985        assert_eq!(encoded[1], 200);
986
987        let decoded = decode_bytes(&encoded).unwrap();
988        assert_eq!(decoded, data);
989    }
990
991    #[test]
992    fn test_cbor_encode_decode_large() {
993        // Test with large byte string (>= 256 bytes)
994        let data = vec![0xCD; 500];
995        let encoded = encode_bytes(&data);
996
997        // Should be: header (0x59) + 2-byte length (500) + data
998        assert_eq!(encoded[0], 0x59);
999        assert_eq!(u16::from_be_bytes([encoded[1], encoded[2]]), 500);
1000
1001        let decoded = decode_bytes(&encoded).unwrap();
1002        assert_eq!(decoded, data);
1003    }
1004
1005    #[test]
1006    fn test_cbor_verification_key_roundtrip() {
1007        // Simulate a 32-byte Ed25519 verification key
1008        let vk_bytes = vec![0x12; 32];
1009
1010        let encoded = encode_verification_key(&vk_bytes);
1011        let decoded = decode_verification_key(&encoded).unwrap();
1012
1013        assert_eq!(decoded, vk_bytes);
1014    }
1015
1016    #[test]
1017    fn test_cbor_signature_roundtrip() {
1018        // Simulate a 64-byte Ed25519 signature
1019        let sig_bytes = vec![0x34; 64];
1020
1021        let encoded = encode_signature(&sig_bytes);
1022        let decoded = decode_signature(&encoded).unwrap();
1023
1024        assert_eq!(decoded, sig_bytes);
1025    }
1026
1027    #[test]
1028    fn test_cbor_invalid_major_type() {
1029        // Try to decode a CBOR integer (major type 0) as byte string
1030        let invalid = vec![0x00]; // Integer 0
1031
1032        let result = decode_bytes(&invalid);
1033        assert!(matches!(result, Err(CborError::UnexpectedStructure)));
1034    }
1035
1036    #[test]
1037    fn test_cbor_buffer_too_small() {
1038        // Header says 1-byte length follows, but buffer is too short
1039        let invalid = vec![0x58]; // Missing length byte
1040
1041        let result = decode_bytes(&invalid);
1042        assert!(matches!(result, Err(CborError::BufferTooSmall)));
1043    }
1044
1045    #[test]
1046    fn test_cbor_empty() {
1047        let result = decode_bytes(&[]);
1048        assert!(matches!(result, Err(CborError::InvalidEncoding)));
1049    }
1050
1051    #[test]
1052    fn test_encoded_size_bytes() {
1053        // Test size calculations
1054        assert_eq!(encoded_size_bytes(0), 1);
1055        assert_eq!(encoded_size_bytes(23), 24);
1056        assert_eq!(encoded_size_bytes(24), 26); // 2 byte header
1057        assert_eq!(encoded_size_bytes(255), 257);
1058        assert_eq!(encoded_size_bytes(256), 259); // 3 byte header
1059        assert_eq!(encoded_size_bytes(65535), 65538);
1060        assert_eq!(encoded_size_bytes(65536), 65541); // 5 byte header
1061    }
1062
1063    #[test]
1064    fn test_kes_verification_key_cbor() {
1065        // Test with typical Sum6KES verification key size (64 bytes for Sum6)
1066        let vk_bytes = vec![0xAA; 64];
1067        let encoded = encode_verification_key_kes(&vk_bytes);
1068        let decoded = decode_verification_key_kes(&encoded).unwrap();
1069        assert_eq!(decoded, vk_bytes);
1070    }
1071
1072    #[test]
1073    fn test_kes_signature_cbor() {
1074        // Test with typical KES signature size
1075        let sig_bytes = vec![0xBB; 448]; // Sum6KES signature is ~448 bytes
1076        let encoded = encode_signature_kes(&sig_bytes);
1077        let decoded = decode_signature_kes(&encoded).unwrap();
1078        assert_eq!(decoded, sig_bytes);
1079    }
1080
1081    #[test]
1082    fn test_kes_signing_key_cbor() {
1083        // Test with KES signing key
1084        let sk_bytes = vec![0xCC; 128];
1085        let encoded = encode_signing_key_kes(&sk_bytes);
1086        let decoded = decode_signing_key_kes(&encoded).unwrap();
1087        assert_eq!(decoded, sk_bytes);
1088    }
1089
1090    #[test]
1091    fn test_vrf_proof_cbor() {
1092        // VRF proofs are 80 bytes
1093        let proof_bytes = vec![0xCC; 80];
1094        let encoded = encode_proof_vrf(&proof_bytes);
1095        let decoded = decode_proof_vrf(&encoded).unwrap();
1096        assert_eq!(decoded, proof_bytes);
1097    }
1098
1099    #[test]
1100    fn test_vrf_output_cbor() {
1101        // VRF output is 64 bytes
1102        let output_bytes = vec![0xDD; 64];
1103        let encoded = encode_output_vrf(&output_bytes);
1104        let decoded = decode_output_vrf(&encoded).unwrap();
1105        assert_eq!(decoded, output_bytes);
1106    }
1107
1108    #[test]
1109    fn test_dsign_roundtrip() {
1110        // Ed25519 verification key (32 bytes)
1111        let vk = vec![0x11; 32];
1112        let vk_cbor = encode_verification_key_dsign(&vk);
1113        assert_eq!(decode_verification_key_dsign(&vk_cbor).unwrap(), vk);
1114
1115        // Ed25519 signature (64 bytes)
1116        let sig = vec![0x22; 64];
1117        let sig_cbor = encode_signature_dsign(&sig);
1118        assert_eq!(decode_signature_dsign(&sig_cbor).unwrap(), sig);
1119    }
1120
1121    #[test]
1122    fn test_hash_cbor() {
1123        // Blake2b-256 hash (32 bytes)
1124        let hash = vec![0xDD; 32];
1125        let encoded = encode_hash(&hash);
1126        let decoded = decode_hash(&encoded).unwrap();
1127        assert_eq!(decoded, hash);
1128    }
1129
1130    #[test]
1131    fn test_cbor_edge_cases() {
1132        // Empty byte string
1133        let empty: Vec<u8> = vec![];
1134        let encoded = encode_bytes(&empty);
1135        assert_eq!(encoded, vec![0x40]); // Just the header
1136        assert_eq!(decode_bytes(&encoded).unwrap(), empty);
1137
1138        // Exactly 23 bytes (boundary)
1139        let data_23 = vec![0xFF; 23];
1140        let encoded_23 = encode_bytes(&data_23);
1141        assert_eq!(encoded_23[0], 0x57); // 0x40 + 23
1142        assert_eq!(decode_bytes(&encoded_23).unwrap(), data_23);
1143
1144        // Exactly 24 bytes (first to need 2-byte header)
1145        let data_24 = vec![0xEE; 24];
1146        let encoded_24 = encode_bytes(&data_24);
1147        assert_eq!(encoded_24[0], 0x58);
1148        assert_eq!(encoded_24[1], 24);
1149        assert_eq!(decode_bytes(&encoded_24).unwrap(), data_24);
1150
1151        // Exactly 255 bytes (boundary)
1152        let data_255 = vec![0xDD; 255];
1153        let encoded_255 = encode_bytes(&data_255);
1154        assert_eq!(encoded_255[0], 0x58);
1155        assert_eq!(encoded_255[1], 255);
1156        assert_eq!(decode_bytes(&encoded_255).unwrap(), data_255);
1157
1158        // Exactly 256 bytes (first to need 3-byte header)
1159        let data_256 = vec![0xCC; 256];
1160        let encoded_256 = encode_bytes(&data_256);
1161        assert_eq!(encoded_256[0], 0x59);
1162        assert_eq!(u16::from_be_bytes([encoded_256[1], encoded_256[2]]), 256);
1163        assert_eq!(decode_bytes(&encoded_256).unwrap(), data_256);
1164    }
1165
1166    #[test]
1167    fn test_to_cbor_trait_array_32() {
1168        let arr: [u8; 32] = [0x42; 32];
1169        let encoded = arr.to_cbor();
1170        let decoded = <[u8; 32]>::from_cbor(&encoded).unwrap();
1171        assert_eq!(arr, decoded);
1172        assert_eq!(arr.encoded_size(), encoded.len());
1173    }
1174
1175    #[test]
1176    fn test_to_cbor_trait_array_64() {
1177        let arr: [u8; 64] = [0x43; 64];
1178        let encoded = arr.to_cbor();
1179        let decoded = <[u8; 64]>::from_cbor(&encoded).unwrap();
1180        assert_eq!(arr, decoded);
1181        assert_eq!(arr.encoded_size(), encoded.len());
1182    }
1183
1184    #[test]
1185    fn test_to_cbor_trait_array_80() {
1186        let arr: [u8; 80] = [0x44; 80];
1187        let encoded = arr.to_cbor();
1188        let decoded = <[u8; 80]>::from_cbor(&encoded).unwrap();
1189        assert_eq!(arr, decoded);
1190        assert_eq!(arr.encoded_size(), encoded.len());
1191    }
1192
1193    #[test]
1194    fn test_to_cbor_trait_vec() {
1195        let vec = vec![0x45u8; 100];
1196        let encoded = vec.to_cbor();
1197        let decoded = Vec::<u8>::from_cbor(&encoded).unwrap();
1198        assert_eq!(vec, decoded);
1199        assert_eq!(vec.encoded_size(), encoded.len());
1200    }
1201
1202    #[test]
1203    fn test_from_cbor_invalid_length() {
1204        // Try to decode a 31-byte payload as [u8; 32]
1205        let data = vec![0x42u8; 31];
1206        let encoded = encode_bytes(&data);
1207        let result = <[u8; 32]>::from_cbor(&encoded);
1208        assert!(matches!(result, Err(CborError::InvalidLength)));
1209    }
1210
1211    #[test]
1212    fn test_vrf_output_trait_roundtrip() {
1213        use crate::vrf::{OutputVrf, VrfDraft03};
1214
1215        let seed = [42u8; 32];
1216        let (secret_key, public_key) = VrfDraft03::keypair_from_seed(&seed);
1217        let proof = VrfDraft03::prove(&secret_key, b"test").unwrap();
1218        let output_bytes = VrfDraft03::verify(&public_key, &proof, b"test").unwrap();
1219
1220        let output = OutputVrf::new(output_bytes);
1221        let encoded = output.to_cbor();
1222        let decoded = OutputVrf::from_cbor(&encoded).unwrap();
1223        assert_eq!(output.as_bytes(), decoded.as_bytes());
1224    }
1225
1226    #[test]
1227    fn test_certified_vrf_cbor_roundtrip() {
1228        use crate::vrf::CertifiedVrf;
1229
1230        let seed = [42u8; 32];
1231        let (secret_key, _) = crate::vrf::VrfDraft03::keypair_from_seed(&seed);
1232        let certified = CertifiedVrf::eval(&secret_key, b"test message").unwrap();
1233
1234        let encoded = certified.to_cbor();
1235        let decoded = CertifiedVrf::from_cbor(&encoded).unwrap();
1236
1237        assert_eq!(
1238            certified.get_output().as_bytes(),
1239            decoded.get_output().as_bytes()
1240        );
1241        assert_eq!(certified.get_proof(), decoded.get_proof());
1242    }
1243
1244    #[test]
1245    fn test_signed_dsign_cbor_roundtrip() {
1246        use crate::dsign::{DsignAlgorithm, Ed25519, SignedDsign};
1247
1248        let signing_key = Ed25519::gen_key(&[42u8; 32]);
1249        let signed = SignedDsign::<Ed25519>::sign(&signing_key, b"test message");
1250
1251        let encoded = signed.to_cbor();
1252        let decoded = SignedDsign::<Ed25519>::from_cbor(&encoded).unwrap();
1253
1254        assert_eq!(
1255            signed.get_signature().as_bytes(),
1256            decoded.get_signature().as_bytes()
1257        );
1258    }
1259
1260    #[test]
1261    fn test_ed25519_verification_key_cbor_roundtrip() {
1262        use crate::dsign::ed25519::Ed25519VerificationKey;
1263        use crate::dsign::{DsignAlgorithm, Ed25519};
1264
1265        let signing_key = Ed25519::gen_key(&[42u8; 32]);
1266        let vk = Ed25519::derive_verification_key(&signing_key);
1267
1268        let encoded = vk.to_cbor();
1269        let decoded = Ed25519VerificationKey::from_cbor(&encoded).unwrap();
1270
1271        assert_eq!(vk.as_bytes(), decoded.as_bytes());
1272    }
1273
1274    #[test]
1275    fn test_ed25519_signature_cbor_roundtrip() {
1276        use crate::dsign::ed25519::Ed25519Signature;
1277        use crate::dsign::{DsignAlgorithm, Ed25519};
1278
1279        let signing_key = Ed25519::gen_key(&[42u8; 32]);
1280        let sig = Ed25519::sign(&signing_key, b"test message");
1281
1282        let encoded = sig.to_cbor();
1283        let decoded = Ed25519Signature::from_cbor(&encoded).unwrap();
1284
1285        assert_eq!(sig.as_bytes(), decoded.as_bytes());
1286    }
1287
1288    // ========================================================================
1289    // Size Expression Tests (matching cardano-crypto-class patterns)
1290    // ========================================================================
1291
1292    #[test]
1293    fn test_dsign_size_expressions() {
1294        // Ed25519 verification key: 32 bytes -> 34 bytes CBOR (2 byte header + 32 bytes)
1295        assert_eq!(encoded_verification_key_dsign_size(), 34);
1296
1297        // Ed25519 signing key: 64 bytes -> 66 bytes CBOR
1298        assert_eq!(encoded_signing_key_dsign_size(), 66);
1299
1300        // Ed25519 signature: 64 bytes -> 66 bytes CBOR
1301        assert_eq!(encoded_signature_dsign_size(), 66);
1302
1303        // Verify against actual encoding
1304        let vk = vec![0x42u8; 32];
1305        assert_eq!(
1306            encode_verification_key_dsign(&vk).len(),
1307            encoded_verification_key_dsign_size()
1308        );
1309
1310        let sig = vec![0x43u8; 64];
1311        assert_eq!(
1312            encode_signature_dsign(&sig).len(),
1313            encoded_signature_dsign_size()
1314        );
1315    }
1316
1317    #[test]
1318    fn test_vrf_size_expressions() {
1319        // VRF verification key: 32 bytes -> 34 bytes CBOR
1320        assert_eq!(encoded_verification_key_vrf_size(), 34);
1321
1322        // VRF signing key: 64 bytes -> 66 bytes CBOR
1323        assert_eq!(encoded_signing_key_vrf_size(), 66);
1324
1325        // VRF Draft-03 proof: 80 bytes -> 82 bytes CBOR
1326        assert_eq!(encoded_proof_vrf_draft03_size(), 82);
1327
1328        // VRF Draft-13 proof: 128 bytes -> 130 bytes CBOR
1329        assert_eq!(encoded_proof_vrf_draft13_size(), 130);
1330
1331        // VRF output: 64 bytes -> 66 bytes CBOR
1332        assert_eq!(encoded_output_vrf_size(), 66);
1333
1334        // Verify against actual encoding
1335        let vk = vec![0x44u8; 32];
1336        assert_eq!(
1337            encode_verification_key_vrf(&vk).len(),
1338            encoded_verification_key_vrf_size()
1339        );
1340
1341        let proof = vec![0x45u8; 80];
1342        assert_eq!(
1343            encode_proof_vrf(&proof).len(),
1344            encoded_proof_vrf_draft03_size()
1345        );
1346
1347        let output = vec![0x46u8; 64];
1348        assert_eq!(encode_output_vrf(&output).len(), encoded_output_vrf_size());
1349    }
1350
1351    #[test]
1352    fn test_kes_size_expressions() {
1353        // KES verification key: 32 bytes -> 34 bytes CBOR
1354        assert_eq!(encoded_verification_key_kes_size(), 34);
1355
1356        // Sum6KES signing key: 2112 bytes -> 2115 bytes CBOR (3 byte header + 2112 bytes)
1357        assert_eq!(encoded_signing_key_sum6kes_size(), 2115);
1358
1359        // Sum6KES signature: 448 bytes -> 451 bytes CBOR (3 byte header + 448 bytes)
1360        assert_eq!(encoded_signature_sum6kes_size(), 451);
1361
1362        // Verify against actual encoding
1363        let vk = vec![0x47u8; 32];
1364        assert_eq!(
1365            encode_verification_key_kes(&vk).len(),
1366            encoded_verification_key_kes_size()
1367        );
1368
1369        let sig = vec![0x48u8; 448];
1370        assert_eq!(
1371            encode_signature_kes(&sig).len(),
1372            encoded_signature_sum6kes_size()
1373        );
1374    }
1375
1376    #[test]
1377    fn test_hash_size_expressions() {
1378        // Blake2b-224: 28 bytes -> 30 bytes CBOR (2 byte header + 28 bytes)
1379        assert_eq!(encoded_hash_blake2b224_size(), 30);
1380
1381        // Blake2b-256: 32 bytes -> 34 bytes CBOR (2 byte header + 32 bytes)
1382        assert_eq!(encoded_hash_blake2b256_size(), 34);
1383
1384        // Verify against actual encoding
1385        let hash224 = vec![0x49u8; 28];
1386        assert_eq!(encode_hash(&hash224).len(), encoded_hash_blake2b224_size());
1387
1388        let hash256 = vec![0x4Au8; 32];
1389        assert_eq!(encode_hash(&hash256).len(), encoded_hash_blake2b256_size());
1390    }
1391
1392    #[test]
1393    fn test_size_expression_generic() {
1394        // Test the generic size functions
1395        assert_eq!(encoded_verification_key_size(32), 34);
1396        assert_eq!(encoded_verification_key_size(64), 66);
1397        assert_eq!(encoded_signature_size(64), 66);
1398        assert_eq!(encoded_signature_size(448), 451);
1399    }
1400
1401    #[test]
1402    fn test_size_expression_boundaries() {
1403        // Test boundary conditions
1404        // 0-23 bytes: 1 byte header
1405        assert_eq!(encoded_size_bytes(0), 1);
1406        assert_eq!(encoded_size_bytes(23), 24);
1407
1408        // 24-255 bytes: 2 byte header
1409        assert_eq!(encoded_size_bytes(24), 26);
1410        assert_eq!(encoded_size_bytes(255), 257);
1411
1412        // 256-65535 bytes: 3 byte header
1413        assert_eq!(encoded_size_bytes(256), 259);
1414        assert_eq!(encoded_size_bytes(65535), 65538);
1415
1416        // 65536+ bytes: 5 byte header
1417        assert_eq!(encoded_size_bytes(65536), 65541);
1418    }
1419
1420    // ========================================================================
1421    // Serialization Roundtrip Tests (matching cardano-crypto-tests patterns)
1422    // ========================================================================
1423
1424    #[test]
1425    fn test_dsign_verification_key_serialization_roundtrip() {
1426        use crate::dsign::{DsignAlgorithm, Ed25519};
1427
1428        // Generate a real verification key
1429        let signing_key = Ed25519::gen_key(&[0xABu8; 32]);
1430        let vk = Ed25519::derive_verification_key(&signing_key);
1431
1432        // Raw serialization roundtrip
1433        let raw = Ed25519::raw_serialize_verification_key(&vk);
1434        let recovered = Ed25519::raw_deserialize_verification_key(raw).unwrap();
1435        assert_eq!(vk.as_bytes(), recovered.as_bytes());
1436
1437        // CBOR serialization roundtrip
1438        let cbor = encode_verification_key_dsign(raw);
1439        let decoded = decode_verification_key_dsign(&cbor).unwrap();
1440        assert_eq!(raw, &decoded[..]);
1441    }
1442
1443    #[test]
1444    fn test_dsign_signature_serialization_roundtrip() {
1445        use crate::dsign::{DsignAlgorithm, Ed25519};
1446
1447        let signing_key = Ed25519::gen_key(&[0xCDu8; 32]);
1448        let sig = Ed25519::sign(&signing_key, b"test message");
1449
1450        // Raw serialization roundtrip
1451        let raw = Ed25519::raw_serialize_signature(&sig);
1452        let recovered = Ed25519::raw_deserialize_signature(raw).unwrap();
1453        assert_eq!(sig.as_bytes(), recovered.as_bytes());
1454
1455        // CBOR serialization roundtrip
1456        let cbor = encode_signature_dsign(raw);
1457        let decoded = decode_signature_dsign(&cbor).unwrap();
1458        assert_eq!(raw, &decoded[..]);
1459    }
1460
1461    #[test]
1462    fn test_vrf_verification_key_serialization_roundtrip() {
1463        use crate::vrf::{VrfAlgorithm, VrfDraft03};
1464
1465        let seed = [0xEFu8; 32];
1466        let (_, vk) = VrfDraft03::keypair_from_seed(&seed);
1467
1468        // Raw serialization roundtrip
1469        let raw = VrfDraft03::raw_serialize_verification_key(&vk);
1470        let recovered = VrfDraft03::raw_deserialize_verification_key(raw).unwrap();
1471        assert_eq!(vk, recovered);
1472
1473        // CBOR serialization roundtrip
1474        let cbor = encode_verification_key_vrf(raw);
1475        let decoded = decode_verification_key_vrf(&cbor).unwrap();
1476        assert_eq!(raw, &decoded[..]);
1477    }
1478
1479    #[test]
1480    fn test_vrf_proof_serialization_roundtrip() {
1481        use crate::vrf::{VrfAlgorithm, VrfDraft03};
1482
1483        let seed = [0x12u8; 32];
1484        let (sk, _) = VrfDraft03::keypair_from_seed(&seed);
1485        let proof = VrfDraft03::prove(&sk, b"test input").unwrap();
1486
1487        // Raw serialization roundtrip
1488        let raw = VrfDraft03::raw_serialize_proof(&proof);
1489        let recovered = VrfDraft03::raw_deserialize_proof(raw).unwrap();
1490        assert_eq!(proof, recovered);
1491
1492        // CBOR serialization roundtrip
1493        let cbor = encode_proof_vrf(raw);
1494        let decoded = decode_proof_vrf(&cbor).unwrap();
1495        assert_eq!(raw, &decoded[..]);
1496    }
1497
1498    #[test]
1499    fn test_kes_verification_key_serialization_roundtrip() {
1500        use crate::kes::{KesAlgorithm, Sum6Kes};
1501
1502        let seed = [0x34u8; 32];
1503        let signing_key = Sum6Kes::gen_key_kes_from_seed_bytes(&seed).unwrap();
1504        let vk = Sum6Kes::derive_verification_key(&signing_key).unwrap();
1505
1506        // Raw serialization roundtrip
1507        let raw = Sum6Kes::raw_serialize_verification_key_kes(&vk);
1508        let recovered = Sum6Kes::raw_deserialize_verification_key_kes(&raw).unwrap();
1509        assert_eq!(vk, recovered);
1510
1511        // CBOR serialization roundtrip
1512        let cbor = encode_verification_key_kes(&raw);
1513        let decoded = decode_verification_key_kes(&cbor).unwrap();
1514        assert_eq!(raw, decoded);
1515    }
1516
1517    #[test]
1518    fn test_kes_signature_serialization_roundtrip() {
1519        use crate::kes::{KesAlgorithm, Sum6Kes};
1520
1521        let seed = [0x56u8; 32];
1522        let signing_key = Sum6Kes::gen_key_kes_from_seed_bytes(&seed).unwrap();
1523        let signature = Sum6Kes::sign_kes(&(), 0, b"test message", &signing_key).unwrap();
1524
1525        // Raw serialization roundtrip
1526        let raw = Sum6Kes::raw_serialize_signature_kes(&signature);
1527        let _recovered = Sum6Kes::raw_deserialize_signature_kes(&raw).unwrap();
1528        // Note: KES signature comparison would need proper Eq impl
1529
1530        // CBOR serialization roundtrip
1531        let cbor = encode_signature_kes(&raw);
1532        let decoded = decode_signature_kes(&cbor).unwrap();
1533        assert_eq!(raw, decoded);
1534    }
1535}