|  | @@ -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);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  |  }
 |