vss.rs 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. use curve25519_dalek::edwards::EdwardsPoint;
  2. use curve25519_dalek::scalar::Scalar;
  3. use curve25519_dalek::constants::ED25519_BASEPOINT_POINT;
  4. use rand::rngs::ThreadRng;
  5. pub type Secret = Scalar;
  6. #[derive(Copy, Clone)]
  7. pub struct Share {
  8. index: u32,
  9. value: Scalar,
  10. }
  11. pub struct Commitment {
  12. coms: Vec<EdwardsPoint>,
  13. }
  14. /// Create secret shares for a given secret.
  15. pub fn generate_shares(secret: Secret, numshares: u32, threshold: u32) -> Result<(Commitment, Vec<Share>), &'static str> {
  16. if threshold < 1 { return Err("Threshold cannot be 0") }
  17. if numshares < 1 { return Err("Number of shares cannot be 0") }
  18. if threshold > numshares { return Err("Threshold cannot exceed numshares") }
  19. let numcoeffs = (threshold-1) as usize;
  20. let mut coeffs: Vec<Scalar> = Vec::with_capacity(numcoeffs);
  21. let mut rng: ThreadRng = rand::thread_rng();
  22. let mut shares: Vec<Share> = Vec::with_capacity(numshares as usize);
  23. let mut comm: Commitment = Commitment { coms: Vec::with_capacity(threshold as usize) };
  24. for _ in 0..numcoeffs {
  25. coeffs.push(Scalar::random(&mut rng));
  26. }
  27. for share_index in 1..numshares+1 {
  28. // Evaluate the polynomial with `secret` as the constant term
  29. // and `coeffs` as the other coefficients at the point x=share_index
  30. // using Horner's method
  31. let scalar_index = Scalar::from(share_index);
  32. let mut value = Scalar::zero();
  33. for i in (0..numcoeffs).rev() {
  34. value += coeffs[i];
  35. value *= scalar_index;
  36. }
  37. value += secret;
  38. shares.push(Share{ index: share_index, value: value });
  39. }
  40. comm.coms.push(ED25519_BASEPOINT_POINT * secret);
  41. for c in coeffs {
  42. comm.coms.push(ED25519_BASEPOINT_POINT * c);
  43. }
  44. Ok((comm, shares))
  45. }
  46. /// Verify that a share is consistent with a commitment.
  47. pub fn verify_share(share: Share, commitment: Commitment) -> Result<bool, &'static str> {
  48. unimplemented!("Not yet implemented")
  49. }
  50. /// Reconstruct the secret from enough (at least the threshold) already-verified shares.
  51. pub fn reconstruct_secret(shares: &Vec<Share>) -> Result<Secret, &'static str> {
  52. let numshares = shares.len();
  53. if numshares < 1 { return Err("No shares provided"); }
  54. let mut lagrange_coeffs: Vec<Scalar> = Vec::with_capacity(numshares);
  55. for i in 0..numshares {
  56. let mut num = Scalar::one();
  57. let mut den = Scalar::one();
  58. for j in 0..numshares {
  59. if j==i { continue; }
  60. num *= Scalar::from(shares[j].index);
  61. den *= (Scalar::from(shares[j].index) - Scalar::from(shares[i].index));
  62. }
  63. if den == Scalar::zero() {
  64. return Err("Duplicate shares provided");
  65. }
  66. lagrange_coeffs.push(num * den.invert());
  67. }
  68. let mut secret = Scalar::zero();
  69. for i in 0..numshares {
  70. secret += lagrange_coeffs[i] * shares[i].value;
  71. }
  72. return Ok(secret)
  73. }
  74. /// Create a proactive update.
  75. pub fn create_update(numshares: u32, threshold: u32) -> Result<(Commitment, Vec<Share>), &'static str> {
  76. unimplemented!("Not yet implemented")
  77. }
  78. /// Apply the commitment for the update to the master commitment.
  79. pub fn apply_commitment_update(oldcommitment: &Commitment, update: &Commitment) -> Result<Commitment, &'static str> {
  80. unimplemented!("Not yet implemented")
  81. }
  82. /// Apply the share update to an existing share
  83. pub fn apply_share_update(oldshare: &Share, update: &Share) -> Result<Share, &'static str> {
  84. unimplemented!("Not yet implemented")
  85. }
  86. #[cfg(test)]
  87. mod tests {
  88. use crate::vss::*;
  89. #[test]
  90. fn share_simple() {
  91. let s = Secret::from(42u32);
  92. let res = generate_shares(s, 5, 2);
  93. assert!(res.is_ok());
  94. let (com, shares) = res.unwrap();
  95. let mut recshares: Vec<Share> = Vec::new();
  96. recshares.push(shares[1]);
  97. recshares.push(shares[3]);
  98. let recres = reconstruct_secret(&recshares);
  99. assert!(recres.is_ok());
  100. assert_eq!(recres.unwrap(), s);
  101. }
  102. #[test]
  103. fn share_not_enough() {
  104. let s = Secret::from(42u32);
  105. let res = generate_shares(s, 5, 2);
  106. assert!(res.is_ok());
  107. let (com, shares) = res.unwrap();
  108. let mut recshares: Vec<Share> = Vec::new();
  109. recshares.push(shares[1]);
  110. let recres = reconstruct_secret(&recshares);
  111. assert!(recres.is_ok());
  112. assert_ne!(recres.unwrap(), s);
  113. }
  114. #[test]
  115. fn share_dup() {
  116. let s = Secret::from(42u32);
  117. let res = generate_shares(s, 5, 2);
  118. assert!(res.is_ok());
  119. let (com, shares) = res.unwrap();
  120. let mut recshares: Vec<Share> = Vec::new();
  121. recshares.push(shares[1]);
  122. recshares.push(shares[1]);
  123. let recres = reconstruct_secret(&recshares);
  124. assert!(recres.is_err());
  125. assert_eq!(recres.err(), Some("Duplicate shares provided"));
  126. }
  127. #[test]
  128. fn share_badparams() {
  129. let s = Secret::from(42u32);
  130. {
  131. let res = generate_shares(s, 5, 0);
  132. assert!(res.is_err());
  133. assert_eq!(res.err(), Some("Threshold cannot be 0"));
  134. }
  135. {
  136. let res = generate_shares(s, 0, 3);
  137. assert!(res.is_err());
  138. assert_eq!(res.err(), Some("Number of shares cannot be 0"));
  139. }
  140. {
  141. let res = generate_shares(s, 1, 3);
  142. assert!(res.is_err());
  143. assert_eq!(res.err(), Some("Threshold cannot exceed numshares"));
  144. }
  145. }
  146. }