A pure-Rust implementation of various threshold secret sharing schemes

Overview

Threshold Secret Sharing

Build Status Latest version License: MIT/Apache2

Efficient pure-Rust library for secret sharing, offering efficient share generation and reconstruction for both traditional Shamir sharing and packet sharing. For now, secrets and shares are fixed as prime field elements represented by i64 values.

Installation

Cargo

[dependencies]
threshold-secret-sharing = "0.2"

GitHub

git clone https://github.com/snipsco/rust-threshold-secret-sharing
cd rust-threshold-secret-sharing
cargo build --release

Examples

Several examples are included in the examples/ directory. Run each with cargo using e.g.

cargo run --example shamir

for the Shamir example below.

Shamir sharing

Using the Shamir scheme is relatively straight-forward.

When choosing parameters, threshold and share_count must be chosen to satisfy security requirements, and prime must be large enough to correctly encode the value to be shared (and such that prime >= share_count + 1).

When reconstructing the secret, indices must be explicitly provided to identify the shares; these correspond to the indices the shares had in the vector returned by share().

extern crate threshold_secret_sharing as tss;

fn main() {
  // create instance of the Shamir scheme
  let ref tss = tss::shamir::ShamirSecretSharing {
    threshold: 8,           // privacy threshold
    share_count: 20,        // total number of shares to generate
    prime: 41               // prime field to use
  };

  let secret = 5;

  // generate shares for secret
  let all_shares = tss.share(secret);

  // artificially remove some of the shares
  let number_of_recovered_shared = 10;
  assert!(number_of_recovered_shared >= tss.reconstruct_limit());
  let recovered_indices: Vec<usize> = (0..number_of_recovered_shared).collect();
  let recovered_shares: &[i64] = &all_shares[0..number_of_recovered_shared];

  // reconstruct using remaining subset of shares
  let reconstructed_secret = tss.reconstruct(&recovered_indices, recovered_shares);
  assert_eq!(reconstructed_secret, secret);
}

Packed sharing

If many secrets are to be secret shared, it may be beneficial to use the packed scheme where several secrets are packed into each share. While still very computational efficient, one downside is that the parameters are somewhat restricted.

Specifically, the parameters are split in scheme parameters and implementation parameters:

  • the former, like in Shamir sharing, determines the abstract properties of the scheme, yet now also with a secret_count specifying how many secrets are to be packed into each share; the reconstruction limit is implicitly defined as secret_count + threshold + 1
  • the latter is related to the implementation (currently based on the Fast Fourier Transform) and requires not only a prime specifying the field, but also two principal roots of unity within that field, which must be respectively a power of 2 and a power of 3

Due to this increased complexity, providing helper functions for finding suitable parameters are in progress. For now, a few fixed fields are included in the packed module as illustrated in the example below:

  • PSS_4_8_3, PSS_4_26_3, PSS_155_728_100, PSS_155_19682_100

with format PSS_T_N_D for sharing D secrets into N shares with a threshold of T.

extern crate threshold_secret_sharing as tss;

fn main() {
  // use predefined parameters
  let ref tss = tss::packed::PSS_4_26_3;

  // generate shares for a vector of secrets
  let secrets = [1, 2, 3];
  let all_shares = tss.share(&secrets);

  // artificially remove some of the shares; keep only the first 8
  let indices: Vec<usize> = (0..8).collect();
  let shares = &all_shares[0..8];

  // reconstruct using remaining subset of shares
  let recovered_secrets = tss.reconstruct(&indices, shares);
  assert_eq!(recovered_secrets, vec![1, 2, 3]);
}

Homomorphic properties

Both the Shamir and the packed scheme enjoy certain homomorphic properties: shared secrets can be transformed by manipulating the shares. Both addition and multiplications work, yet notice that the reconstruction limit in the case of multiplication goes up by a factor of two for each application.

extern crate threshold_secret_sharing as tss;

fn main() {
  // use predefined parameters
  let ref tss = tss::PSS_4_26_3;

  // generate shares for first vector of secrets
  let secrets_1 = [1, 2, 3];
  let shares_1 = tss.share(&secrets_1);

  // generate shares for second vector of secrets
  let secrets_2 = [4, 5, 6];
  let shares_2 = tss.share(&secrets_2);

  // combine shares pointwise to get shares of the sum of the secrets
  let shares_sum: Vec<i64> = shares_1.iter().zip(&shares_2)
    .map(|(a, b)| (a + b) % tss.prime).collect();

  // artificially remove some of the shares; keep only the first 8
  let indices: Vec<usize> = (0..8).collect();
  let shares = &shares_sum[0..8];

  // reconstruct using remaining subset of shares
  let recovered_secrets = tss.reconstruct(&indices, shares);
  assert_eq!(recovered_secrets, vec![5, 7, 9]);
}

Parameter generation

While it's straight-forward to instantiate the Shamir scheme, as mentioned above the packed scheme is more tricky and a few helper methods are provided as a result. Since some applications needs only a fixed choice of parameters, these helper methods are optional and only included if the paramgen feature is activated during compilation:

cargo build --features paramgen

which also adds several extra dependencies.

Performance

So far most performance efforts has been focused on share generation for the packed scheme, with some obvious enhancements for reconstruction in the process of being implemented. As an example, sharing 100 secrets into approximately 20,000 shares with the packed scheme runs in around 31ms on a recent laptop, and in around 590ms on a Raspberry Pi 3.

These numbers were obtained by running

cargo bench

using the nightly toolchain.

License

Licensed under either of

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

You might also like...
A simple port sniffer(scanner) implementation with 🦀

