22use crate :: { backend, hash:: HashInto , marker:: * , op} ;
33use core:: {
44 marker:: PhantomData ,
5- num:: NonZeroU32 ,
65 ops:: { AddAssign , MulAssign , SubAssign } ,
76} ;
87use digest:: { self , generic_array:: typenum:: U32 } ;
@@ -185,7 +184,7 @@ impl<S> Scalar<S, NonZero> {
185184
186185 /// Returns the integer `1` as a `Scalar`.
187186 pub fn one ( ) -> Self {
188- Scalar :: from ( 1 ) . non_zero ( ) . unwrap ( )
187+ Scalar :: < S , Zero > :: from ( 1u32 ) . non_zero ( ) . unwrap ( )
189188 }
190189
191190 /// Returns the integer -1 (modulo the curve order) as a `Scalar`.
@@ -221,13 +220,6 @@ impl<S> Scalar<S, NonZero> {
221220 pub fn mark_zero_choice < Z : ZeroChoice > ( self ) -> Scalar < S , Z > {
222221 Scalar :: from_inner ( self . 0 )
223222 }
224-
225- /// Converts a [`NonZeroU32`] into a `Scalar<Secret,NonZero>`.
226- ///
227- /// [`NonZeroU32`]: core::num::NonZeroU32
228- pub fn from_non_zero_u32 ( int : core:: num:: NonZeroU32 ) -> Self {
229- Self :: from_inner ( backend:: BackendScalar :: from_u32 ( int. get ( ) ) )
230- }
231223}
232224
233225impl Scalar < Secret , NonZero > {
@@ -344,18 +336,6 @@ impl<Z1, Z2, S1, S2> PartialEq<Scalar<S2, Z2>> for Scalar<S1, Z1> {
344336
345337impl < Z , S > Eq for Scalar < Z , S > { }
346338
347- impl < S > From < u32 > for Scalar < S , Zero > {
348- fn from ( int : u32 ) -> Self {
349- Self :: from_inner ( backend:: BackendScalar :: from_u32 ( int) )
350- }
351- }
352-
353- impl < S > From < NonZeroU32 > for Scalar < S , NonZero > {
354- fn from ( int : NonZeroU32 ) -> Self {
355- Self :: from_inner ( backend:: BackendScalar :: from_u32 ( int. into ( ) ) )
356- }
357- }
358-
359339crate :: impl_fromstr_deserialize! {
360340 name => "secp256k1 scalar" ,
361341 fn from_bytes<S , Z : ZeroChoice >( bytes: [ u8 ; 32 ] ) -> Option <Scalar <S , Z >> {
@@ -405,7 +385,7 @@ where
405385 S : Secrecy ,
406386{
407387 fn default ( ) -> Self {
408- Self :: from_inner ( backend :: BackendScalar :: from_u32 ( 1 ) )
388+ Self :: one ( )
409389 }
410390}
411391
@@ -470,10 +450,109 @@ impl<Z> Ord for Scalar<Public, Z> {
470450 }
471451}
472452
453+ mod conversion_impls {
454+ use super :: * ;
455+ use core:: { any:: type_name, convert:: TryFrom , fmt, marker:: PhantomData , mem} ;
456+ use subtle:: ConstantTimeEq ;
457+
458+ /// Returned when a `Scalar` value exceeds the range of the target integer.
459+ #[ derive( Clone , Copy , PartialEq , Eq ) ]
460+ pub struct ScalarTooLarge < T > ( PhantomData < T > ) ;
461+
462+ impl < T > core:: fmt:: Display for ScalarTooLarge < T > {
463+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
464+ write ! ( f, "scalar value does not fit into {}" , type_name:: <T >( ) )
465+ }
466+ }
467+
468+ impl < T > core:: fmt:: Debug for ScalarTooLarge < T > {
469+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
470+ f. debug_tuple ( "ScalarTooLarge" )
471+ . field ( & type_name :: < T > ( ) )
472+ . finish ( )
473+ }
474+ }
475+
476+ #[ cfg( feature = "std" ) ]
477+ impl < T > std:: error:: Error for ScalarTooLarge < T > { }
478+
479+ /// Implements `From<$t> for $scalar` **and**
480+ /// `TryFrom<$scalar> for $t` for every `$t` supplied.
481+ macro_rules! impl_scalar_conversions {
482+ ( $( $t: ty) ,+ $( , ) ?) => {
483+ $(
484+ impl <S > From <$t> for Scalar <S , Zero > {
485+ fn from( value: $t) -> Self {
486+ // big-endian integer → 32-byte array
487+ let mut bytes = [ 0u8 ; 32 ] ;
488+ let int_bytes = value. to_be_bytes( ) ;
489+ bytes[ 32 - int_bytes. len( ) ..] . copy_from_slice( & int_bytes) ;
490+ Scalar :: <S , Zero >:: from_bytes( bytes) . unwrap( )
491+ }
492+ }
493+
494+ impl <S , Z > TryFrom <Scalar <S , Z >> for $t {
495+ type Error = ScalarTooLarge <$t>;
496+
497+ fn try_from( value: Scalar <S , Z >) -> Result <Self , Self :: Error > {
498+ let bytes = value. to_bytes( ) ;
499+
500+ // Overflow check: any non-zero in the high 32−N bytes fails.
501+ let high = & bytes[ .. 32 - mem:: size_of:: <$t>( ) ] ;
502+ if high. ct_eq( & [ 0x0 ; 32 - mem:: size_of:: <$t>( ) ] ) . into( ) {
503+ // Safe: the slice is exactly the right length.
504+ let mut buf = [ 0u8 ; mem:: size_of:: <$t>( ) ] ;
505+ buf. copy_from_slice( & bytes[ 32 - mem:: size_of:: <$t>( ) ..] ) ;
506+ Ok ( <$t>:: from_be_bytes( buf) )
507+ } else {
508+ Err ( ScalarTooLarge ( PhantomData ) )
509+ }
510+
511+ }
512+ }
513+
514+ impl <S > From <core:: num:: NonZero <$t>> for Scalar <S , NonZero > {
515+ fn from( value: core:: num:: NonZero <$t>) -> Self {
516+ // big-endian integer → 32-byte array
517+ let mut bytes = [ 0u8 ; 32 ] ;
518+ let int_bytes = value. get( ) . to_be_bytes( ) ;
519+ bytes[ 32 - int_bytes. len( ) ..] . copy_from_slice( & int_bytes) ;
520+ Scalar :: <S , Zero >:: from_bytes( bytes) . unwrap( ) . non_zero( ) . unwrap( )
521+ }
522+ }
523+
524+ impl <S > TryFrom <Scalar <S , NonZero >> for core:: num:: NonZero <$t> {
525+ type Error = ScalarTooLarge <$t>;
526+
527+ fn try_from( value: Scalar <S , NonZero >) -> Result <Self , Self :: Error > {
528+ let bytes = value. to_bytes( ) ;
529+
530+ // Overflow check: any non-zero in the high 32−N bytes fails.
531+ let high = & bytes[ .. 32 - mem:: size_of:: <$t>( ) ] ;
532+ if high. ct_eq( & [ 0x0 ; 32 - mem:: size_of:: <$t>( ) ] ) . into( ) {
533+ // Safe: the slice is exactly the right length.
534+ let mut buf = [ 0u8 ; mem:: size_of:: <$t>( ) ] ;
535+ buf. copy_from_slice( & bytes[ 32 - mem:: size_of:: <$t>( ) ..] ) ;
536+ Ok ( core:: num:: NonZero :: new( <$t>:: from_be_bytes( buf) ) . unwrap( ) )
537+ } else {
538+ Err ( ScalarTooLarge ( PhantomData ) )
539+ }
540+
541+ }
542+ }
543+
544+ ) *
545+ } ;
546+ }
547+
548+ impl_scalar_conversions ! ( u8 , u16 , u32 , u64 , usize , u128 ) ;
549+ }
550+
473551#[ cfg( test) ]
474552mod test {
475553 use super :: * ;
476554 use crate :: { hex, s} ;
555+ #[ cfg( feature = "alloc" ) ]
477556 use proptest:: prelude:: * ;
478557 #[ cfg( target_arch = "wasm32" ) ]
479558 use wasm_bindgen_test:: wasm_bindgen_test as test;
@@ -503,11 +582,12 @@ mod test {
503582 assert_ne ! ( scalar_1, scalar_2) ;
504583 }
505584
585+ #[ cfg( feature = "alloc" ) ]
506586 proptest ! {
507587 #[ test]
508588 fn invert( x in any:: <Scalar >( ) , y in any:: <Scalar <Public >>( ) ) {
509- assert_eq !( s!( x * { x. invert( ) } ) , s!( 1 ) ) ;
510- assert_eq !( s!( y * { y. invert( ) } ) , s!( 1 ) ) ;
589+ prop_assert_eq !( s!( x * { x. invert( ) } ) , s!( 1 ) ) ;
590+ prop_assert_eq !( s!( y * { y. invert( ) } ) , s!( 1 ) ) ;
511591 }
512592
513593 #[ test]
@@ -516,24 +596,48 @@ mod test {
516596 c in any:: <Scalar <Public , Zero >>( ) ,
517597 d in any:: <Scalar <Secret , Zero >>( ) ,
518598 ) {
519- assert_eq !( s!( a - a) , s!( 0 ) ) ;
520- assert_eq !( s!( b - b) , s!( 0 ) ) ;
521- assert_eq !( s!( c - c) , s!( 0 ) ) ;
522- assert_eq !( s!( d - d) , s!( 0 ) ) ;
523- assert_eq !( s!( a - a) , s!( -a + a) ) ;
524- assert_eq !( s!( a - b) , s!( -b + a) ) ;
525- assert_eq !( s!( a - c) , s!( -c + a) ) ;
526- assert_eq !( s!( a - d) , s!( -d + a) ) ;
599+ prop_assert_eq !( s!( a - a) , s!( 0 ) ) ;
600+ prop_assert_eq !( s!( b - b) , s!( 0 ) ) ;
601+ prop_assert_eq !( s!( c - c) , s!( 0 ) ) ;
602+ prop_assert_eq !( s!( d - d) , s!( 0 ) ) ;
603+ prop_assert_eq !( s!( a - a) , s!( -a + a) ) ;
604+ prop_assert_eq !( s!( a - b) , s!( -b + a) ) ;
605+ prop_assert_eq !( s!( a - c) , s!( -c + a) ) ;
606+ prop_assert_eq !( s!( a - d) , s!( -d + a) ) ;
527607
528608 if a != b {
529- assert_ne !( s!( a - b) , s!( b - a) ) ;
609+ prop_assert_ne !( s!( a - b) , s!( b - a) ) ;
530610 }
531611
532612 if c != d {
533- assert_ne !( s!( c - d) , s!( d - c) ) ;
613+ prop_assert_ne !( s!( c - d) , s!( d - c) ) ;
534614 }
535615 }
536616
617+ /// Any `u128` should convert to a `Scalar` and back loss-lessly.
618+ #[ test]
619+ fn u128_roundtrip( xs in any:: <u128 >( ) ) {
620+ // u128 → Scalar
621+ let s: Scalar <Public , Zero > = xs. into( ) ;
622+
623+ // Scalar → u128
624+ let back = u128 :: try_from( s)
625+ . expect( "a u128 always fits inside a 256-bit scalar" ) ;
626+
627+ prop_assert_eq!( xs, back) ;
628+ }
629+
630+ #[ test]
631+ fn nz_u128_roundtrip( xs in any:: <core:: num:: NonZero <u128 >>( ) ) {
632+ // u128 → Scalar
633+ let s: Scalar <Public , NonZero > = xs. into( ) ;
634+
635+ // Scalar → u128
636+ let back = core:: num:: NonZero :: <u128 >:: try_from( s)
637+ . expect( "a u128 always fits inside a 256-bit scalar" ) ;
638+
639+ prop_assert_eq!( xs, back) ;
640+ }
537641
538642 }
539643
@@ -566,7 +670,10 @@ mod test {
566670
567671 #[ test]
568672 fn zero ( ) {
569- assert_eq ! ( Scalar :: <Secret , Zero >:: zero( ) , Scalar :: <Secret , _>:: from( 0 ) ) ;
673+ assert_eq ! (
674+ Scalar :: <Secret , Zero >:: zero( ) ,
675+ Scalar :: <Secret , _>:: from( 0u32 )
676+ ) ;
570677 }
571678
572679 #[ test]
@@ -610,7 +717,7 @@ mod test {
610717 . as_ref( )
611718 )
612719 . unwrap( ) ,
613- Scalar :: <Secret , _>:: from( 1 )
720+ Scalar :: <Secret , _>:: from( 1u32 )
614721 )
615722 }
616723
@@ -629,21 +736,21 @@ mod test {
629736
630737 #[ test]
631738 fn assign_tests ( ) {
632- let mut a = Scalar :: < Secret , _ > :: from ( 42 ) ;
633- let b = Scalar :: < Secret , _ > :: from ( 1337 ) . public ( ) ;
739+ let mut a = Scalar :: < Secret , _ > :: from ( 42u8 ) ;
740+ let b = Scalar :: < Secret , _ > :: from ( 1337u16 ) . public ( ) ;
634741 a += b;
635- assert_eq ! ( a, Scalar :: <Secret , _>:: from( 1379 ) ) ;
742+ assert_eq ! ( a, Scalar :: <Secret , _>:: from( 1379u16 ) ) ;
636743 a -= b;
637- assert_eq ! ( a, Scalar :: <Secret , _>:: from( 42 ) ) ;
744+ assert_eq ! ( a, Scalar :: <Secret , _>:: from( 42u32 ) ) ;
638745 a *= b;
639- assert_eq ! ( a, Scalar :: <Secret , _>:: from( 42 * 1337 ) ) ;
746+ assert_eq ! ( a, Scalar :: <Secret , _>:: from( 42u16 * 1337u16 ) ) ;
640747 }
641748
642749 #[ test]
643750 fn scalar_ord ( ) {
644- assert ! ( Scalar :: <Public , _>:: from( 1337 ) > Scalar :: <Public , _>:: from( 42 ) ) ;
645- assert ! ( Scalar :: <Public , _>:: from( 42 ) < Scalar :: <Public , _>:: from( 1337 ) ) ;
646- assert ! ( Scalar :: <Public , _>:: from( 41 ) < Scalar :: <Public , _>:: from( 42 ) ) ;
647- assert ! ( Scalar :: <Public , _>:: from( 42 ) <= Scalar :: <Public , _>:: from( 42 ) ) ;
751+ assert ! ( Scalar :: <Public , _>:: from( 1337u32 ) > Scalar :: <Public , _>:: from( 42u8 ) ) ;
752+ assert ! ( Scalar :: <Public , _>:: from( 42u32 ) < Scalar :: <Public , _>:: from( 1337u16 ) ) ;
753+ assert ! ( Scalar :: <Public , _>:: from( 41u32 ) < Scalar :: <Public , _>:: from( 42u32 ) ) ;
754+ assert ! ( Scalar :: <Public , _>:: from( 42u32 ) <= Scalar :: <Public , _>:: from( 42u32 ) ) ;
648755 }
649756}
0 commit comments