Browse Source

add verifying commitment

Chelsea H. Komlo 5 years ago
parent
commit
fed045bbe5
1 changed files with 57 additions and 3 deletions
  1. 57 3
      src/vss.rs

+ 57 - 3
src/vss.rs

@@ -58,8 +58,25 @@ pub fn generate_shares(secret: Secret, numshares: u32, threshold: u32) -> Result
 }
 
 /// Verify that a share is consistent with a commitment.
-pub fn verify_share(share: Share, commitment: Commitment) -> Result<bool, &'static str> {
-    unimplemented!("Not yet implemented")
+pub fn verify_share(share: Share, commitment: &Commitment) -> Result<bool, &'static str> {
+    let f_result = ED25519_BASEPOINT_POINT * share.value;
+
+    // always calculate at least the first share
+    let mut result = commitment.coms[0];
+
+    for i in 1..share.index+1 {
+        // check in case of the last share
+        if (i as usize) >= commitment.coms.len() {
+            break;
+        }
+
+        let next_comm = commitment.coms[i as usize];
+        let x_raised_to_threshold = share.index.pow(i as u32);
+        result += next_comm * Scalar::from(x_raised_to_threshold);
+    }
+
+    let is_valid = f_result == result;
+    Ok(is_valid)
 }
 
 /// Reconstruct the secret from enough (at least the threshold) already-verified shares.
@@ -76,7 +93,7 @@ pub fn reconstruct_secret(shares: &Vec<Share>) -> Result<Secret, &'static str> {
         for j in 0..numshares {
             if j==i { continue; }
             num *= Scalar::from(shares[j].index);
-            den *= (Scalar::from(shares[j].index) - Scalar::from(shares[i].index));
+            den *= Scalar::from(shares[j].index) - Scalar::from(shares[i].index);
         }
         if den == Scalar::zero() {
             return Err("Duplicate shares provided");
@@ -119,6 +136,7 @@ mod tests {
         let res = generate_shares(s, 5, 2);
         assert!(res.is_ok());
         let (com, shares) = res.unwrap();
+        assert!(shares.len() == 5);
 
         let mut recshares: Vec<Share> = Vec::new();
         recshares.push(shares[1]);
@@ -179,4 +197,40 @@ mod tests {
             assert_eq!(res.err(), Some("Threshold cannot exceed numshares"));
         }
     }
+
+    #[test]
+    fn share_commitment_valid() {
+        let s = Secret::from(42u32);
+
+        let res = generate_shares(s, 5, 2);
+        assert!(res.is_ok());
+        let (com, shares) = res.unwrap();
+
+        for share in shares {
+            let is_valid = verify_share(share, &com);
+            assert!(is_valid.is_ok());
+            assert!(is_valid.unwrap());
+        }
+    }
+
+    #[test]
+    fn share_commitment_invalid() {
+        let s1 = Secret::from(42u32);
+        let s2 = Secret::from(43u32);
+
+        let res1 = generate_shares(s1, 5, 2);
+        assert!(res1.is_ok());
+        let (_, shares1) = res1.unwrap();
+
+        let res2 = generate_shares(s2, 5, 2);
+        assert!(res2.is_ok());
+        let (com2, _) = res2.unwrap();
+
+        for share in shares1 {
+            // test that commitments to a different set of shares fails
+            let is_valid = verify_share(share, &com2);
+            assert!(is_valid.is_ok());
+            assert_ne!(is_valid.unwrap(), true);
+        }
+    }
 }