ssss/
lib.rs

1// Copyright (c) 2020 ssss developers
2//
3// Licensed under the Apache License, Version 2.0
4// <LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0> or the MIT
5// license <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
6// option. All files in the project carrying such notice may not be copied,
7// modified, or distributed except according to those terms.
8
9//! # Shamir's Secret Sharing Scheme
10//!
11//! A [Shamir's Secret Sharing Scheme](https://en.wikipedia.org/wiki/Shamir%27s_Secret_Sharing) implementation in Rust
12//!
13//! To quote the Wikipedia article linked above:
14//!
15//! > Shamir's Secret Sharing is used to secure a secret in a distributed way, most often to secure other encryption keys.
16//! > The secret is split into multiple parts, called shares. These shares are used to reconstruct the original secret.
17//!
18//! > To unlock the secret via Shamir's secret sharing, you need a minimum number of shares. This is called the threshold,
19//! > and is used to denote the minimum number of shares needed to unlock the secret. Let us walk through an example:
20//!
21//! >> Problem: Company XYZ needs to secure their vault's passcode. They could use something standard, such as AES, but what
22//! >> if the holder of the key is unavailable or dies? What if the key is compromised via a malicious hacker or the holder
23//! >> of the key turns rogue, and uses their power over the vault to their benefit?
24//!
25//! This is where ssss comes in. It can be used to encrypt the vault's passcode and generate a certain number of shares,
26//! where a certain number of shares can be allocated to each executive within Company XYZ. Now, only if they pool their
27//! shares can they unlock the vault. The threshold can be appropriately set for the number of executives, so the vault
28//! is always able to be accessed by the authorized individuals. Should a share or two fall into the wrong hands,
29//! they couldn't open the passcode unless the other executives cooperated.
30//!
31//! # Example
32//!
33//! ```rust
34//! # use anyhow::Result;
35//! # use rand::{thread_rng, rngs::ThreadRng};
36//! # use ssss::{unlock, gen_shares, remove_random_entry, SsssConfig};
37//! #
38//! # fn main() -> Result<()> {
39//! let secret = "correct horse battery staple".as_bytes();
40//! let config = SsssConfig::default();
41//!
42//! // Generate 5 shares to be distributed, requiring a minimum of 3 later
43//! // to unlock the secret
44//! let mut shares = gen_shares(&config, &secret)?;
45//!
46//! // Check that all 5 shares can unlock the secret
47//! assert_eq!(shares.len(), 5);
48//! assert_eq!(unlock(&shares)?, secret);
49//!
50//! // Remove a random share from `shares` and check that 4 shares can unlock
51//! // the secret
52//! let mut rng = thread_rng();
53//! remove_random_entry(&mut rng, &mut shares);
54//! assert_eq!(shares.len(), 4);
55//! assert_eq!(unlock(&shares)?, secret);
56//!
57//! // Remove another random share from `shares` and check that 3 shares can unlock
58//! // the secret
59//! remove_random_entry(&mut rng, &mut shares);
60//! assert_eq!(shares.len(), 3);
61//! assert_eq!(unlock(&shares)?, secret);
62//!
63//! // Remove another random share from `shares` and check that 2 shares *CANNOT*
64//! // unlock the secret
65//! remove_random_entry(&mut rng, &mut shares);
66//! assert_eq!(shares.len(), 2);
67//! assert_ne!(unlock(&shares)?, secret);
68//! #
69//! # Ok(())
70//! # }
71//!
72
73// rustc lints
74#![cfg_attr(
75    all(msrv, feature = "unstable", nightly),
76    feature(
77        lint_reasons,
78        multiple_supertrait_upcastable,
79        must_not_suspend,
80        non_exhaustive_omitted_patterns_lint,
81        rustdoc_missing_doc_code_examples,
82        strict_provenance,
83    )
84)]
85#![cfg_attr(
86    msrv,
87    deny(
88        absolute_paths_not_starting_with_crate,
89        anonymous_parameters,
90        array_into_iter,
91        asm_sub_register,
92        bad_asm_style,
93        bare_trait_objects,
94        box_pointers,
95        break_with_label_and_loop,
96        byte_slice_in_packed_struct_with_derive,
97        clashing_extern_declarations,
98        coherence_leak_check,
99        confusable_idents,
100        const_evaluatable_unchecked,
101        const_item_mutation,
102        dead_code,
103        deprecated,
104        deprecated_in_future,
105        deprecated_where_clause_location,
106        deref_into_dyn_supertrait,
107        deref_nullptr,
108        drop_bounds,
109        duplicate_macro_attributes,
110        dyn_drop,
111        elided_lifetimes_in_paths,
112        ellipsis_inclusive_range_patterns,
113        explicit_outlives_requirements,
114        exported_private_dependencies,
115        forbidden_lint_groups,
116        for_loops_over_fallibles,
117        function_item_references,
118        illegal_floating_point_literal_pattern,
119        improper_ctypes,
120        improper_ctypes_definitions,
121        incomplete_features,
122        indirect_structural_match,
123        inline_no_sanitize,
124        invalid_doc_attributes,
125        invalid_value,
126        irrefutable_let_patterns,
127        keyword_idents,
128        large_assignments,
129        late_bound_lifetime_arguments,
130        legacy_derive_helpers,
131        let_underscore_drop,
132        macro_use_extern_crate,
133        map_unit_fn,
134        meta_variable_misuse,
135        missing_abi,
136        missing_copy_implementations,
137        missing_debug_implementations,
138        missing_docs,
139        mixed_script_confusables,
140        named_arguments_used_positionally,
141        no_mangle_generic_items,
142        non_ascii_idents,
143        non_camel_case_types,
144        non_fmt_panics,
145        non_shorthand_field_patterns,
146        non_snake_case,
147        nontrivial_structural_match,
148        non_upper_case_globals,
149        noop_method_call,
150        opaque_hidden_inferred_bound,
151        overlapping_range_endpoints,
152        path_statements,
153        pointer_structural_match,
154        private_in_public,
155        redundant_semicolons,
156        renamed_and_removed_lints,
157        repr_transparent_external_private_fields,
158        rust_2021_incompatible_closure_captures,
159        rust_2021_incompatible_or_patterns,
160        rust_2021_prefixes_incompatible_syntax,
161        rust_2021_prelude_collisions,
162        semicolon_in_expressions_from_macros,
163        single_use_lifetimes,
164        special_module_name,
165        stable_features,
166        suspicious_auto_trait_impls,
167        temporary_cstring_as_ptr,
168        trivial_bounds,
169        trivial_casts,
170        trivial_numeric_casts,
171        type_alias_bounds,
172        tyvar_behind_raw_pointer,
173        uncommon_codepoints,
174        unconditional_recursion,
175        unexpected_cfgs,
176        ungated_async_fn_track_caller,
177        uninhabited_static,
178        unknown_lints,
179        unnameable_test_items,
180        unreachable_code,
181        unreachable_patterns,
182        unreachable_pub,
183        unsafe_code,
184        unsafe_op_in_unsafe_fn,
185        unstable_features,
186        unstable_name_collisions,
187        unstable_syntax_pre_expansion,
188        unsupported_calling_conventions,
189        unused_allocation,
190        unused_assignments,
191        unused_attributes,
192        unused_braces,
193        unused_comparisons,
194        unused_crate_dependencies,
195        unused_doc_comments,
196        unused_extern_crates,
197        unused_features,
198        unused_import_braces,
199        unused_imports,
200        unused_labels,
201        unused_lifetimes,
202        unused_macro_rules,
203        unused_macros,
204        unused_must_use,
205        unused_mut,
206        unused_parens,
207        unused_qualifications,
208        unused_results,
209        unused_tuple_struct_fields,
210        unused_unsafe,
211        unused_variables,
212        variant_size_differences,
213        where_clauses_object_safety,
214        while_true,
215    )
216)]
217// If nightly and unstable, allow `unstable_features`
218#![cfg_attr(all(msrv, feature = "unstable", nightly), allow(unstable_features))]
219// The unstable lints
220#![cfg_attr(
221    all(msrv, feature = "unstable", nightly),
222    deny(
223        ffi_unwind_calls,
224        fuzzy_provenance_casts,
225        lossy_provenance_casts,
226        multiple_supertrait_upcastable,
227        must_not_suspend,
228        non_exhaustive_omitted_patterns,
229        unfulfilled_lint_expectations,
230    )
231)]
232// If nightly and not unstable, deny `unstable_features`
233#![cfg_attr(all(msrv, not(feature = "unstable"), nightly), deny(unstable_features))]
234// nightly only lints
235#![cfg_attr(
236    all(msrv, nightly),
237    deny(
238        invalid_macro_export_arguments,
239        suspicious_double_ref_op,
240        undefined_naked_function_abi,
241    )
242)]
243// nightly or beta only lints
244#![cfg_attr(all(msrv, any(beta, nightly)), deny(ambiguous_glob_reexports))]
245// beta only lints
246// #![cfg_attr( all(msrv, beta), deny())]
247// beta or stable only lints
248// #![cfg_attr(all(msrv, any(beta, stable)), deny())]
249// stable only lints
250// #![cfg_attr(all(msrv, stable), deny())]
251// clippy lints
252#![cfg_attr(msrv, deny(clippy::all, clippy::pedantic))]
253// #![cfg_attr(msrv, allow())]
254// rustdoc lints
255#![cfg_attr(
256    msrv,
257    deny(
258        rustdoc::bare_urls,
259        rustdoc::broken_intra_doc_links,
260        rustdoc::invalid_codeblock_attributes,
261        rustdoc::invalid_html_tags,
262        rustdoc::missing_crate_level_docs,
263        rustdoc::private_doc_tests,
264        rustdoc::private_intra_doc_links,
265    )
266)]
267#![cfg_attr(
268    all(msrv, feature = "unstable", nightly),
269    deny(rustdoc::missing_doc_code_examples)
270)]
271
272#[cfg(all(feature = "arbitrary", not(feature = "fuzz")))]
273use arbitrary as _;
274mod base62;
275mod error;
276mod gf256;
277mod shamir;
278mod utils;
279
280pub use shamir::gen_shares;
281pub use shamir::unlock;
282pub use shamir::SsssConfig;
283pub use utils::remove_random_entry;