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.

154 lines
4.6 KiB

  1. extern crate rand;
  2. extern crate num;
  3. extern crate num_bigint;
  4. extern crate num_traits;
  5. use num_bigint::RandBigInt;
  6. use num::pow::pow;
  7. use num_bigint::{BigInt, ToBigInt};
  8. use num_traits::{Zero, One};
  9. fn modulus(a: &BigInt, m: &BigInt) -> BigInt {
  10. ((a%m) + m) % m
  11. }
  12. pub fn create(t: u32, n: u32,p: &BigInt, k: &BigInt) -> Vec<[BigInt;2]> {
  13. // t: number of secrets needed
  14. // n: number of shares
  15. // p: random point
  16. // k: secret to share
  17. if k>p {
  18. println!("\nERROR: need k<p\n");
  19. }
  20. // generate base_polynomial
  21. let mut base_polynomial: Vec<BigInt> = Vec::new();
  22. base_polynomial.push(k.clone());
  23. for _ in 0..t as usize-1 {
  24. let mut rng = rand::thread_rng();
  25. let a = rng.gen_bigint(1024);
  26. base_polynomial.push(a);
  27. }
  28. // calculate shares, based on the base_polynomial
  29. let mut shares: Vec<BigInt> = Vec::new();
  30. for i in 1..n+1 {
  31. let mut p_res: BigInt = Zero::zero();
  32. let mut x = 0;
  33. for pol_elem in &base_polynomial {
  34. if x==0 {
  35. p_res = p_res + pol_elem;
  36. } else {
  37. let i_pow = pow(i, x);
  38. let curr_elem = i_pow * pol_elem;
  39. p_res = p_res + curr_elem;
  40. p_res = modulus(&p_res, p);
  41. }
  42. x = x+1;
  43. }
  44. shares.push(p_res);
  45. }
  46. pack_shares(shares)
  47. }
  48. fn pack_shares(shares: Vec<BigInt>) -> Vec<[BigInt;2]> {
  49. let mut r: Vec<[BigInt;2]> = Vec::new();
  50. for i in 0..shares.len() {
  51. let curr: [BigInt;2] = [shares[i].clone(), (i+1).to_bigint().unwrap()];
  52. r.push(curr);
  53. }
  54. r
  55. }
  56. fn unpack_shares(s: Vec<[BigInt;2]>) -> (Vec<BigInt>, Vec<BigInt>) {
  57. let mut shares: Vec<BigInt> = Vec::new();
  58. let mut is: Vec<BigInt> = Vec::new();
  59. for i in 0..s.len() {
  60. shares.push(s[i][0].clone());
  61. is.push(s[i][1].clone());
  62. }
  63. (shares, is)
  64. }
  65. fn mod_inverse(a: BigInt, module: BigInt) -> BigInt {
  66. // TODO search biguint impl of mod_inv
  67. let mut mn = (module.clone(), a);
  68. let mut xy: (BigInt, BigInt) = (Zero::zero(), One::one());
  69. let big_zero: BigInt = Zero::zero();
  70. while mn.1 != big_zero {
  71. xy = (xy.1.clone(), xy.0 - (mn.0.clone() / mn.1.clone()) * xy.1);
  72. mn = (mn.1.clone(), modulus(&mn.0, &mn.1));
  73. }
  74. while xy.0 < Zero::zero() {
  75. xy.0 += module.clone();
  76. }
  77. xy.0
  78. }
  79. pub fn lagrange_interpolation(p: &BigInt, shares_packed: Vec<[BigInt;2]>) -> BigInt {
  80. let mut res_n: BigInt = Zero::zero();
  81. let mut res_d: BigInt = Zero::zero();
  82. let (shares, sh_i) = unpack_shares(shares_packed);
  83. for i in 0..shares.len() {
  84. let mut lagrange_numerator: BigInt = One::one();
  85. let mut lagrange_denominator: BigInt = One::one();
  86. for j in 0..shares.len() {
  87. if shares[i] != shares[j] {
  88. let curr_l_numerator = &sh_i[j];
  89. let curr_l_denominator = &sh_i[j] - &sh_i[i];
  90. lagrange_numerator = lagrange_numerator * curr_l_numerator;
  91. lagrange_denominator = lagrange_denominator * curr_l_denominator;
  92. }
  93. }
  94. let numerator: BigInt = &shares[i] * &lagrange_numerator;
  95. let quo: BigInt = (&numerator / &lagrange_denominator) + (&lagrange_denominator ) % &lagrange_denominator;
  96. if quo != Zero::zero() {
  97. res_n = res_n + quo;
  98. } else {
  99. let res_n_mul_lagrange_den = res_n * &lagrange_denominator;
  100. res_n = res_n_mul_lagrange_den + numerator;
  101. res_d = res_d + lagrange_denominator;
  102. }
  103. }
  104. let modinv_mul: BigInt;
  105. if res_d != Zero::zero() {
  106. let modinv = mod_inverse(res_d, p.clone());
  107. modinv_mul = res_n * modinv;
  108. } else {
  109. modinv_mul = res_n;
  110. }
  111. let r = modulus(&modinv_mul, &p);
  112. r
  113. }
  114. #[cfg(test)]
  115. mod tests {
  116. use super::*;
  117. #[test]
  118. fn test_create_and_lagrange_interpolation() {
  119. let mut rng = rand::thread_rng();
  120. let p = rng.gen_biguint(1024).to_bigint().unwrap();
  121. println!("p: {:?}", p);
  122. let k = BigInt::parse_bytes(b"123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890", 10).unwrap();
  123. let s = create(3, 6, &p, &k);
  124. // println!("s: {:?}", s);
  125. let mut shares_to_use: Vec<[BigInt;2]> = Vec::new();
  126. shares_to_use.push(s[2].clone());
  127. shares_to_use.push(s[1].clone());
  128. shares_to_use.push(s[0].clone());
  129. let r = lagrange_interpolation(&p, shares_to_use);
  130. println!("recovered secret: {:?}", r.to_string());
  131. println!("original secret: {:?}", k.to_string());
  132. assert_eq!(k, r);
  133. }
  134. }