shamir-vault

Crates.ioshamir-vault
lib.rsshamir-vault
version1.3.0
created_at2025-01-19 12:16:21.000092+00
updated_at2025-11-27 08:15:06.222158+00
descriptionA Rust Crate implementation of Shamir's Secret Sharing algorithm
homepagehttps://github.com/simplysabir/shamir-vault
repositoryhttps://github.com/simplysabir/shamir-vault
max_upload_size
id1522775
size21,640
Sabir Khan (simplysabir)

documentation

README

Shamir Vault

shamir-vault is a Rust crate that provides an implementation of Shamir's Secret Sharing algorithm, enabling secure splitting and reconstruction of secrets. This crate allows you to divide a secret into multiple shares and reconstruct it with a minimum threshold of shares, ensuring data security and redundancy.

Features

  • Split secrets into n shares with a threshold t required for reconstruction.
  • Robust error handling for input validation.
  • Implementation using Galois Field arithmetic for security and efficiency.
  • Easy-to-use API with comprehensive test coverage.
  • no_std compatible - works in embedded and WASM environments
  • Explicit RNG control - you provide the randomness source for better security

Installation

Add shamir-vault to your Cargo.toml dependencies:

[dependencies]
shamir-vault = "1.3.0"

For no_std environments, both dependencies will automatically work without their default features.

Rand Version Compatibility

This crate works with both rand 0.8 and 0.9. The way you instantiate the RNG differs between versions:

For rand 0.8.x:

use rand::thread_rng;

let secret = b"My Super Secret Data";
let shares = split(secret, 5, 3, &mut thread_rng()).unwrap();

For rand 0.9.x:

use rand::rng;

let secret = b"My Super Secret Data";
let shares = split(secret, 5, 3, &mut rng()).unwrap();

Alternatively with rand 0.9, you can also use:

use rand::thread_rng::thread_rng;

let secret = b"My Super Secret Data";
let shares = split(secret, 5, 3, &mut thread_rng()).unwrap();

The split function accepts any &mut dyn RngCore, so it's compatible with any version - just use the appropriate import for your rand version.

Usage

1. Splitting a Secret

You can split a secret into multiple shares, requiring a specified threshold for reconstruction. You must provide your own RNG instance.

use shamir_vault::{split, combine};

fn main() {
    let secret = b"My Super Secret Data";
    // Use rand::thread_rng() for rand 0.8, or rand::rng() for rand 0.9
    let mut rng = rand::thread_rng(); // or rand::rng() for 0.9+
    let shares = split(secret, 5, 3, &mut rng).expect("Failed to split secret");
    
    println!("Generated Shares:");
    for (i, share) in shares.iter().enumerate() {
        println!("Share {}: {:?}", i + 1, share);
    }
}

Parameters:

  • secret: A byte array representing the secret.
  • shares: The total number of shares to generate.
  • threshold: The minimum number of shares required to reconstruct the secret.
  • rng: A mutable reference to any RNG implementing RngCore.

Errors:

  • InvalidShareCount: If shares are not between 2 and 255.
  • InvalidThreshold: If the threshold is not between 2 and 255.
  • SharesLessThanThreshold: If the number of shares is less than the threshold.
  • EmptySecret: If the secret is empty.

2. Reconstructing a Secret

To recover the original secret, provide at least the threshold number of shares.

use shamir_vault::{split, combine};

fn main() {
    let secret = b"My Super Secret Data";
    // Use rand::thread_rng() for rand 0.8, or rand::rng() for rand 0.9
    let mut rng = rand::thread_rng(); // or rand::rng() for 0.9+
    let shares = split(secret, 5, 3, &mut rng).expect("Failed to split secret");
    
    let recovered_secret = combine(&shares[0..3]).expect("Failed to reconstruct secret");
    
    assert_eq!(secret, recovered_secret.as_slice());
    println!("Recovered Secret: {:?}", String::from_utf8_lossy(&recovered_secret));
}

Parameters:

  • shares: A slice of shares used for reconstruction.

Errors:

  • InconsistentShareLength: If shares have varying lengths.
  • DuplicateShares: If there are duplicate shares.
  • ShareCountMismatch: If the provided shares count does not match the required count.

3. Handling Errors

This crate provides robust error handling with the ShamirError enum.

use shamir_vault::{split, ShamirError};

fn main() {
    // Use rand::thread_rng() for rand 0.8, or rand::rng() for rand 0.9
    let mut rng = rand::thread_rng(); // or rand::rng() for 0.9+
    match split(b"", 5, 3, &mut rng) {
        Ok(_) => println!("Secret successfully split"),
        Err(ShamirError::EmptySecret) => println!("Secret cannot be empty"),
        Err(e) => println!("Error: {}", e),
    }
}

4. Using in no_std Environments

For embedded systems or WASM, you can use any RNG that implements RngCore:

#![no_std]
extern crate alloc;

use shamir_vault::{split, combine};
use alloc::vec::Vec;
use rand_core::RngCore;

// Example with a custom RNG or hardware RNG
fn split_secret_embedded(mut rng: impl RngCore) {
    let secret = b"My Super Secret Data";
    let shares = split(secret, 5, 3, &mut rng).expect("Failed to split secret");
    // ... use shares
}

API Documentation

Functions

split(secret: &[u8], shares: usize, threshold: usize, rng: &mut (dyn RngCore + '_)) -> Result<Vec<Vec<u8>>, ShamirError>

Splits the given secret into a specified number of shares with a threshold for reconstruction.

combine(shares: &[Vec<u8>]) -> Result<Vec<u8>, ShamirError>

Combines the provided shares to reconstruct the original secret.

Errors

ShamirError

  • InvalidShareCount
  • InvalidThreshold
  • SharesLessThanThreshold
  • EmptySecret
  • DuplicateShares
  • InconsistentShareLength
  • ShareCountMismatch

Security Considerations

  • Ensure that secret shares are distributed securely to prevent unauthorized reconstruction.
  • Use a sufficiently high threshold to prevent loss due to missing shares.
  • Keep the number of generated shares within a reasonable limit (max 255).
  • Use a cryptographically secure RNG - rand::thread_rng() is recommended for most applications.
  • Control your randomness source - the explicit RNG parameter gives you full control over entropy.

Performance

The crate is optimized for performance using precomputed Galois Field tables for fast arithmetic operations. The no_std design makes it suitable for resource-constrained environments.

Testing

Unit tests are included to ensure the correctness of the implementation.

Run tests with:

cargo test

Breaking Changes in v1.2.0

  • RNG Parameter Required: The split function now requires an explicit RNG parameter
  • no_std Compatible: Now works in no_std environments
  • Dependency Changes: rand and thiserror now use default-features = false

License

This project is licensed under the MIT License. See the LICENSE file for more details.

Contribution

Feel free to submit issues, suggestions, or pull requests on GitHub: shamir-vault

Author

Developed by Sabir Khan

Commit count: 6

cargo fmt