A simple port sniffer(scanner) implementation with 🦀 Install from crates.io crago install ports-sniffer From aur: yay -S ports-sniffer Arguments Argu

A Trojan implementation from SSPanel-Uim group

TrojanX A Trojan-based proxy implementation. Attention Early Version This is an early version. Security, features, and potential bugs may be insuffici

Detects usage of unsafe Rust in a Rust crate and its dependencies.
Detects usage of unsafe Rust in a Rust crate and its dependencies.

cargo-geiger ☢️ Looking for maintainer: https://github.com/rust-secure-code/cargo-geiger/issues/210 A program that lists statistics related to the usa

An esoteric language/compiler written with Rust and Rust LLVM bindings

MeidoLang (メイドラング) A not so useful and esoteric language. The goal of this project was to contain some quirky or novel syntax in a stack-style program

Rust-verification-tools - RVT is a collection of tools/libraries to support both static and dynamic verification of Rust programs.

Rust verification tools This is a collection of tools/libraries to support both static and dynamic verification of Rust programs. We see static verifi

Rust bindings for libinjection

libinjection-rs Rust bindings for libinjection. How to use Add libinjection to dependencies of Cargo.toml: libinjection = "0.2" Import crate: extern c

A simple password manager written in Rust
A simple password manager written in Rust

ripasso A simple password manager written in Rust. The root crate ripasso is a library for accessing and decrypting passwords stored in pass format (G

tcp connection hijacker, rust rewrite of shijack
tcp connection hijacker, rust rewrite of shijack

rshijack tcp connection hijacker, rust rewrite of shijack from 2001. This was written for TAMUctf 2018, brick house 100. The target was a telnet serve

A fast, simple, recursive content discovery tool written in Rust.
A fast, simple, recursive content discovery tool written in Rust.

A simple, fast, recursive content discovery tool written in Rust 🦀 Releases ✨ Example Usage ✨ Contributing ✨ Documentation 🦀 😕 What the heck is a f

Comments
  • partial reveal?

    partial reveal?

    Using this library, is it possible to "partially reveal" a secret using fewer shares than the threshold, produce some value, and use the value + the remaining shares to reconstruct the secret?

    opened by S1nus 1
  • failing

    failing

    `let ref tss = tss::shamir::ShamirSecretSharing { threshold: 1, share_count: 4, prime : 11 };

    let mobile_number_secret = 9034218120;
    let all_shares = tss.share(mobile_number_secret);
    let recovered_share = 3;
    assert!(recovered_share >= tss.reconstruct_limit());
    let recovered_indices: Vec<usize> = (0..recovered_share).collect();
    let recovered_shares: &[i64] = &all_shares[0..recovered_share];
    

    // // reconstruct using remaining subset of shares let reconstructed_secret = tss.reconstruct(&recovered_indices, recovered_shares); assert_eq!(reconstructed_secret, mobile_number_secret);`

    image

    opened by Alakazam03 0
  • Support full range of i64 for basic shamir case

    Support full range of i64 for basic shamir case

    • upsample numbers in calculate polynomial to support full range of i64 values in standalone shamir sharing case.
    • add respective test to check no overflow occurs
    opened by canufeel 0
Owner
Snips
We make technology disappear
Snips
Cross-platform Secure TUI Secret Locker

SafeCloset keeps your secrets in password protected files. SafeCloset is designed to be convenient and avoid common weaknesses like external editing or temporary files written on disk.

Canop 63 Dec 26, 2022
Lightweight slowloris (HTTP DoS) implementation in Rust.

slowlorust Lightweight slowloris (HTTP DoS) implementation in Rust. Slowloris is a denial-of-service attack program which allows an attacker to overwh

Michael Van Leeuwen 6 Sep 29, 2022
A paseto implementation in rust.

Paseto Rust Paseto is everything you love about JOSE (JWT, JWE, JWS) without any of the many design deficits that plague the JOSE standards. This is d

Instructure, Inc. 145 Nov 7, 2022
OpenSK is an open-source implementation for security keys written in Rust that supports both FIDO U2F and FIDO2 standards.

OpenSK This repository contains a Rust implementation of a FIDO2 authenticator. We developed OpenSK as a Tock OS application. We intend to bring a ful

Google 2.4k Jan 7, 2023
Userspace WireGuard® Implementation in Rust

BoringTun BoringTun is an implementation of the WireGuard® protocol designed for portability and speed. BoringTun is successfully deployed on millions

Cloudflare 4.8k Jan 4, 2023
Rust implementation of The Update Framework (TUF)

rust-tuf A Rust implementation of The Update Framework (TUF). Full documentation is hosted at docs.rs. Warning: Beta Software This is under active dev

heartsucker 152 Dec 11, 2022
A Rust implementation of the Message Layer Security group messaging protocol

Molasses An extremely early implementation of the Message Layer Security group messaging protocol. This repo is based on draft 4 of the MLS protocol s

Trail of Bits 109 Dec 13, 2022
Rust implementation of the H3 geospatial indexing system.

h3o Rust implementation of the H3 geospatial indexing system. Design This is not a binding of the reference implementation, but a reimplementation fro

Hydronium Labs 196 Jan 31, 2023
Fast, Concurrent, Rust based Tidal-Media-Downloader implementation.

tdl tdl is a rust implementation of the Python Script Tidal-Media-Downloader. Overview tdl offers significant performance improvements over the origin

null 42 Mar 18, 2023
An implementation of webauthn components for Rustlang servers

Webauthn-rs Webauthn is a modern approach to hardware based authentication, consisting of a user with an authenticator device, a browser or client tha

Kanidm 226 Dec 28, 2022