@@ -458,11 +458,91 @@ impl G1Affine<CtG1, CtFp> for CtG1Affine {
458458 }
459459
460460 fn to_bytes_uncompressed ( & self ) -> [ u8 ; 96 ] {
461- todo ! ( )
461+ let mut out = [ 0u8 ; 96 ] ;
462+
463+ // Check if point is infinity
464+ if self . is_infinity ( ) {
465+ // Set infinity flag (bit 6) in first byte
466+ out[ 0 ] = 0x40 ;
467+ return out;
468+ }
469+
470+ // Serialize: 48 bytes x (big-endian) || 48 bytes y (big-endian)
471+ // limbs are stored in little-endian, so limbs[5] is most significant
472+ for i in 0 ..6 {
473+ let bytes = self . 0 . x . limbs [ 5 - i] . to_be_bytes ( ) ;
474+ out[ i * 8 ..( i + 1 ) * 8 ] . copy_from_slice ( & bytes) ;
475+ }
476+ for i in 0 ..6 {
477+ let bytes = self . 0 . y . limbs [ 5 - i] . to_be_bytes ( ) ;
478+ out[ 48 + i * 8 ..48 + ( i + 1 ) * 8 ] . copy_from_slice ( & bytes) ;
479+ }
480+
481+ out
462482 }
463483
464- fn from_bytes_uncompressed ( _bytes : [ u8 ; 96 ] ) -> Result < Self , String > {
465- todo ! ( )
484+ fn from_bytes_uncompressed ( bytes : [ u8 ; 96 ] ) -> Result < Self , String > {
485+ // Check flags in first byte
486+ let compression_flag = bytes[ 0 ] & 0x80 ; // most-significant bit
487+ let infinity_flag = bytes[ 0 ] & 0x40 ; // second most-significant bit
488+ let sort_flag = bytes[ 0 ] & 0x20 ; // third most-significant bit
489+
490+ // For uncompressed, compression bit must be 0
491+ if compression_flag != 0 {
492+ return Err ( "Compression flag set for uncompressed encoding" . to_string ( ) ) ;
493+ }
494+
495+ // Sort flag must be 0 for uncompressed
496+ if sort_flag != 0 {
497+ return Err ( "Sort flag must be 0 for uncompressed encoding" . to_string ( ) ) ;
498+ }
499+
500+ // Handle infinity point
501+ if infinity_flag != 0 {
502+ // All other bits (except flags) must be zero for infinity
503+ if bytes[ 0 ] & 0x1f != 0 || bytes[ 1 ..] . iter ( ) . any ( |& b| b != 0 ) {
504+ return Err ( "Invalid infinity encoding" . to_string ( ) ) ;
505+ }
506+ return Ok ( Self :: zero ( ) ) ;
507+ }
508+
509+ let mut x_limbs: [ usize ; 6 ] = [ 0 ; 6 ] ;
510+ let mut y_limbs: [ usize ; 6 ] = [ 0 ; 6 ] ;
511+
512+ // Deserialize: bytes come in big-endian
513+ // We need to store them in little-endian limbs array
514+ // First limb needs to have flag bits cleared
515+ for i in 0 ..6 {
516+ let mut limb_bytes = [ 0u8 ; 8 ] ;
517+ limb_bytes. copy_from_slice ( & bytes[ i * 8 ..( i + 1 ) * 8 ] ) ;
518+ let mut limb_value = usize:: from_be_bytes ( limb_bytes) ;
519+ // Clear top 3 flag bits from the first limb (most significant)
520+ if i == 0 {
521+ limb_value &= 0x1fffffffffffffff ; // Clear bits 63, 62, 61
522+ }
523+ x_limbs[ 5 - i] = limb_value;
524+ }
525+ for i in 0 ..6 {
526+ let mut limb_bytes = [ 0u8 ; 8 ] ;
527+ limb_bytes. copy_from_slice ( & bytes[ 48 + i * 8 ..48 + ( i + 1 ) * 8 ] ) ;
528+ y_limbs[ 5 - i] = usize:: from_be_bytes ( limb_bytes) ;
529+ }
530+
531+ let tmp = bls12_381_g1_aff {
532+ x : bls12_381_fp { limbs : x_limbs } ,
533+ y : bls12_381_fp { limbs : y_limbs } ,
534+ } ;
535+
536+ // Validate point is on curve
537+ unsafe {
538+ match constantine:: ctt_bls12_381_validate_g1 ( & tmp) {
539+ ctt_codec_ecc_status:: cttCodecEcc_Success => Ok ( CtG1Affine ( tmp) ) ,
540+ ctt_codec_ecc_status:: cttCodecEcc_PointAtInfinity => {
541+ Err ( "Point at infinity should have infinity flag set" . to_string ( ) )
542+ }
543+ _ => Err ( "Point is not on the curve" . to_string ( ) ) ,
544+ }
545+ }
466546 }
467547}
468548
0 commit comments