Skip to content

Commit

Permalink
add explanations
Browse files Browse the repository at this point in the history
  • Loading branch information
0x471 committed Dec 4, 2024
1 parent 4b8ee0f commit 5f7163c
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 27 deletions.
25 changes: 25 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# **Shamir's Secret Sharing**

This is an implementation of **Shamir's Secret Sharing** scheme on the **BN254** field using the **arkworks** library. It allows splitting a secret into multiple shares such that the secret can only be reconstructed when a minimum number of shares (threshold) are available. This ensures both fault tolerance and security for sensitive information.

---

## **Overview**

### **What is Shamir's Secret Sharing?**
Shamir's Secret Sharing is a cryptographic technique that allows a secret (e.g., a password, private key, or any sensitive data) to be divided into \( n \) shares. To reconstruct the secret, at least \( k \) (threshold) shares are required. It is based on polynomial interpolation and works over a finite field.

- **Security**: With fewer than \( k \) shares, the secret cannot be reconstructed.
- **Fault Tolerance**: Even if some shares are lost, the secret can still be recovered using any \( k \) shares.

---

### **Dependencies**
Add the following dependencies to your `Cargo.toml` file:
```toml
[dependencies]
ark-bn254 = "0.5.0"
ark-ff = "0.5.0"
ark-poly = "0.5.0"
rand = "0.8.5"
```
52 changes: 25 additions & 27 deletions src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,75 +4,72 @@ use ark_poly::{univariate::DensePolynomial, DenseUVPolynomial, Polynomial};
use rand::rngs::OsRng;

struct Point {
x: Field,
y: Field,
x: Field, // The x-coordinate of the share
y: Field, // The y-coordinate of the share (f(x) evaluated at x)
}

struct ShamirSecretShare {
total_shares: usize,
total_shares: usize, // Total number of shares to distribute
}

impl ShamirSecretShare {
fn new(total_shares: usize) -> Self {
Self {
total_shares,
}
Self { total_shares }
}

fn generate_polynomial(
secret: Field,
degree: usize,
rand: &mut OsRng,
) -> DensePolynomial<Field> {
let mut coefficients = vec![secret];
let mut coefficients = vec![secret]; // The constant term of the polynomial (a_0 = secret)
for _ in 1..degree {
let coefficient = Field::rand(rand);
coefficients.push(coefficient)
let coefficient = Field::rand(rand); // Generate random coefficients a_1, a_2, ..., a_{k-1}
coefficients.push(coefficient);
}
DensePolynomial::from_coefficients_vec(coefficients)
DensePolynomial::from_coefficients_vec(coefficients) // Construct the polynomial f(x) = a_0 + a_1x + ... + a_{k-1}x^{k-1}
}

fn generate_shares(&self, secret: Field, degree: usize, rand: &mut OsRng) -> Vec<Point> {
let poly = Self::generate_polynomial(secret, degree, rand);
let poly = Self::generate_polynomial(secret, degree, rand); // Generate the polynomial representing the secret
(1..=self.total_shares)
.map(|i| {
let x = Field::from(i as u64);
let y = poly.evaluate(&x);
Point { x, y }
let x = Field::from(i as u64); // Assign x-values 1, 2, ..., total_shares
let y = poly.evaluate(&x); // Compute f(x) to generate the corresponding y-value (the share)
Point { x, y } // Create a Point struct for each share
})
.collect()
.collect() // Collect all shares into a vector
}

fn reconstruct_secret(shares: &[Point], threshold: usize) -> Field {
let mut secret = Field::from(0);

for i in 0..threshold {
let point_x = &shares[i];
let x_i = point_x.x;
let y_i = point_x.y;
let mut lagrange_coeff = Field::from(1);
let x_i = point_x.x; // The x-coordinate of the i-th share
let y_i = point_x.y; // The y-coordinate of the i-th share (f(x_i))
let mut lagrange_coeff = Field::from(1); // Initialize the Lagrange coefficient for this share

for j in 0..threshold {
if i != j {
let point_j = &shares[j];
let x_j = point_j.x;
//let y_j = point_j.y;
let numerator = Field::from(0) - x_j; // -x_j
let denominator = x_i - x_j; // x_i - x_j
let x_j = point_j.x; // The x-coordinate of the j-th share
let numerator = Field::from(0) - x_j; // Compute the numerator: -x_j
let denominator = x_i - x_j; // Compute the denominator: x_i - x_j
lagrange_coeff *= numerator * denominator.inverse().unwrap();
// Modular inverse
// Update the Lagrange coefficient with the term (-x_j / (x_i - x_j))
}
}

secret += lagrange_coeff * y_i;
secret += lagrange_coeff * y_i; // Add the contribution of this share: y_i * Lagrange coefficient
}

secret
secret // The reconstructed secret is f(0), the constant term of the polynomial
}
}

fn main() {
let secret = Field::from(1234u64); // The secret to be shared
let secret = Field::from(1337u64); // The secret to be shared
let threshold = 3; // Minimum number of shares required to reconstruct the secret
let mut rng = OsRng;

Expand All @@ -87,7 +84,8 @@ fn main() {

// Step 2: Reconstruct the secret using the first `threshold` shares
let reconstruction_shares = &shares[0..threshold]; // Take the first `threshold` shares
let reconstructed_secret = ShamirSecretShare::reconstruct_secret(reconstruction_shares, threshold);
let reconstructed_secret =
ShamirSecretShare::reconstruct_secret(reconstruction_shares, threshold);

println!("\nOriginal Secret: {}", secret);
println!("Reconstructed Secret: {}", reconstructed_secret);
Expand Down

0 comments on commit 5f7163c

Please sign in to comment.