Skip to content

Commit

Permalink
Shamir secret sharing (#782)
Browse files Browse the repository at this point in the history
* Create lib.rs

* Create shamir_secret_sharing.rs

* Delete examples/src directory

* Update Cargo.toml

* Create lib.rs

* Create shamir_secret_sharing.rs

* Create Cargo.toml

* Create README.md

* Update shamir_secret_sharing.rs
  • Loading branch information
cliraa authored Jan 26, 2024
1 parent ff2bdb7 commit 2395ee5
Show file tree
Hide file tree
Showing 5 changed files with 147 additions and 1 deletion.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[workspace]

members = ["math", "crypto", "gpu", "benches", "provers/plonk", "provers/stark", "provers/cairo", "provers/groth16", "provers/groth16/arkworks-adapter", "examples/merkle-tree-cli", "examples/prove-miden", "winterfell_adapter"]
members = ["math", "crypto", "gpu", "benches", "provers/plonk", "provers/stark", "provers/cairo", "provers/groth16", "provers/groth16/arkworks-adapter", "examples/merkle-tree-cli", "examples/prove-miden", "winterfell_adapter", "examples/shamir_secret_sharing"]
exclude = ["ensure-no_std"]
resolver = "2"

Expand Down
13 changes: 13 additions & 0 deletions examples/shamir_secret_sharing/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[package]
name = "shamir_secret_sharing"
version.workspace = true
edition.workspace = true
license.workspace = true
repository.workspace = true

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]

lambdaworks-math = { git = "https://github.com/lambdaclass/lambdaworks.git" }
rand = { version = "0.8", features = [ "std", "std_rng" ] }
34 changes: 34 additions & 0 deletions examples/shamir_secret_sharing/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# Shamir's Secret Sharing

## Usage example

```rust
// Definition of the secret
// Creation of 6 shares
// 3 shares will be used to recover the secret
let sss = ShamirSecretSharing {
secret: FE::new(1234),
n: 6,
k: 3,
};

// Polynomial calculation
let polynomial = sss.calculate_polynomial();

// Produce shares
let shares = sss.generating_shares(polynomial.clone());

// Specify the x and y coordinates of the shares to use
let shares_to_use_x = vec![shares.x[1], shares.x[3], shares.x[4]];
let shares_to_use_y = vec![shares.y[1], shares.y[3], shares.y[4]];

// Interpolation
let poly_2 = sss.reconstructing(shares_to_use_x, shares_to_use_y);

// Recover the free coefficient of the polynomial
let secret_recovered = sss.recover(&poly_2);

// Verifications
assert_eq!(polynomial, poly_2);
assert_eq!(sss.secret, secret_recovered);
```
1 change: 1 addition & 0 deletions examples/shamir_secret_sharing/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod shamir_secret_sharing;
98 changes: 98 additions & 0 deletions examples/shamir_secret_sharing/src/shamir_secret_sharing.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
use lambdaworks_math::{
field::{element::FieldElement, traits::IsField},
polynomial::Polynomial,
};

use rand::distributions::Standard;
use rand::prelude::Distribution;
use rand::random;

pub struct ShamirSecretSharing<F: IsField> {
secret: FieldElement<F>,
n: usize,
k: usize,
}

pub struct Shares<F: IsField> {
pub x: Vec<FieldElement<F>>,
pub y: Vec<FieldElement<F>>,
}

impl<F: IsField> ShamirSecretSharing<F> {
pub fn calculate_polynomial(&self) -> Polynomial<FieldElement<F>>
where
Standard: Distribution<<F as IsField>::BaseType>,
{
let mut coefficients = Vec::new();
coefficients.push(self.secret.clone());
for _ in 0..self.k - 1 {
coefficients.push(FieldElement::<F>::new(random()));
}

let polynomial = Polynomial::new(coefficients.as_slice());
polynomial
}

pub fn generating_shares(&self, polynomial: Polynomial<FieldElement<F>>) -> Shares<F>
where
Standard: Distribution<<F as IsField>::BaseType>,
{
let mut shares_x: Vec<FieldElement<F>> = Vec::new();
let mut shares_y: Vec<FieldElement<F>> = Vec::new();

for _ in 0..self.n {
let x = FieldElement::<F>::new(random());
let y = polynomial.evaluate(&x);
shares_x.push(x);
shares_y.push(y);
}

Shares {
x: shares_x,
y: shares_y,
}
}

pub fn reconstructing(
&self,
x: Vec<FieldElement<F>>,
y: Vec<FieldElement<F>>,
) -> Polynomial<FieldElement<F>> {
Polynomial::interpolate(&x, &y).unwrap()
}

pub fn recover(&self, polynomial: &Polynomial<FieldElement<F>>) -> FieldElement<F> {
polynomial.coefficients()[0].clone()
}
}

#[cfg(test)]
#[allow(non_snake_case)]
mod tests {

use crate::shamir_secret_sharing::ShamirSecretSharing;
use lambdaworks_math::field::element::FieldElement;
use lambdaworks_math::field::fields::u64_prime_field::U64PrimeField;

#[test]
fn shamir_secret_sharing_works() {
const ORDER: u64 = 1613;
type F = U64PrimeField<ORDER>;
type FE = FieldElement<F>;

let sss = ShamirSecretSharing {
secret: FE::new(1234),
n: 6,
k: 3,
};

let polynomial = sss.calculate_polynomial();
let shares = sss.generating_shares(polynomial.clone());
let shares_to_use_x = vec![shares.x[1], shares.x[3], shares.x[4]];
let shares_to_use_y = vec![shares.y[1], shares.y[3], shares.y[4]];
let poly_2 = sss.reconstructing(shares_to_use_x, shares_to_use_y);
let secret_recovered = sss.recover(&poly_2);
assert_eq!(polynomial, poly_2);
assert_eq!(sss.secret, secret_recovered);
}
}

0 comments on commit 2395ee5

Please sign in to comment.