@@ -882,119 +882,6 @@ impl FieldElement {
882882 FieldElement :: montgomery_reduce ( & limbs)
883883 }
884884
885- /// Compute `a^-1 (mod l)` using the the Kalinski implementation
886- /// of the Montgomery Modular Inverse algorithm.
887- /// B. S. Kaliski Jr. - The Montgomery inverse and its applications.
888- /// IEEE Transactions on Computers, 44(8):1064–1065, August-1995
889- #[ allow( dead_code) ]
890- pub ( self ) fn kalinski_inverse ( & self ) -> FieldElement {
891- /// This Phase I indeed is the Binary GCD algorithm, a version of Steins algorithm
892- /// which tries to remove the expensive division operation away from the Classical
893- /// Euclidean GDC algorithm by replacing it with Bit-shifting, subtraction and comparison.
894- ///
895- /// Output = `a^(-1) * 2^k (mod l)` where `k = log2(FIELD_L) == 253`.
896- ///
897- /// Stein, J.: Computational problems associated with Racah algebra.J. Comput. Phys.1, 397–405 (1967)
898- ///
899- ///
900- /// Mentioned on: SPECIAL ISSUE ON MONTGOMERY ARITHMETIC.
901- /// Montgomery inversion - Erkay Sava ̧s & Çetin Kaya Koç
902- /// J Cryptogr Eng (2018) 8:201–210
903- /// https://doi.org/10.1007/s13389-017-0161-x
904-
905- fn phase1 ( a : & FieldElement ) -> ( FieldElement , u64 ) {
906- // Declare L = 2^252 + 27742317777372353535851937790883648493
907- let p = FieldElement ( [
908- 671914833335277 ,
909- 3916664325105025 ,
910- 1367801 ,
911- 0 ,
912- 17592186044416 ,
913- ] ) ;
914- let mut u = p. clone ( ) ;
915- let mut v = * a;
916- let mut r = FieldElement :: zero ( ) ;
917- let mut s = FieldElement :: one ( ) ;
918- let two = FieldElement ( [ 2 , 0 , 0 , 0 , 0 ] ) ;
919- let mut k = 0u64 ;
920-
921- while v > FieldElement :: zero ( ) {
922- match ( u. is_even ( ) , v. is_even ( ) , u > v, v >= u) {
923- // u is even
924- ( true , _, _, _) => {
925- u = u. inner_half ( ) ;
926- s = s * two;
927- }
928- // u isn't even but v is even
929- ( false , true , _, _) => {
930- v = v. inner_half ( ) ;
931- r = r * two;
932- }
933- // u and v aren't even and u > v
934- ( false , false , true , _) => {
935- u = u - v;
936- u = u. inner_half ( ) ;
937- r = r + s;
938- s = s * two;
939- }
940- // u and v aren't even and v > u
941- ( false , false , false , true ) => {
942- v = v - u;
943- v = v. inner_half ( ) ;
944- s = r + s;
945- r = r * two;
946- }
947- ( false , false , false , false ) => panic ! ( "Unexpected error has ocurred." ) ,
948- }
949- k += 1 ;
950- }
951- if r > p {
952- r = r - p;
953- }
954- ( p - r, k)
955- }
956-
957- /// Phase II performs some adjustments to obtain
958- /// the Montgomery inverse.
959- ///
960- /// Output: `a^(-1) * 2^n (mod l)` where `n = 253 = log2(p) = log2(FIELD_L)`
961-
962- fn phase2 ( r : & FieldElement , k : u64 ) -> FieldElement {
963- let mut rr = * r;
964- let _p = & constants:: FIELD_L ;
965-
966- for _i in 0 ..( k - 253 ) {
967- match rr. is_even ( ) {
968- true => {
969- rr = rr. inner_half ( ) ;
970- }
971- false => {
972- rr = rr. plus_p_and_half ( ) ;
973- }
974- }
975- }
976- rr
977- }
978-
979- let ( mut r, z) = phase1 ( & self ) ;
980-
981- r = phase2 ( & r, z) ;
982-
983- // Since the output of the Phase II is multiplied by `2^n`
984- // We can multiply it by the two power needed to achive the
985- // Montgomery modulus value and then convert it back to the
986- // normal FieldElement domain.
987- //
988- // In this case: `R = 2^260` & `n = 2^253`.
989- // So we multiply `r * 2^7` to get R on the Montgomery domain.
990- r = & r * & FieldElement :: inner_two_pow_k ( 7 ) ;
991-
992- // Now we apply `from_montgomery()` function which performs
993- // `r/2^260` carrying the `FieldElement` out of the
994- // Montgomery domain.
995- r. from_montgomery ( )
996- }
997-
998885 /// Compute `a^-1 (mod l)` using the the Savas & Koç modular
999886 /// inverse algorithm. It's an optimization of the Kalinski
1000887 /// modular inversion algorithm that extends the Binary GCD
@@ -1687,24 +1574,6 @@ pub mod tests {
16871574 assert ! ( msb[ 31 ] < pos_sign) ;
16881575 }
16891576
1690- #[ test]
1691- fn kalinski_inverse ( ) {
1692- let res = FieldElement :: kalinski_inverse ( & A ) ;
1693- for i in 0 ..5 {
1694- assert ! ( res[ i] == INV_MOD_A [ i] ) ;
1695- }
1696-
1697- let res = FieldElement :: kalinski_inverse ( & B ) ;
1698- for i in 0 ..5 {
1699- assert ! ( res[ i] == INV_MOD_B [ i] ) ;
1700- }
1701-
1702- let res = FieldElement :: kalinski_inverse ( & C ) ;
1703- for i in 0 ..5 {
1704- assert ! ( res[ i] == INV_MOD_C [ i] ) ;
1705- }
1706- }
1707-
17081577 #[ test]
17091578 fn savas_koc_inverse ( ) {
17101579 let res = FieldElement :: inverse ( & A ) ;
0 commit comments