4040
4141use curve25519_dalek:: {
4242 constants:: RISTRETTO_BASEPOINT_POINT , constants:: RISTRETTO_BASEPOINT_TABLE ,
43- ristretto:: RistrettoPoint , scalar:: Scalar , traits:: VartimeMultiscalarMul ,
43+ ristretto:: CompressedRistretto , ristretto:: RistrettoPoint , scalar:: Scalar ,
44+ traits:: VartimeMultiscalarMul ,
4445} ;
4546use rand_core:: { CryptoRng , RngCore } ;
4647use sha3:: digest:: { ExtendableOutput , Update } ;
@@ -115,6 +116,113 @@ impl<T: AsRef<[u8]>> From<T> for Identity {
115116 }
116117}
117118
119+ // Helper: decode a 32-byte slice into a canonical `Scalar`.
120+ fn scalar_from_canonical ( bytes : [ u8 ; 32 ] ) -> Option < Scalar > {
121+ Scalar :: from_canonical_bytes ( bytes) . into ( )
122+ }
123+
124+ // Helper: decode a 32-byte slice into a `RistrettoPoint`.
125+ fn point_from_bytes ( bytes : [ u8 ; 32 ] ) -> Option < RistrettoPoint > {
126+ CompressedRistretto ( bytes) . decompress ( )
127+ }
128+
129+ impl PublicKey {
130+ /// Serialize the public key to its compressed byte encoding.
131+ pub fn to_bytes ( & self ) -> [ u8 ; PK_BYTES ] {
132+ self . 0 . compress ( ) . to_bytes ( )
133+ }
134+
135+ /// Deserialize a public key from its compressed byte encoding.
136+ ///
137+ /// Returns `None` if `bytes` is not a valid compressed Ristretto point.
138+ pub fn from_bytes ( bytes : & [ u8 ; PK_BYTES ] ) -> Option < Self > {
139+ point_from_bytes ( * bytes) . map ( PublicKey )
140+ }
141+ }
142+
143+ impl SecretKey {
144+ /// Serialize the secret key to its canonical byte encoding.
145+ pub fn to_bytes ( & self ) -> [ u8 ; SK_BYTES ] {
146+ self . 0 . to_bytes ( )
147+ }
148+
149+ /// Deserialize a secret key from its canonical byte encoding.
150+ ///
151+ /// Returns `None` if `bytes` is not a canonical scalar encoding.
152+ pub fn from_bytes ( bytes : & [ u8 ; SK_BYTES ] ) -> Option < Self > {
153+ scalar_from_canonical ( * bytes) . map ( SecretKey )
154+ }
155+ }
156+
157+ impl UserSecretKey {
158+ /// Serialize the user secret key to a 96-byte encoding.
159+ ///
160+ /// Layout: `y (32 bytes) || gr (32 bytes, compressed) || id (32 bytes)`.
161+ pub fn to_bytes ( & self ) -> [ u8 ; USK_BYTES ] {
162+ let mut out = [ 0u8 ; USK_BYTES ] ;
163+ out[ ..32 ] . copy_from_slice ( & self . y . to_bytes ( ) ) ;
164+ out[ 32 ..64 ] . copy_from_slice ( & self . gr . compress ( ) . to_bytes ( ) ) ;
165+ out[ 64 ..96 ] . copy_from_slice ( & self . id . 0 ) ;
166+ out
167+ }
168+
169+ /// Deserialize a user secret key from its 96-byte encoding.
170+ ///
171+ /// Returns `None` if `y` is not a canonical scalar or if `gr` is not a
172+ /// valid compressed Ristretto point. See [`UserSecretKey::to_bytes`] for
173+ /// the encoding layout.
174+ pub fn from_bytes ( bytes : & [ u8 ; USK_BYTES ] ) -> Option < Self > {
175+ let mut y_bytes = [ 0u8 ; 32 ] ;
176+ let mut gr_bytes = [ 0u8 ; 32 ] ;
177+ let mut id_bytes = [ 0u8 ; IDENTITY_BYTES ] ;
178+ y_bytes. copy_from_slice ( & bytes[ ..32 ] ) ;
179+ gr_bytes. copy_from_slice ( & bytes[ 32 ..64 ] ) ;
180+ id_bytes. copy_from_slice ( & bytes[ 64 ..96 ] ) ;
181+
182+ let y = scalar_from_canonical ( y_bytes) ?;
183+ let gr = point_from_bytes ( gr_bytes) ?;
184+
185+ Some ( UserSecretKey {
186+ y,
187+ gr,
188+ id : Identity ( id_bytes) ,
189+ } )
190+ }
191+ }
192+
193+ impl Signature {
194+ /// Serialize the signature to a 96-byte encoding.
195+ ///
196+ /// Layout: `ga (32 bytes, compressed) || b (32 bytes) || gr (32 bytes, compressed)`.
197+ pub fn to_bytes ( & self ) -> [ u8 ; SIG_BYTES ] {
198+ let mut out = [ 0u8 ; SIG_BYTES ] ;
199+ out[ ..32 ] . copy_from_slice ( & self . ga . compress ( ) . to_bytes ( ) ) ;
200+ out[ 32 ..64 ] . copy_from_slice ( & self . b . to_bytes ( ) ) ;
201+ out[ 64 ..96 ] . copy_from_slice ( & self . gr . compress ( ) . to_bytes ( ) ) ;
202+ out
203+ }
204+
205+ /// Deserialize a signature from its 96-byte encoding.
206+ ///
207+ /// Returns `None` if `ga` or `gr` is not a valid compressed Ristretto
208+ /// point or if `b` is not a canonical scalar encoding. See
209+ /// [`Signature::to_bytes`] for the encoding layout.
210+ pub fn from_bytes ( bytes : & [ u8 ; SIG_BYTES ] ) -> Option < Self > {
211+ let mut ga_bytes = [ 0u8 ; 32 ] ;
212+ let mut b_bytes = [ 0u8 ; 32 ] ;
213+ let mut gr_bytes = [ 0u8 ; 32 ] ;
214+ ga_bytes. copy_from_slice ( & bytes[ ..32 ] ) ;
215+ b_bytes. copy_from_slice ( & bytes[ 32 ..64 ] ) ;
216+ gr_bytes. copy_from_slice ( & bytes[ 64 ..96 ] ) ;
217+
218+ let ga = point_from_bytes ( ga_bytes) ?;
219+ let b = scalar_from_canonical ( b_bytes) ?;
220+ let gr = point_from_bytes ( gr_bytes) ?;
221+
222+ Some ( Signature { ga, b, gr } )
223+ }
224+ }
225+
118226// Helper function to compute H(g^r || id).
119227fn h_helper ( gr : & RistrettoPoint , id : & Identity ) -> Scalar {
120228 let mut h = Sha3_512 :: new ( ) ;
@@ -313,22 +421,26 @@ mod tests {
313421 // where all communicated messages are serialized/deserialized.
314422
315423 let ( pk, usk, id) = default_setup ( ) ;
424+ let cfg = bincode:: config:: standard ( ) ;
316425
317426 // 1. PKG creates key pair and publishes the public key.
318- let pk_serialized = bincode:: serialize ( & pk) . unwrap ( ) ;
319- let usk_serialized = bincode:: serialize ( & usk) . unwrap ( ) ;
427+ let pk_serialized = bincode:: serde :: encode_to_vec ( & pk, cfg ) . unwrap ( ) ;
428+ let usk_serialized = bincode:: serde :: encode_to_vec ( & usk, cfg ) . unwrap ( ) ;
320429
321430 // 2. A signer retrieves the public key and signs some message,
322431 // after which it sends the signature to the verifier.
323- let pk_recovered: PublicKey = bincode:: deserialize ( & pk_serialized) . unwrap ( ) ;
324- let usk_recovered = bincode:: deserialize ( & usk_serialized) . unwrap ( ) ;
432+ let ( pk_recovered, _) : ( PublicKey , usize ) =
433+ bincode:: serde:: decode_from_slice ( & pk_serialized, cfg) . unwrap ( ) ;
434+ let ( usk_recovered, _) : ( UserSecretKey , usize ) =
435+ bincode:: serde:: decode_from_slice ( & usk_serialized, cfg) . unwrap ( ) ;
325436 let sig = Signer :: new ( )
326437 . chain ( b"some message" )
327438 . sign ( & usk_recovered, & mut OsRng ) ;
328- let sig_serialized = bincode:: serialize ( & sig) . unwrap ( ) ;
439+ let sig_serialized = bincode:: serde :: encode_to_vec ( & sig, cfg ) . unwrap ( ) ;
329440
330441 // 3. A verifier retrieves the signature from the signer and verifies it.
331- let sig_recovered: Signature = bincode:: deserialize ( & sig_serialized) . unwrap ( ) ;
442+ let ( sig_recovered, _) : ( Signature , usize ) =
443+ bincode:: serde:: decode_from_slice ( & sig_serialized, cfg) . unwrap ( ) ;
332444
333445 assert ! ( Verifier :: new( )
334446 . chain( b"some message" )
@@ -348,6 +460,85 @@ mod tests {
348460 assert_ne ! ( sig, sig_other) ;
349461 }
350462
463+ #[ test]
464+ fn test_byte_roundtrip_public_key ( ) {
465+ let ( pk, _) = setup ( & mut OsRng ) ;
466+ let bytes = pk. to_bytes ( ) ;
467+ let recovered = PublicKey :: from_bytes ( & bytes) . expect ( "valid pk bytes" ) ;
468+ assert_eq ! ( pk, recovered) ;
469+ assert_eq ! ( bytes, recovered. to_bytes( ) ) ;
470+ }
471+
472+ #[ test]
473+ fn test_byte_roundtrip_secret_key ( ) {
474+ let ( _, sk) = setup ( & mut OsRng ) ;
475+ let bytes = sk. to_bytes ( ) ;
476+ let recovered = SecretKey :: from_bytes ( & bytes) . expect ( "valid sk bytes" ) ;
477+ assert_eq ! ( sk, recovered) ;
478+ assert_eq ! ( bytes, recovered. to_bytes( ) ) ;
479+ }
480+
481+ #[ test]
482+ fn test_byte_roundtrip_user_secret_key ( ) {
483+ let ( _, usk, _) = default_setup ( ) ;
484+ let bytes = usk. to_bytes ( ) ;
485+ let recovered = UserSecretKey :: from_bytes ( & bytes) . expect ( "valid usk bytes" ) ;
486+ assert_eq ! ( usk, recovered) ;
487+ assert_eq ! ( bytes, recovered. to_bytes( ) ) ;
488+ }
489+
490+ #[ test]
491+ fn test_byte_roundtrip_signature ( ) {
492+ let ( _, usk, _) = default_setup ( ) ;
493+ let sig = Signer :: new ( ) . chain ( b"msg" ) . sign ( & usk, & mut OsRng ) ;
494+ let bytes = sig. to_bytes ( ) ;
495+ let recovered = Signature :: from_bytes ( & bytes) . expect ( "valid sig bytes" ) ;
496+ assert_eq ! ( bytes, recovered. to_bytes( ) ) ;
497+ }
498+
499+ #[ test]
500+ fn test_byte_roundtrip_end_to_end ( ) {
501+ // Full sign/verify across to_bytes/from_bytes on every type.
502+ let ( pk, sk) = setup ( & mut OsRng ) ;
503+ let mut id_bytes = [ 0u8 ; 32 ] ;
504+ OsRng . fill_bytes ( & mut id_bytes) ;
505+ let id: Identity = id_bytes. into ( ) ;
506+ let usk = keygen ( & sk, & id, & mut OsRng ) ;
507+
508+ let pk = PublicKey :: from_bytes ( & pk. to_bytes ( ) ) . unwrap ( ) ;
509+ let usk = UserSecretKey :: from_bytes ( & usk. to_bytes ( ) ) . unwrap ( ) ;
510+
511+ let message = b"the eagle has landed" ;
512+ let sig = Signer :: new ( ) . chain ( message) . sign ( & usk, & mut OsRng ) ;
513+ let sig = Signature :: from_bytes ( & sig. to_bytes ( ) ) . unwrap ( ) ;
514+
515+ assert ! ( Verifier :: new( ) . chain( message) . verify( & pk, & sig, & id) ) ;
516+ }
517+
518+ #[ test]
519+ fn test_from_bytes_rejects_invalid_point ( ) {
520+ // 0xFF... is not a canonical compressed Ristretto encoding.
521+ let bad = [ 0xFFu8 ; PK_BYTES ] ;
522+ assert ! ( PublicKey :: from_bytes( & bad) . is_none( ) ) ;
523+ }
524+
525+ #[ test]
526+ fn test_from_bytes_rejects_non_canonical_scalar ( ) {
527+ // The all-ones byte string exceeds the curve25519 scalar order.
528+ let bad = [ 0xFFu8 ; SK_BYTES ] ;
529+ assert ! ( SecretKey :: from_bytes( & bad) . is_none( ) ) ;
530+ }
531+
532+ #[ test]
533+ fn test_signature_from_bytes_rejects_bad_point ( ) {
534+ let ( _, usk, _) = default_setup ( ) ;
535+ let sig = Signer :: new ( ) . chain ( b"msg" ) . sign ( & usk, & mut OsRng ) ;
536+ let mut bytes = sig. to_bytes ( ) ;
537+ // Corrupt the `ga` point to an invalid encoding.
538+ bytes[ ..32 ] . copy_from_slice ( & [ 0xFFu8 ; 32 ] ) ;
539+ assert ! ( Signature :: from_bytes( & bytes) . is_none( ) ) ;
540+ }
541+
351542 #[ test]
352543 fn test_clone_state ( ) {
353544 let ( pk, usk, id) = default_setup ( ) ;
0 commit comments