You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

274 lines
8.6 KiB

  1. extern crate num;
  2. extern crate num_bigint;
  3. extern crate num_traits;
  4. extern crate rand;
  5. use std::str::FromStr;
  6. use num::pow::pow;
  7. use num::Integer;
  8. use num_bigint::RandBigInt;
  9. use num_bigint::{BigInt, ToBigInt};
  10. use num_traits::{One, Zero};
  11. fn modulus(a: &BigInt, m: &BigInt) -> BigInt {
  12. ((a % m) + m) % m
  13. }
  14. pub fn create(t: u32, n: u32, p: &BigInt, k: &BigInt) -> Vec<[BigInt; 2]> {
  15. // t: number of secrets needed
  16. // n: number of shares
  17. // p: size of finite field
  18. // k: secret to share
  19. if k > p {
  20. println!("\nERROR: need k<p\n");
  21. }
  22. // generate base_polynomial
  23. let mut base_polynomial: Vec<BigInt> = Vec::new();
  24. base_polynomial.push(k.clone());
  25. for _ in 0..t as usize - 1 {
  26. let mut rng = rand::thread_rng();
  27. let a = rng.gen_bigint(1024);
  28. base_polynomial.push(a);
  29. }
  30. // calculate shares, based on the base_polynomial
  31. let mut shares: Vec<BigInt> = Vec::new();
  32. for i in 1..n + 1 {
  33. let mut p_res: BigInt = Zero::zero();
  34. let mut x = 0;
  35. for pol_elem in &base_polynomial {
  36. if x == 0 {
  37. p_res = p_res + pol_elem;
  38. } else {
  39. let i_pow = pow(i, x);
  40. let curr_elem = i_pow * pol_elem;
  41. p_res = p_res + curr_elem;
  42. p_res = modulus(&p_res, p);
  43. }
  44. x = x + 1;
  45. }
  46. shares.push(p_res);
  47. }
  48. pack_shares(shares)
  49. }
  50. fn pack_shares(shares: Vec<BigInt>) -> Vec<[BigInt; 2]> {
  51. let mut r: Vec<[BigInt; 2]> = Vec::new();
  52. for i in 0..shares.len() {
  53. let curr: [BigInt; 2] = [shares[i].clone(), (i + 1).to_bigint().unwrap()];
  54. r.push(curr);
  55. }
  56. r
  57. }
  58. fn unpack_shares(s: Vec<[BigInt; 2]>) -> (Vec<BigInt>, Vec<BigInt>) {
  59. let mut shares: Vec<BigInt> = Vec::new();
  60. let mut is: Vec<BigInt> = Vec::new();
  61. for i in 0..s.len() {
  62. shares.push(s[i][0].clone());
  63. is.push(s[i][1].clone());
  64. }
  65. (shares, is)
  66. }
  67. pub fn mod_inverse(a: BigInt, module: BigInt) -> BigInt {
  68. // TODO search biguint impl of mod_inv
  69. let mut mn = (module.clone(), a);
  70. let mut xy: (BigInt, BigInt) = (Zero::zero(), One::one());
  71. let big_zero: BigInt = Zero::zero();
  72. while mn.1 != big_zero {
  73. xy = (xy.1.clone(), xy.0 - (mn.0.clone() / mn.1.clone()) * xy.1);
  74. mn = (mn.1.clone(), modulus(&mn.0, &mn.1));
  75. }
  76. while xy.0 < Zero::zero() {
  77. xy.0 += module.clone();
  78. }
  79. xy.0
  80. }
  81. /// Compute `a^-1 (mod l)` using the the Kalinski implementation
  82. /// of the Montgomery Modular Inverse algorithm.
  83. /// B. S. Kaliski Jr. - The Montgomery inverse and its applica-tions.
  84. /// IEEE Transactions on Computers, 44(8):1064–1065, August-1995
  85. pub fn kalinski_inv(a: &BigInt, modulo: &BigInt) -> BigInt {
  86. // This Phase I indeed is the Binary GCD algorithm , a version o Stein's algorithm
  87. // which tries to remove the expensive division operation away from the Classical
  88. // Euclidean GDC algorithm replacing it for Bit-shifting, subtraction and comparaison.
  89. //
  90. // Output = `a^(-1) * 2^k (mod l)` where `k = log2(modulo) == Number of bits`.
  91. //
  92. // Stein, J.: Computational problems associated with Racah algebra.J. Comput. Phys.1, 397–405 (1967).
  93. let phase1 = |a: &BigInt| -> (BigInt, u64) {
  94. assert!(a != &BigInt::zero());
  95. let p = modulo;
  96. let mut u = modulo.clone();
  97. let mut v = a.clone();
  98. let mut r = BigInt::zero();
  99. let mut s = BigInt::one();
  100. let mut k = 0u64;
  101. while v > BigInt::zero() {
  102. match (u.is_even(), v.is_even(), u > v, v >= u) {
  103. // u is even
  104. (true, _, _, _) => {
  105. u = u >> 1;
  106. s = s << 1;
  107. }
  108. // u isn't even but v is even
  109. (false, true, _, _) => {
  110. v = v >> 1;
  111. r = &r << 1;
  112. }
  113. // u and v aren't even and u > v
  114. (false, false, true, _) => {
  115. u = &u - &v;
  116. u = u >> 1;
  117. r = &r + &s;
  118. s = &s << 1;
  119. }
  120. // u and v aren't even and v > u
  121. (false, false, false, true) => {
  122. v = &v - &u;
  123. v = v >> 1;
  124. s = &r + &s;
  125. r = &r << 1;
  126. }
  127. (false, false, false, false) => panic!("Unexpected error has ocurred."),
  128. }
  129. k += 1;
  130. }
  131. if &r > p {
  132. r = &r - p;
  133. }
  134. ((p - &r), k)
  135. };
  136. // Phase II performs some adjustments to obtain
  137. // the Montgomery inverse.
  138. //
  139. // We implement it as a clousure to be able to grap the
  140. // kalinski_inv scope to get `modulo` variable.
  141. let phase2 = |r: &BigInt, k: &u64| -> BigInt {
  142. let mut rr = r.clone();
  143. let _p = modulo;
  144. for _i in 0..*k {
  145. match rr.is_even() {
  146. true => {
  147. rr = rr >> 1;
  148. }
  149. false => {
  150. rr = (rr + modulo) >> 1;
  151. }
  152. }
  153. }
  154. rr
  155. };
  156. let (r, z) = phase1(&a.clone());
  157. phase2(&r, &z)
  158. }
  159. pub fn lagrange_interpolation(p: &BigInt, shares_packed: Vec<[BigInt; 2]>) -> BigInt {
  160. let mut res_n: BigInt = Zero::zero();
  161. let mut res_d: BigInt = Zero::zero();
  162. let (shares, sh_i) = unpack_shares(shares_packed);
  163. for i in 0..shares.len() {
  164. let mut lagrange_numerator: BigInt = One::one();
  165. let mut lagrange_denominator: BigInt = One::one();
  166. for j in 0..shares.len() {
  167. if shares[i] != shares[j] {
  168. let curr_l_numerator = &sh_i[j];
  169. let curr_l_denominator = &sh_i[j] - &sh_i[i];
  170. lagrange_numerator = lagrange_numerator * curr_l_numerator;
  171. lagrange_denominator = lagrange_denominator * curr_l_denominator;
  172. }
  173. }
  174. let numerator: BigInt = &shares[i] * &lagrange_numerator;
  175. let quo: BigInt =
  176. (&numerator / &lagrange_denominator) + (&lagrange_denominator) % &lagrange_denominator;
  177. if quo != Zero::zero() {
  178. res_n = res_n + quo;
  179. } else {
  180. let res_n_mul_lagrange_den = res_n * &lagrange_denominator;
  181. res_n = res_n_mul_lagrange_den + numerator;
  182. res_d = res_d + lagrange_denominator;
  183. }
  184. }
  185. let modinv_mul: BigInt;
  186. if res_d != Zero::zero() {
  187. let modinv = kalinski_inv(&res_d, &p);
  188. modinv_mul = res_n * modinv;
  189. } else {
  190. modinv_mul = res_n;
  191. }
  192. let r = modulus(&modinv_mul, &p);
  193. r
  194. }
  195. #[cfg(test)]
  196. mod tests {
  197. use super::*;
  198. use std::str::FromStr;
  199. #[test]
  200. fn test_create_and_lagrange_interpolation() {
  201. // 2 ** 127 - 1
  202. let p = BigInt::parse_bytes(b"170141183460469231731687303715884105727", 10).unwrap();
  203. println!("p: {:?}", p.to_string());
  204. let k = BigInt::parse_bytes(b"12345678901234567890123456789012345678", 10).unwrap();
  205. let s = create(3, 6, &p, &k);
  206. // println!("s: {:?}", s);
  207. let mut shares_to_use: Vec<[BigInt; 2]> = Vec::new();
  208. shares_to_use.push(s[2].clone());
  209. shares_to_use.push(s[1].clone());
  210. shares_to_use.push(s[0].clone());
  211. let r = lagrange_interpolation(&p, shares_to_use);
  212. println!("recovered secret: {:?}", r.to_string());
  213. println!("original secret: {:?}", k.to_string());
  214. assert_eq!(k, r);
  215. }
  216. #[test]
  217. fn kalinski_modular_inverse() {
  218. let modul1 = BigInt::from(127u64);
  219. let a = BigInt::from(79u64);
  220. let res1 = kalinski_inv(&a, &modul1);
  221. let expected1 = BigInt::from(82u64);
  222. assert_eq!(res1, expected1);
  223. let b = BigInt::from(50u64);
  224. let res2 = kalinski_inv(&b, &modul1);
  225. let expected2 = BigInt::from(94u64);
  226. assert_eq!(res2, expected2);
  227. // Modulo: 2^252 + 27742317777372353535851937790883648493
  228. // Tested: 182687704666362864775460604089535377456991567872
  229. // Expected for: inverse_mod(a, l) computed on SageMath:
  230. // `7155219595916845557842258654134856828180378438239419449390401977965479867845`.
  231. let modul3 = BigInt::from_str(
  232. "7237005577332262213973186563042994240857116359379907606001950938285454250989",
  233. )
  234. .unwrap();
  235. let d = BigInt::from_str("182687704666362864775460604089535377456991567872").unwrap();
  236. let res4 = kalinski_inv(&d, &modul3);
  237. let expected4 = BigInt::from_str(
  238. "7155219595916845557842258654134856828180378438239419449390401977965479867845",
  239. )
  240. .unwrap();
  241. assert_eq!(expected4, res4);
  242. }
  243. }