@@ -569,6 +569,23 @@ impl Scalar {
569569 Self :: from_bytes_le ( & le_bytes)
570570 }
571571
572+ /// Interprets `bytes` as a big-endian integer of any length and reduces it modulo the
573+ /// group order.
574+ pub fn from_be_bytes_mod_order ( bytes : & [ u8 ] ) -> Self {
575+ // necessary because `blst_scalar_from_be_bytes` below does not work for this value
576+ if bytes. is_empty ( ) {
577+ return Self :: ZERO ;
578+ }
579+
580+ let mut raw = blst_scalar:: default ( ) ;
581+ unsafe { blst_scalar_from_be_bytes ( & mut raw, bytes. as_ptr ( ) , bytes. len ( ) ) } ;
582+
583+ let mut out = blst_fr:: default ( ) ;
584+ unsafe { blst_fr_from_scalar ( & mut out, & raw ) } ;
585+
586+ Scalar ( out)
587+ }
588+
572589 /// Converts an element of `Scalar` into a byte representation in
573590 /// little-endian byte order.
574591 #[ inline]
@@ -1895,4 +1912,30 @@ mod tests {
18951912 }
18961913 assert_eq ! ( 0 , yep_bad. len( ) ) ;
18971914 }
1915+
1916+ /// Vectors from `bls12_381`'s `map_scalar`. These pin the endianness; blst covers the
1917+ /// reduction itself.
1918+ #[ test]
1919+ fn test_from_be_bytes_mod_order ( ) {
1920+ let vectors: & [ ( & [ u8 ] , & str ) ] = & [
1921+ (
1922+ b"aaaaaabbbbbbccccccddddddeeeeeeffffffgggggghhhhhh" ,
1923+ "Scalar(0x2228450bf55d8fe62395161bd3677ff6fc28e45b89bc87e02a818eda11a8c5da)" ,
1924+ ) ,
1925+ (
1926+ b"111111222222333333444444555555666666777777888888" ,
1927+ "Scalar(0x4aa543cbd2f0c8f37f8a375ce2e383eb343e7e3405f61e438b0a15fb8899d1ae)" ,
1928+ ) ,
1929+ ] ;
1930+
1931+ for ( okm, expected) in vectors {
1932+ assert_eq ! (
1933+ & format!( "{:?}" , Scalar :: from_be_bytes_mod_order( okm) ) ,
1934+ expected
1935+ ) ;
1936+ }
1937+
1938+ // The empty-input guard is ours: blst would underflow its digit count.
1939+ assert_eq ! ( Scalar :: from_be_bytes_mod_order( & [ ] ) , Scalar :: ZERO ) ;
1940+ }
18981941}
0 commit comments