@@ -811,3 +811,125 @@ pub fn print_password(
811
811
print_file. write_all ( & [ CR , FF ] ) ?;
812
812
Ok ( ( ) )
813
813
}
814
+
815
+ #[ cfg( test) ]
816
+ mod tests {
817
+ use super :: * ;
818
+
819
+ // secret split into the feldman verifier & shares below
820
+ const SECRET : & str =
821
+ "f259a45c17624b9317d8e292050c46a0f3d7387724b4cd26dd94f8bd3d1c0e1a" ;
822
+
823
+ // verifier created and serialized to json by `new_split_wrap`
824
+ const VERIFIER : & str = r#"
825
+ {
826
+ "generator": "036b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296",
827
+ "commitments": [
828
+ "02315e9e3cd76d0917ecd60378b75259bbdf2e35a31f46c05a497409d5d89c69dc",
829
+ "0250e4e04d42e92bc15eecbe0789f5ac4831abe962df6b1eaed897e4634df702e3",
830
+ "02dfc3c60074cb4896163e7e188f8ec93d3bd1e2fd2ed68854c9324e4a56e94cc7"
831
+ ]
832
+ }"# ;
833
+
834
+ // shares dumped to the printer by `new_split_wrap`
835
+ const SHARE_ARRAY : [ & str ; SHARES ] = [
836
+ "01 b5b7dd6a 8ef8762f 0f266784 be191202 7b8a4b21 72fcb410 f28b2e1a e3669f9c" ,
837
+ "02 042cfd2b 1ede9e78 d7827065 2d8c20ef 1cb43bf1 c722f2e3 a08ac387 b57b18f8" ,
838
+ "03 ddb9039b c714c472 70ecfd33 53657366 51230043 6f56c6a8 cf074e89 ac1fc4d0" ,
839
+ "04 425bf0bf 879ae818 db660def 2fa509f8 e221a80d 765153d1 a2d34dd7 d22d3321" ,
840
+ "05 3215c494 6071096e 16eda298 c24ae4a6 497e28ab 2a41d768 036261f8 2063ae8d" ,
841
+ ] ;
842
+
843
+ fn secret_bytes ( ) -> [ u8 ; KEY_LEN ] {
844
+ let mut secret = [ 0u8 ; KEY_LEN ] ;
845
+ hex:: decode_to_slice ( SECRET , & mut secret) . unwrap ( ) ;
846
+
847
+ secret
848
+ }
849
+
850
+ fn deserialize_share ( share : & str ) -> Result < Share < { KEY_LEN + 1 } > > {
851
+ // filter out whitespace to keep hex::decode happy
852
+ let share: String =
853
+ share. chars ( ) . filter ( |c| !c. is_whitespace ( ) ) . collect ( ) ;
854
+ let share = hex:: decode ( share) ?;
855
+
856
+ Ok ( Share :: try_from ( & share[ ..] ) ?)
857
+ }
858
+
859
+ #[ test]
860
+ fn round_trip ( ) -> Result < ( ) > {
861
+ use rand:: rngs:: ThreadRng ;
862
+
863
+ let secret = secret_bytes ( ) ;
864
+ let secret_key = SecretKey :: from_be_bytes ( & secret) ?;
865
+ let nzs = secret_key. to_nonzero_scalar ( ) ;
866
+
867
+ let mut rng = ThreadRng :: default ( ) ;
868
+ let ( shares, verifier) = Feldman :: < THRESHOLD , SHARES > :: split_secret :: <
869
+ Scalar ,
870
+ ProjectivePoint ,
871
+ ThreadRng ,
872
+ { KEY_LEN + 1 } ,
873
+ > ( * nzs. as_ref ( ) , None , & mut rng)
874
+ . map_err ( |e| anyhow:: anyhow!( "failed to split secret: {}" , e) ) ?;
875
+
876
+ for s in & shares {
877
+ assert ! ( verifier. verify( s) ) ;
878
+ }
879
+
880
+ let scalar = Feldman :: < THRESHOLD , SHARES > :: combine_shares :: <
881
+ Scalar ,
882
+ { KEY_LEN + 1 } ,
883
+ > ( & shares)
884
+ . map_err ( |e| anyhow:: anyhow!( "failed to combine secret: {}" , e) ) ?;
885
+
886
+ let nzs_dup = NonZeroScalar :: from_repr ( scalar. to_repr ( ) ) . unwrap ( ) ;
887
+ let sk_dup = SecretKey :: from ( nzs_dup) ;
888
+ let new_secret: [ u8 ; KEY_LEN ] = sk_dup. to_be_bytes ( ) . try_into ( ) ?;
889
+
890
+ assert_eq ! ( new_secret, secret) ;
891
+
892
+ Ok ( ( ) )
893
+ }
894
+
895
+ // deserialize a verifier & use it to verify the shares in SHARE_ARRAY
896
+ #[ test]
897
+ fn verify_shares ( ) -> Result < ( ) > {
898
+ use vsss_rs:: FeldmanVerifier ;
899
+
900
+ let verifier: FeldmanVerifier <
901
+ Scalar ,
902
+ ProjectivePoint ,
903
+ { KEY_LEN + 1 } ,
904
+ > = serde_json:: from_str ( VERIFIER ) ?;
905
+
906
+ for share in SHARE_ARRAY {
907
+ let share = deserialize_share ( share) ?;
908
+ assert ! ( verifier. verify( & share) ) ;
909
+ }
910
+
911
+ Ok ( ( ) )
912
+ }
913
+
914
+ #[ test]
915
+ fn recover_secret ( ) -> Result < ( ) > {
916
+ let mut shares: Vec < Share < { KEY_LEN + 1 } > > = Vec :: new ( ) ;
917
+ for share in SHARE_ARRAY {
918
+ shares. push ( deserialize_share ( share) ?) ;
919
+ }
920
+
921
+ let scalar = Feldman :: < THRESHOLD , SHARES > :: combine_shares :: <
922
+ Scalar ,
923
+ { KEY_LEN + 1 } ,
924
+ > ( & shares)
925
+ . map_err ( |e| anyhow:: anyhow!( "failed to combine secret: {}" , e) ) ?;
926
+
927
+ let nzs_dup = NonZeroScalar :: from_repr ( scalar. to_repr ( ) ) . unwrap ( ) ;
928
+ let sk_dup = SecretKey :: from ( nzs_dup) ;
929
+ let secret: [ u8 ; KEY_LEN ] = sk_dup. to_be_bytes ( ) . try_into ( ) ?;
930
+
931
+ assert_eq ! ( secret, secret_bytes( ) ) ;
932
+
933
+ Ok ( ( ) )
934
+ }
935
+ }
0 commit comments