Preliminary implementation of deterministic secret sharing

#32
This commit is contained in:
Romain Ruetschi
2018-02-11 22:17:07 +01:00
committed by GitHub
parent d857157efd
commit 40f6190a9b
93 changed files with 6075 additions and 1573 deletions

View File

@ -9,3 +9,7 @@ rust:
matrix:
allow_failures:
- rust: nightly
script:
- cargo build --verbose --all-features
- cargo test --verbose --all-features

359
Cargo.lock generated
View File

@ -1,12 +1,18 @@
[root]
name = "rusty_secrets"
version = "0.0.3"
[[package]]
name = "aho-corasick"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"merkle_sigs 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"protobuf 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
"ring 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "base64"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
@ -14,189 +20,332 @@ name = "bitflags"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "byteorder"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "cc"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "coco"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"either 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"scopeguard 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
"either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "conv"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"custom_derive 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "custom_derive"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "either"
version = "1.1.0"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "futures"
version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "gcc"
version = "0.3.51"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "lamport_sigs"
version = "0.3.0"
name = "env_logger"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rand 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
"ring 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "lazy_static"
version = "0.2.8"
name = "error-chain"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libc"
version = "0.2.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "magenta"
version = "0.1.1"
name = "flate2"
version = "0.2.20"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"conv 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"magenta-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
"miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "magenta-sys"
version = "0.1.1"
name = "fuchsia-zircon"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"fuchsia-zircon-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "fuchsia-zircon-sys"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "merkle"
version = "1.3.0"
name = "gcc"
version = "0.3.54"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "itertools"
version = "0.7.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"protobuf 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ring 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "kernel32-sys"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "lamport_sigs"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
"ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "lazy_static"
version = "0.2.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libc"
version = "0.2.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "log"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "memchr"
version = "0.1.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "merkle"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"protobuf 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "merkle_sigs"
version = "1.2.1"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"lamport_sigs 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"merkle 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ring 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"lamport_sigs 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"merkle 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "miniz-sys"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "num_cpus"
version = "1.6.2"
version = "1.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "protobuf"
version = "1.4.1"
version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rand"
version = "0.3.16"
name = "quickcheck"
version = "0.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
"magenta 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rand"
version = "0.3.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"fuchsia-zircon 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rayon"
version = "0.7.1"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rayon-core 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rayon-core 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rayon-core"
version = "1.2.1"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"coco 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "regex"
version = "0.1.80"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)",
"memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)",
"regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
"thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
"utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "regex-syntax"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "ring"
version = "0.11.0"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
"rayon 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"untrusted 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
"rayon 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
"untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rustc-serialize"
version = "0.3.24"
name = "rusty_secrets"
version = "0.0.3"
dependencies = [
"base64 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"flate2 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)",
"itertools 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
"merkle_sigs 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"protobuf 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"quickcheck 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)",
"ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "safemem"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "scopeguard"
version = "0.3.2"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "thread-id"
version = "2.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "thread_local"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "untrusted"
version = "0.5.0"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "utf8-ranges"
version = "0.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi-build"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum aho-corasick 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ca972c2ea5f742bfce5687b9aef75506a764f61d37f8f649047846a9686ddb66"
"checksum base64 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "229d032f1a99302697f10b27167ae6d03d49d032e6a8e2550e8d3fc13356d2b4"
"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
"checksum byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "652805b7e73fada9d85e9a6682a4abd490cb52d96aeecc12e33a0de34dfd0d23"
"checksum cc 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a9b13a57efd6b30ecd6598ebdb302cca617930b5470647570468a65d12ef9719"
"checksum coco 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c06169f5beb7e31c7c67ebf5540b8b472d23e3eade3b2ec7d1f5b504a85f91bd"
"checksum conv 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "78ff10625fd0ac447827aa30ea8b861fead473bb60aeb73af6c1c58caf0d1299"
"checksum custom_derive 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "ef8ae57c4978a2acd8b869ce6b9ca1dfe817bff704c220209fdef2c0b75a01b9"
"checksum either 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18785c1ba806c258137c937e44ada9ee7e69a37e3c72077542cd2f069d78562a"
"checksum futures 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "4b63a4792d4f8f686defe3b39b92127fea6344de5d38202b2ee5a11bbbf29d6a"
"checksum gcc 0.3.51 (registry+https://github.com/rust-lang/crates.io-index)" = "120d07f202dcc3f72859422563522b66fe6463a4c513df062874daad05f85f0a"
"checksum lamport_sigs 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2169eee511fb4b2af1d9581f74d9503b5a86e4dbfa52ca1f5ee0d1193bf1d913"
"checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf"
"checksum libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)" = "8a014d9226c2cc402676fbe9ea2e15dd5222cd1dd57f576b5b283178c944a264"
"checksum magenta 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4bf0336886480e671965f794bc9b6fce88503563013d1bfb7a502c81fe3ac527"
"checksum magenta-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40d014c7011ac470ae28e2f76a02bfea4a8480f73e701353b49ad7a8d75f4699"
"checksum merkle 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "204bbb6953e7cc6c2cec3f63e108f0d61311a3dab33d33582b1f6f4d4ae6f992"
"checksum merkle_sigs 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b446a57d9a060a9db764b6c6bd44bf79e46c512733ed9b6c23206e74394d3255"
"checksum num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aec53c34f2d0247c5ca5d32cca1478762f301740468ee9ee6dcb7a0dd7a0c584"
"checksum protobuf 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "568a15e4d572d9a5e63ae3a55f84328c984842887db179b40b4cc6a608bac6a4"
"checksum rand 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)" = "eb250fd207a4729c976794d03db689c9be1d634ab5a1c9da9492a13d8fecbcdf"
"checksum rayon 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a77c51c07654ddd93f6cb543c7a849863b03abc7e82591afda6dc8ad4ac3ac4a"
"checksum rayon-core 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7febc28567082c345f10cddc3612c6ea020fc3297a1977d472cf9fdb73e6e493"
"checksum ring 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2a6dc7fc06a05e6de183c5b97058582e9da2de0c136eafe49609769c507724"
"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
"checksum scopeguard 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c79eb2c3ac4bc2507cda80e7f3ac5b88bd8eae4c0914d5663e6a8933994be918"
"checksum untrusted 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6b65243989ef6aacd9c0d6bd2b822765c3361d8ed352185a6f3a41f3a718c673"
"checksum either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "740178ddf48b1a9e878e6d6509a1442a2d42fd2928aae8e7a6f8a36fb01981b3"
"checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f"
"checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3"
"checksum flate2 0.2.20 (registry+https://github.com/rust-lang/crates.io-index)" = "e6234dd4468ae5d1e2dbb06fe2b058696fdc50a339c68a393aefbf00bc81e423"
"checksum fuchsia-zircon 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f6c0581a4e363262e52b87f59ee2afe3415361c6ec35e665924eb08afe8ff159"
"checksum fuchsia-zircon-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "43f3795b4bae048dc6123a6b972cadde2e676f9ded08aef6bb77f5f157684a82"
"checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb"
"checksum itertools 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)" = "99f3f75d7cf195a7eedb0611efe8684b55c6c7264afe3d8bc00b704f061c0fdf"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
"checksum lamport_sigs 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5dff26ae558be16afda65815c847447c81eede19c639982e49e33bd15973d857"
"checksum lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)" = "76f033c7ad61445c5b347c7382dd1237847eb1bce590fe50365dcb33d546be73"
"checksum libc 0.2.33 (registry+https://github.com/rust-lang/crates.io-index)" = "5ba3df4dcb460b9dfbd070d41c94c19209620c191b0340b929ce748a2bcd42d2"
"checksum log 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "880f77541efa6e5cc74e76910c9884d9859683118839d6a1dc3b11e63512565b"
"checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20"
"checksum merkle 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a6311caa1c5c71548021dfc5f6113fca485d453185fdc44da92bafe266f6a5fe"
"checksum merkle_sigs 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "94367864019d3b781c28c67d0a7057da0df498525982869c47ecfd73ece29f26"
"checksum miniz-sys 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "609ce024854aeb19a0ef7567d348aaa5a746b32fb72e336df7fcc16869d7e2b4"
"checksum num_cpus 1.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "514f0d73e64be53ff320680ca671b64fe3fb91da01e1ae2ddc99eb51d453b20d"
"checksum protobuf 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "99c7a6694a7896f7c039bc20a6947b83781b019d7d40df77ae069cd2a432e4a7"
"checksum quickcheck 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "02c2411d418cea2364325b18a205664f9ef8252e06b2e911db97c0b0d98b1406"
"checksum rand 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)" = "6475140dfd8655aeb72e1fd4b7a1cc1c202be65d71669476e392fe62532b9edd"
"checksum rayon 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b614fe08b6665cb9a231d07ac1364b0ef3cb3698f1239ee0c4c3a88a524f54c8"
"checksum rayon-core 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e64b609139d83da75902f88fd6c01820046840a18471e4dfcd5ac7c0f46bea53"
"checksum regex 0.1.80 (registry+https://github.com/rust-lang/crates.io-index)" = "4fd4ace6a8cf7860714a2c2280d6c1f7e6a413486c13298bbc86fd3da019402f"
"checksum regex-syntax 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "f9ec002c35e86791825ed294b50008eea9ddfc8def4420124fbc6b08db834957"
"checksum ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6f7d28b30a72c01b458428e0ae988d4149c20d902346902be881e3edc4bb325c"
"checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f"
"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
"checksum thread-id 2.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "a9539db560102d1cef46b8b78ce737ff0bb64e7e18d35b2a5688f7d097d0ff03"
"checksum thread_local 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8576dbbfcaef9641452d5cf0df9b0e7eeab7694956dd33bb61515fb8f18cfdd5"
"checksum untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f392d7819dbe58833e26872f5f6f0d68b7bbbe90fc3667e98731c4a15ad9a7ae"
"checksum utf8-ranges 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "a1ca13c08c41c9c3e04224ed9ff80461d97e121589ff27c753a16cb10830ae0f"
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"

View File

@ -8,10 +8,38 @@ license = "BSD-3-Clause"
readme = "README.md"
build = "build.rs"
[dependencies]
rustc-serialize = "^0.3.18"
rand = "^0.3.14"
ring = "^0.11.0"
merkle_sigs = "^1.2.1"
protobuf = "^1.2.0"
[features]
default = []
dss = []
[dependencies]
base64 = "0.9.0"
rand = "^0.3"
ring = "^0.12"
merkle_sigs = "^1.4"
protobuf = "^1.4"
[dependencies.error-chain]
version = "0.11.0"
default-features = false
[dev-dependencies]
itertools = "^0.7"
quickcheck = "^0.4"
flate2 = "^0.2"
[profile.bench]
opt-level = 3
debug = false
rpath = false
lto = true
debug-assertions = false
codegen-units = 1
[profile.release]
opt-level = 3
debug = false
rpath = false
lto = true
debug-assertions = false
codegen-units = 1

View File

@ -0,0 +1 @@
Privacy isn't about something to hide. Privacy is about something to protect. That's who you are. That's what you believe in, that's who you want to become. Privacy is the right to the self. Privacy is what gives you the ability to share with the world who you are, on your own terms, for them to understand what you're trying to be. And to protect for yourself the parts of you that you're not sure about, that you're still experimenting with. If we don't have privacy, what we're losing is the ability to make mistakes. We're losing the ability to be ourselves. Privacy is the fountainhead of all other rights. Freedom of speech doesn't have a lot of meaning if you can't have a quiet space. . . . to decide what it is that you actually wanna say. Freedom of religion doesn't mean that if you can't figure out what you actually believe without being influenced by the criticisms and sort of outside direction and peer pressure of others. And it goes on and on and on. But privacy is baked into our language, our core concepts of government and self in every way . . . without privacy, you won't have anything for yourself. So when people say that to me, I say back arguing that you don't have privacy because you have nothing to hide is like arguing that you don't care about free speech because you have nothing to say.

5
benches/shared.rs Normal file
View File

@ -0,0 +1,5 @@
#![cfg(test)]
pub fn secret_1kb() -> &'static [u8] {
include_bytes!("resources/1KB.txt")
}

51
benches/ss1.rs Normal file
View File

@ -0,0 +1,51 @@
#![cfg(test)]
#![feature(test)]
extern crate rusty_secrets;
extern crate test;
mod shared;
mod ss1 {
use rusty_secrets::dss::ss1;
use test::{black_box, Bencher};
use shared;
macro_rules! bench_generate {
($name:ident, $k:expr, $n:expr, $secret:ident) => (
#[bench]
fn $name(b: &mut Bencher) {
let secret = shared::$secret();
b.iter(move || {
let shares = ss1::split_secret($k, $n, &secret, ss1::Reproducibility::reproducible(), &None).unwrap();
black_box(shares);
});
}
)
}
macro_rules! bench_recover {
($name:ident, $k:expr, $n:expr, $secret:ident) => (
#[bench]
fn $name(b: &mut Bencher) {
let secret = shared::$secret();
let all_shares = ss1::split_secret($k, $n, &secret, ss1::Reproducibility::reproducible(), &None).unwrap();
let shares = &all_shares.into_iter().take($k).collect::<Vec<_>>().clone();
b.iter(|| {
let result = ss1::recover_secret(&shares.to_vec()).unwrap();
black_box(result);
});
}
)
}
bench_generate!(generate_1kb_3_5, 3, 5, secret_1kb);
bench_recover!(recover_1kb_3_5, 3, 5, secret_1kb);
bench_generate!(generate_1kb_10_25, 10, 25, secret_1kb);
bench_recover!(recover_1kb_10_25, 10, 25, secret_1kb);
}

57
benches/sss.rs Normal file
View File

@ -0,0 +1,57 @@
#![cfg(test)]
#![feature(test)]
extern crate rusty_secrets;
extern crate test;
mod shared;
mod sss {
use test::{black_box, Bencher};
use rusty_secrets::sss;
use shared;
macro_rules! bench_generate {
($name:ident, $k:expr, $n:expr, $secret:ident, $signed:expr) => (
#[bench]
fn $name(b: &mut Bencher) {
let secret = shared::$secret();
b.iter(move || {
let shares = sss::split_secret($k, $n, secret, $signed).unwrap();
black_box(shares);
});
}
)
}
macro_rules! bench_recover {
($name:ident, $k:expr, $n:expr, $secret:ident, $signed:expr) => (
#[bench]
fn $name(b: &mut Bencher) {
let secret = shared::$secret();
let all_shares = sss::split_secret($k, $n, &secret, $signed).unwrap();
let shares = all_shares.into_iter().take($k).collect::<Vec<_>>();
b.iter(|| {
let result = sss::recover_secret(&shares, $signed).unwrap();
black_box(result);
});
}
)
}
bench_generate!(generate_1kb_3_5, 3, 5, secret_1kb, false);
bench_recover!(recover_1kb_3_5, 3, 5, secret_1kb, false);
bench_generate!(generate_1kb_3_5_signed, 3, 5, secret_1kb, true);
bench_recover!(recover_1kb_3_5_signed, 3, 5, secret_1kb, true);
bench_generate!(generate_1kb_10_25, 10, 25, secret_1kb, false);
bench_recover!(recover_1kb_10_25, 10, 25, secret_1kb, false);
bench_generate!(generate_1kb_10_25_signed, 10, 25, secret_1kb, true);
bench_recover!(recover_1kb_10_25_signed, 10, 25, secret_1kb, true);
}

51
benches/thss.rs Normal file
View File

@ -0,0 +1,51 @@
#![cfg(test)]
#![feature(test)]
extern crate rusty_secrets;
extern crate test;
mod shared;
mod thss {
use rusty_secrets::dss::thss;
use test::{black_box, Bencher};
use shared;
macro_rules! bench_generate {
($name:ident, $k:expr, $n:expr, $secret:ident) => (
#[bench]
fn $name(b: &mut Bencher) {
let secret = shared::$secret();
b.iter(move || {
let shares = thss::split_secret($k, $n, &secret, &None).unwrap();
black_box(shares);
});
}
)
}
macro_rules! bench_recover {
($name:ident, $k:expr, $n:expr, $secret:ident) => (
#[bench]
fn $name(b: &mut Bencher) {
let secret = shared::$secret();
let all_shares = thss::split_secret($k, $n, &secret, &None).unwrap();
let shares = &all_shares.into_iter().take($k).collect::<Vec<_>>().clone();
b.iter(|| {
let result = thss::recover_secret(&shares.to_vec()).unwrap();
black_box(result);
});
}
)
}
bench_generate!(generate_1kb_3_5, 3, 5, secret_1kb);
bench_recover!(recover_1kb_3_5, 3, 5, secret_1kb);
bench_generate!(generate_1kb_10_25, 10, 25, secret_1kb);
bench_recover!(recover_1kb_10_25, 10, 25, secret_1kb);
}

View File

@ -0,0 +1,57 @@
#![cfg(test)]
#![feature(test)]
extern crate rusty_secrets;
extern crate test;
mod shared;
mod wrapped_secrets {
use test::{black_box, Bencher};
use rusty_secrets::wrapped_secrets;
use shared;
macro_rules! bench_generate {
($name:ident, $k:expr, $n:expr, $secret:ident, $signed:expr) => (
#[bench]
fn $name(b: &mut Bencher) {
let secret = shared::$secret();
b.iter(move || {
let shares = wrapped_secrets::split_secret($k, $n, secret, None, $signed).unwrap();
black_box(shares);
});
}
)
}
macro_rules! bench_recover {
($name:ident, $k:expr, $n:expr, $secret:ident, $signed:expr) => (
#[bench]
fn $name(b: &mut Bencher) {
let secret = shared::$secret();
let all_shares = wrapped_secrets::split_secret($k, $n, &secret, None, $signed).unwrap();
let shares = all_shares.into_iter().take($k).collect::<Vec<_>>();
b.iter(|| {
let result = wrapped_secrets::recover_secret(&shares, $signed).unwrap();
black_box(result);
});
}
)
}
bench_generate!(generate_1kb_3_5, 3, 5, secret_1kb, false);
bench_recover!(recover_1kb_3_5, 3, 5, secret_1kb, false);
bench_generate!(generate_1kb_3_5_signed, 3, 5, secret_1kb, true);
bench_recover!(recover_1kb_3_5_signed, 3, 5, secret_1kb, true);
bench_generate!(generate_1kb_10_25, 10, 25, secret_1kb, false);
bench_recover!(recover_1kb_10_25, 10, 25, secret_1kb, false);
bench_generate!(generate_1kb_10_25_signed, 10, 25, secret_1kb, true);
bench_recover!(recover_1kb_10_25_signed, 10, 25, secret_1kb, true);
}

View File

@ -17,38 +17,38 @@ fn mask(bit: u8) -> u8 {
/// of the polynomial division with POLY as divisor
#[inline]
fn xtimes(poly: u8) -> u8 {
(poly << 1) ^ (mask(poly >> 7) & POLY)
(poly << 1) ^ (mask(poly >> 7) & POLY)
}
struct Tables {
exp: [u8; 256],
log: [u8; 256],
exp: [u8; 256],
log: [u8; 256],
}
fn generate_tables(mut file: &File) {
let mut tabs = Tables {
exp: [0; 256],
log: [0; 256],
exp: [0; 256],
log: [0; 256],
};
let mut tmp = 1;
for power in 0..255usize {
tabs.exp[power] = tmp;
tabs.log[tmp as usize] = power as u8;
tmp = xtimes(tmp);
tabs.exp[power] = tmp;
tabs.log[tmp as usize] = power as u8;
tmp = xtimes(tmp);
}
tabs.exp[255] = 1;
match write!(file, "{}", tabs) {
Ok(()) => {}
Err(_) => panic!("Could not format the table. Aborting build.")
Err(_) => panic!("Could not format the table. Aborting build."),
};
}
fn farray(array: [u8; 256], f: &mut fmt::Formatter) -> fmt::Result {
for (index, value) in array.into_iter().enumerate() {
try!(write!(f, "{}", value));
if index != array.len()-1 {
if index != array.len() - 1 {
try!(write!(f, ","));
}
}
@ -75,12 +75,15 @@ fn main() {
let mut f = File::create(&dest).unwrap();
write!(f, "pub struct Tables {{
pub exp: [u8; 256],
pub log: [u8; 256]
}}
pub static TABLES: Tables = ");
write!(
f,
"pub struct Tables {{ \
pub exp: [u8; 256], \
pub log: [u8; 256] \
}} \
\
pub static TABLES: Tables = "
);
generate_tables(&f);
}

4
fuzz/.gitignore vendored Normal file
View File

@ -0,0 +1,4 @@
target
corpus
artifacts

304
fuzz/Cargo.lock generated Normal file
View File

@ -0,0 +1,304 @@
[root]
name = "rusty_secrets-fuzz"
version = "0.0.1"
dependencies = [
"arbitrary 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"libfuzzer-sys 0.1.0 (git+https://github.com/rust-fuzz/libfuzzer-sys.git)",
"rusty_secrets 0.0.3",
]
[[package]]
name = "arbitrary"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "bitflags"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "block-buffer"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"generic-array 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "byte-tools"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "coco"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"either 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"scopeguard 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "conv"
version = "0.3.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"custom_derive 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "custom_derive"
version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "digest"
version = "0.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"generic-array 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "either"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "error-chain"
version = "0.11.0-rc.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "futures"
version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "gcc"
version = "0.3.53"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "generic-array"
version = "0.8.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"nodrop 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
"typenum 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "lamport_sigs"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rand 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
"ring 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "lazy_static"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libc"
version = "0.2.29"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "libfuzzer-sys"
version = "0.1.0"
source = "git+https://github.com/rust-fuzz/libfuzzer-sys.git#67f73995f183099b2c8a736bc95b07d8b5903afe"
dependencies = [
"arbitrary 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"gcc 0.3.53 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "magenta"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"conv 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
"magenta-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "magenta-sys"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "merkle"
version = "1.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"protobuf 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"ring 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "merkle_sigs"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"lamport_sigs 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"merkle 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"ring 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "nodrop"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"odds 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "num_cpus"
version = "1.6.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "odds"
version = "0.2.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "protobuf"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rand"
version = "0.3.16"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
"magenta 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rayon"
version = "0.7.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"rayon-core 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rayon-core"
version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"coco 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
"num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "ring"
version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"gcc 0.3.53 (registry+https://github.com/rust-lang/crates.io-index)",
"lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
"libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)",
"rayon 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)",
"untrusted 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rustc-serialize"
version = "0.3.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rusty_secrets"
version = "0.0.3"
dependencies = [
"digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"error-chain 0.11.0-rc.2 (registry+https://github.com/rust-lang/crates.io-index)",
"merkle_sigs 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"protobuf 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)",
"rand 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)",
"ring 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)",
"sha3 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "scopeguard"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "sha3"
version = "0.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"block-buffer 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)",
"generic-array 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "typenum"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "untrusted"
version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum arbitrary 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "baa5f4eaa3a3603a0d83861560ab55dfa6c8dd094b05604e5d006b41ffaeb1d3"
"checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d"
"checksum block-buffer 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1339a1042f5d9f295737ad4d9a6ab6bf81c84a933dba110b9200cd6d1448b814"
"checksum byte-tools 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "560c32574a12a89ecd91f5e742165893f86e3ab98d21f8ea548658eb9eef5f40"
"checksum coco 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c06169f5beb7e31c7c67ebf5540b8b472d23e3eade3b2ec7d1f5b504a85f91bd"
"checksum conv 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "78ff10625fd0ac447827aa30ea8b861fead473bb60aeb73af6c1c58caf0d1299"
"checksum custom_derive 0.1.7 (registry+https://github.com/rust-lang/crates.io-index)" = "ef8ae57c4978a2acd8b869ce6b9ca1dfe817bff704c220209fdef2c0b75a01b9"
"checksum digest 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e5b29bf156f3f4b3c4f610a25ff69370616ae6e0657d416de22645483e72af0a"
"checksum either 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18785c1ba806c258137c937e44ada9ee7e69a37e3c72077542cd2f069d78562a"
"checksum error-chain 0.11.0-rc.2 (registry+https://github.com/rust-lang/crates.io-index)" = "38d3a55d9a7a456748f2a3912c0941a5d9a68006eb15b3c3c9836b8420dc102d"
"checksum futures 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "4b63a4792d4f8f686defe3b39b92127fea6344de5d38202b2ee5a11bbbf29d6a"
"checksum gcc 0.3.53 (registry+https://github.com/rust-lang/crates.io-index)" = "e8310f7e9c890398b0e80e301c4f474e9918d2b27fca8f48486ca775fa9ffc5a"
"checksum generic-array 0.8.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6181b378c58e5aacf4d3e17836737465cb2857750b53f6b46672a3509f2a8d9d"
"checksum lamport_sigs 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2169eee511fb4b2af1d9581f74d9503b5a86e4dbfa52ca1f5ee0d1193bf1d913"
"checksum lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "3b37545ab726dd833ec6420aaba8231c5b320814b9029ad585555d2a03e94fbf"
"checksum libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)" = "8a014d9226c2cc402676fbe9ea2e15dd5222cd1dd57f576b5b283178c944a264"
"checksum libfuzzer-sys 0.1.0 (git+https://github.com/rust-fuzz/libfuzzer-sys.git)" = "<none>"
"checksum magenta 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "4bf0336886480e671965f794bc9b6fce88503563013d1bfb7a502c81fe3ac527"
"checksum magenta-sys 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "40d014c7011ac470ae28e2f76a02bfea4a8480f73e701353b49ad7a8d75f4699"
"checksum merkle 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "204bbb6953e7cc6c2cec3f63e108f0d61311a3dab33d33582b1f6f4d4ae6f992"
"checksum merkle_sigs 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b446a57d9a060a9db764b6c6bd44bf79e46c512733ed9b6c23206e74394d3255"
"checksum nodrop 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "52cd74cd09beba596430cc6e3091b74007169a56246e1262f0ba451ea95117b2"
"checksum num_cpus 1.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "aec53c34f2d0247c5ca5d32cca1478762f301740468ee9ee6dcb7a0dd7a0c584"
"checksum odds 0.2.25 (registry+https://github.com/rust-lang/crates.io-index)" = "c3df9b730298cea3a1c3faa90b7e2f9df3a9c400d0936d6015e6165734eefcba"
"checksum protobuf 1.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "568a15e4d572d9a5e63ae3a55f84328c984842887db179b40b4cc6a608bac6a4"
"checksum rand 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)" = "eb250fd207a4729c976794d03db689c9be1d634ab5a1c9da9492a13d8fecbcdf"
"checksum rayon 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)" = "a77c51c07654ddd93f6cb543c7a849863b03abc7e82591afda6dc8ad4ac3ac4a"
"checksum rayon-core 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7febc28567082c345f10cddc3612c6ea020fc3297a1977d472cf9fdb73e6e493"
"checksum ring 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1f2a6dc7fc06a05e6de183c5b97058582e9da2de0c136eafe49609769c507724"
"checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda"
"checksum scopeguard 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c79eb2c3ac4bc2507cda80e7f3ac5b88bd8eae4c0914d5663e6a8933994be918"
"checksum sha3 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "26405905b6a56a94c60109cfda62610507ac14a65be531f5767dec5c5a8dd6a0"
"checksum typenum 1.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "13a99dc6780ef33c78780b826cf9d2a78840b72cae9474de4bcaf9051e60ebbd"
"checksum untrusted 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "6b65243989ef6aacd9c0d6bd2b822765c3361d8ed352185a6f3a41f3a718c673"

37
fuzz/Cargo.toml Normal file
View File

@ -0,0 +1,37 @@
[package]
name = "rusty_secrets-fuzz"
version = "0.0.1"
authors = ["Automatically generated"]
publish = false
[package.metadata]
cargo-fuzz = true
[dependencies]
arbitrary = "0.1.0"
[dependencies.rusty_secrets]
path = ".."
[dependencies.libfuzzer-sys]
git = "https://github.com/rust-fuzz/libfuzzer-sys.git"
# Prevent this from interfering with workspaces
[workspace]
members = ["."]
[[bin]]
name = "ss1_1"
path = "fuzz_targets/ss1_1.rs"
[[bin]]
name = "thss_1"
path = "fuzz_targets/thss_1.rs"
[[bin]]
name = "sss_1"
path = "fuzz_targets/sss_1.rs"
[[bin]]
name = "wrapped_secrets_1"
path = "fuzz_targets/wrapped_secrets_1.rs"

View File

@ -0,0 +1,24 @@
#![no_main]
#[macro_use]
extern crate libfuzzer_sys;
extern crate rusty_secrets;
extern crate arbitrary;
use rusty_secrets::dss::ss1::*;
use arbitrary::{RingBuffer, Unstructured};
fuzz_target!(|data: &[u8]| {
// ---
if let Ok(mut buffer) = RingBuffer::new(data, data.len()) {
let mut kn = vec![0; 2];
buffer.fill_buffer(&mut kn).unwrap();
let k = kn[0];
let n = kn[1];
split_secret(k, n, &data, Reproducibility::reproducible(), &None)
.and_then(|ss| recover_secret(&ss))
.map(|_| ())
.unwrap_or(())
}
});

View File

@ -0,0 +1,25 @@
#![no_main]
extern crate arbitrary;
#[macro_use]
extern crate libfuzzer_sys;
extern crate rusty_secrets;
use rusty_secrets::sss;
use arbitrary::{RingBuffer, Unstructured};
fuzz_target!(|data: &[u8]| {
// ---
if let Ok(mut buffer) = RingBuffer::new(data, data.len()) {
let mut kn = vec![0; 2];
buffer.fill_buffer(&mut kn).unwrap();
let k = kn[0];
let n = kn[1];
sss::split_secret(k, n, &data, false)
.map_err(|err| err.into())
.and_then(|ss| sss::recover_secret(&ss, false))
.map(|_| ())
.unwrap_or(())
}
});

View File

@ -0,0 +1,24 @@
#![no_main]
#[macro_use]
extern crate libfuzzer_sys;
extern crate rusty_secrets;
extern crate arbitrary;
use rusty_secrets::dss::thss::*;
use arbitrary::{RingBuffer, Unstructured};
fuzz_target!(|data: &[u8]| {
// ---
if let Ok(mut buffer) = RingBuffer::new(data, data.len()) {
let mut kn = vec![0; 2];
buffer.fill_buffer(&mut kn).unwrap();
let k = kn[0];
let n = kn[1];
split_secret(k, n, &data, &None)
.and_then(|ss| recover_secret(&ss))
.map(|_| ())
.unwrap_or(())
}
});

View File

@ -0,0 +1,25 @@
#![no_main]
extern crate arbitrary;
#[macro_use]
extern crate libfuzzer_sys;
extern crate rusty_secrets;
use rusty_secrets::wrapped_secrets;
use arbitrary::{RingBuffer, Unstructured};
fuzz_target!(|data: &[u8]| {
// ---
if let Ok(mut buffer) = RingBuffer::new(data, data.len()) {
let mut kn = vec![0; 2];
buffer.fill_buffer(&mut kn).unwrap();
let k = kn[0];
let n = kn[1];
wrapped_secrets::split_secret(k, n, &data, false)
.map_err(|err| err.into())
.and_then(|ss| wrapped_secrets::recover_secret(&ss, false))
.map(|_| ())
.unwrap_or(())
}
});

1
protobuf/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
_out/

42
protobuf/Makefile Normal file
View File

@ -0,0 +1,42 @@
SHELL = bash
PROTOC := protoc
DEST_DIR := ../src/proto
BASE_PROTOS := $(wildcard *.proto)
BASE_RUSTS := $(addprefix $(DEST_DIR)/, $(BASE_PROTOS:.proto=.rs))
DSS_PROTOS := $(wildcard dss/*.proto)
DSS_RUSTS := $(addprefix $(DEST_DIR)/, $(DSS_PROTOS:.proto=.rs))
WRAPPED_PROTOS := $(wildcard wrapped/*.proto)
WRAPPED_RUSTS := $(addprefix $(DEST_DIR)/, $(WRAPPED_PROTOS:.proto=.rs))
OUT_DIR := _out
.PHONY: all base wrapped dss clean
all: base wrapped dss
base: $(BASE_RUSTS)
wrapped: $(WRAPPED_RUSTS)
dss: $(DSS_RUSTS)
$(DEST_DIR)/%.rs: %.proto
@echo -n "Processing '$<'..."
@$(RM) -r $(OUT_DIR)
@mkdir -p $(OUT_DIR)
@$(PROTOC) --rust_out $(OUT_DIR) $<
@echo " Done."
@echo -n "Moving generated file to '$(dir $@)'..."
@mkdir -p $(dir $@)
@mv $(OUT_DIR)/*.rs $(dir $@)
@echo " Done."
clean:
$(RM) $(BASE_RUSTS)
$(RM) $(WRAPPED_RUSTS)
$(RM) $(DSS_RUSTS)

View File

@ -1,11 +0,0 @@
syntax = "proto3";
enum RustySecretsVersions {
INITIAL_RELEASE = 0;
}
message RustySecret {
RustySecretsVersions version = 1;
bytes secret = 2;
string mime_type = 3;
}

View File

@ -0,0 +1,7 @@
syntax = "proto3";
package dss;
message MetaDataProto {
map<string, string> tags = 1;
}

10
protobuf/dss/secret.proto Normal file
View File

@ -0,0 +1,10 @@
syntax = "proto3";
import "version.proto";
import "dss/metadata.proto";
message SecretProto {
VersionProto version = 1;
bytes secret = 2;
dss.MetaDataProto meta_data = 3;
}

14
protobuf/dss/share.proto Normal file
View File

@ -0,0 +1,14 @@
syntax = "proto3";
package dss;
import "dss/metadata.proto";
message ShareProto {
uint32 id = 1;
uint32 threshold = 2;
uint32 shares_count = 3;
bytes data = 4;
bytes hash = 5;
dss.MetaDataProto meta_data = 6;
}

6
protobuf/version.proto Normal file
View File

@ -0,0 +1,6 @@
syntax = "proto3";
enum VersionProto {
INITIAL_RELEASE = 0;
}

View File

@ -0,0 +1,11 @@
syntax = "proto3";
package wrapped;
import "version.proto";
message SecretProto {
VersionProto version = 1;
bytes secret = 2;
string mime_type = 3;
}

View File

@ -1,6 +1,8 @@
syntax = "proto3";
message ShareData {
package wrapped;
message ShareProto {
bytes shamir_data = 1;
repeated bytes signature = 2;
bytes proof = 3;

View File

@ -1,183 +0,0 @@
use std::convert;
use std::error::Error;
use std::fmt;
use std::io;
use std::num;
/// Error struct used for generating an `io::Error` from a generic description.
#[derive(Debug)]
pub struct RustyError {
descr: &'static str,
detail: Option<String>,
share_index: Option<u8>,
share_groups: Option<Vec<Vec<u8>>>
}
#[derive(Debug)]
pub enum RustyErrorTypes {
DuplicateShareNum(u8),
DuplicateShareData(u8),
EmptyShares,
IncompatibleSets(Vec<Vec<u8>>),
InvalidSignature(u8, String),
MissingShares(u8, usize),
MissingSignature(u8),
SecretDeserializationIssue,
ShareParsingError(u8, String)
}
impl RustyError {
/// Initializes a new error with a description and optional detail string.
fn new(descr: &'static str, detail: Option<String>, share_index: Option<u8>, share_groups: Option<Vec<Vec<u8>>>) -> RustyError {
RustyError {
descr: descr,
detail: detail,
share_index: share_index,
share_groups: share_groups
}
}
/// Returns a `RustyError` with a given `RustyErrorType`.
pub fn with_type(error_type: RustyErrorTypes) -> RustyError {
RustyError {
descr: RustyError::descr_for_type(&error_type),
detail: RustyError::detail_for_type(&error_type),
share_index: RustyError::share_num_for_type(&error_type),
share_groups: RustyError::share_groups_for_type(error_type),
}
}
/// Returns the index of the share that raised the error, if any.
pub fn share_index(&self) -> Option<u8> {
self.share_index
}
/// Returns the group of shares that were generated during the same secret share.
/// It can be used to provide a debug message to the user telling him what shares are incompatible.
pub fn share_groups(&self) -> Option<Vec<Vec<u8>>> {
self.share_groups.clone()
}
fn descr_for_type(error_type: &RustyErrorTypes) -> &'static str {
match *error_type {
RustyErrorTypes::EmptyShares => "No shares were provided.",
RustyErrorTypes::IncompatibleSets(_) => "The shares are incompatible with each other.",
RustyErrorTypes::InvalidSignature(_, _) => "The signature of this share is not valid.",
RustyErrorTypes::MissingShares(_, _) => "The number of shares provided is insufficient to recover the secret.",
RustyErrorTypes::MissingSignature(_) => "Signature is missing while shares are required to be signed.",
RustyErrorTypes::SecretDeserializationIssue => "An issue was encountered deserializing the secret.
Updating to the latest version of RustySecrets might help fix this.",
RustyErrorTypes::ShareParsingError(_, _) => "This share is incorrectly formatted.",
RustyErrorTypes::DuplicateShareNum(_) => "This share number has already been used by a previous share.",
RustyErrorTypes::DuplicateShareData(_) => "The data encoded in this share is the same as the one found in a previous share."
}
}
fn detail_for_type(error_type: &RustyErrorTypes) -> Option<String> {
match *error_type {
RustyErrorTypes::MissingShares(required, found) => Some(format!("{} shares are required to recover the secret,
found only {}.", required, found)),
RustyErrorTypes::ShareParsingError(_, ref description) => Some(description.clone()),
_ => None
}
}
fn share_groups_for_type(error_type: RustyErrorTypes) -> Option<Vec<Vec<u8>>>{
match error_type {
RustyErrorTypes::IncompatibleSets(groups) => Some(groups),
_ => None
}
}
fn share_num_for_type(error_type: &RustyErrorTypes) -> Option<u8> {
match *error_type {
RustyErrorTypes::InvalidSignature(share_num, _)
| RustyErrorTypes::MissingSignature(share_num)
| RustyErrorTypes::ShareParsingError(share_num, _)
| RustyErrorTypes::DuplicateShareNum(share_num)
| RustyErrorTypes::DuplicateShareData(share_num) => Some(share_num),
_ => None
}
}
}
impl fmt::Display for RustyError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self.detail {
None => write!(f, "{}", self.descr),
Some(ref detail) => write!(f, "{} ({})", self.descr, detail),
}
}
}
impl Error for RustyError {
fn description(&self) -> &str {
self.descr
}
fn cause(&self) -> Option<&Error> {
None
}
}
impl From<io::Error> for RustyError {
fn from(err: io::Error) -> RustyError {
let descr = err.description().to_owned();
RustyError::new("from io:Error", Some(descr), None, None)
}
}
impl From<RustyError> for io::Error {
fn from(me: RustyError) -> io::Error {
io::Error::new(io::ErrorKind::Other, me)
}
}
/// Returns an `io::Error` from description string and optional detail string.
/// Particularly useful in `Result` expressions.
pub fn other_io_err(descr: &'static str, detail: Option<String>,
share_num: Option<u8>, share_groups: Option<Vec<Vec<u8>>>) -> io::Error {
convert::From::from(RustyError::new(descr, detail, share_num, share_groups))
}
/// maps a `ParseIntError` to an `Error`
pub fn pie2error(p: num::ParseIntError) -> RustyError {
RustyError::new("Integer parsing error", Some(p.to_string()), None, None)
}
#[cfg(test)]
mod tests_custom_err {
use std::error;
use custom_error::RustyError;
#[test]
fn test_custom_error() {
let desc = "Boring error description";
let detail = "More of it";
let ewd = RustyError::new(desc, Some(detail.to_string()), None, None);
assert_eq!(error::Error::description(&ewd), desc);
match error::Error::cause(&ewd) {
Some(_) => assert!(false),
None => assert!(true),
}
let _formated_err = format!("{}", ewd);
let ewod = RustyError::new(desc, None, None, None);
let _formated_err = format!("{}", ewod);
}
}
#[cfg(test)]
mod tests_std_err {
use std::error::Error;
use custom_error::pie2error;
#[test]
fn test_parse_errors() {
let nan = "2a".to_string();
match nan.parse::<u8>().map_err(pie2error) {
Ok(_) => assert!(false),
Err(x) => assert_eq!("Integer parsing error", x.description()),
}
}
}

73
src/dss/format.rs Normal file
View File

@ -0,0 +1,73 @@
use std::error::Error;
use protobuf::{self, Message};
use base64;
use errors::*;
use proto::dss::ShareProto;
const BASE64_CONFIG: base64::Config = base64::STANDARD_NO_PAD;
pub(crate) fn format_share_protobuf(share: &ShareProto) -> String {
let bytes = share.write_to_bytes().unwrap();
let base64_data = base64::encode_config(&bytes, BASE64_CONFIG);
format!("{}-{}-{}", share.threshold, share.id, base64_data)
}
pub(crate) fn parse_share_protobuf(raw: &str) -> Result<ShareProto> {
let (threshold, id, base64_data) = parse_raw_share(raw)?;
let data = base64::decode_config(&base64_data, BASE64_CONFIG).chain_err(|| {
ErrorKind::ShareParsingError("Base64 decoding of data block failed".to_string())
})?;
let share_proto = protobuf::parse_from_bytes::<ShareProto>(data.as_slice()).map_err(|e| {
ErrorKind::ShareParsingError(format!(
"Protobuf decoding of data block failed with error: {} .",
e.description()
))
})?;
if threshold != share_proto.threshold {
bail! {
ErrorKind::ShareParsingError(
format!(
"Incompatible thresholds between decoded Protobuf provided \
(k={}) and raw share (k={})", share_proto.threshold, threshold
)
)}
}
if id != share_proto.id {
bail! {
ErrorKind::ShareParsingError(
format!(
"Incompatible ids between decoded Protobuf provided \
(i={}) and raw share (i={})", share_proto.id, id
)
)}
}
Ok(share_proto)
}
fn parse_raw_share(raw: &str) -> Result<(u32, u32, String)> {
let parts: Vec<_> = raw.trim().split('-').collect();
if parts.len() != 3 {
bail! {
ErrorKind::ShareParsingError(
format!(
"Expected 3 parts separated by a minus sign. Found {}.",
raw
),
)
};
}
let mut iter = parts.into_iter();
let k = iter.next().unwrap().parse::<u32>()?;
let i = iter.next().unwrap().parse::<u32>()?;
let data = iter.next().unwrap();
Ok((k, i, data.to_string()))
}

31
src/dss/metadata.rs Normal file
View File

@ -0,0 +1,31 @@
use std::collections::BTreeMap;
use ring::digest;
/// A share's public metadata.
#[derive(Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Default)]
pub struct MetaData {
/// The tags associated with the share
pub tags: BTreeMap<String, String>,
}
impl MetaData {
/// Construct a new MetaData struct.
pub fn new() -> Self {
MetaData {
tags: BTreeMap::new(),
}
}
/// Construct a new MetaData struct, holding the given tags
pub fn with_tags(tags: BTreeMap<String, String>) -> Self {
Self { tags }
}
pub(crate) fn hash_into(&self, ctx: &mut digest::Context) {
for (tag, value) in &self.tags {
ctx.update(tag.as_bytes());
ctx.update(b":");
ctx.update(value.as_bytes());
}
}
}

59
src/dss/mod.rs Normal file
View File

@ -0,0 +1,59 @@
//! Defines two different deterministic sharing schemes, ThSS and SS1.
//!
//! # Deterministic secret sharing
//!
//! TODO: Doc
//!
//! # Schemes
//!
//! The two schemes differ by the security properties that they satisfy.
//! The following table summarizes which properties are satisfied by each scheme.
//! The definitions of the properties can be found under the 'Security properties' section.
//!
//! **Scheme / Property** | **Basic** | **Priv1** | **Priv2** | **Auth1** | **Auth2** | **ErrDet** | **Repro** |
//! :--------------------:|:---------:|:---------:|:---------:|:---------:|:---------:|:----------:|:---------:|
//! **ThSS** | Yes | Yes | No | No | No | Yes | No |
//! **SS1** | Yes | Yes | Yes | Yes | Yes | Yes | Yes |
//!
//! # Security properties
//!
//! **Property** | **Description**
//! :-----------:|----------------|----------------
//! **Basic** | Basic correctness: If you attempt to recover a secret from an authorized set of shares that were obtained by sharing out a secret **M** using an access structure **A**, you're sure to get back **A** and **M**.<br> <em>Note: in this implementation **A** is not actually returned, but definitely could.</em>
//! **Priv1** | Standard privacy notation: When the coins are used by the dealer are uniformly random, unauthorized sets of shares have no computationally extractable information about the underlying secret.
//! **Priv2** | Privacy for deterministic or hedged schemes: extract whatever entropy one can from the underlying secret. If its adequate, no additional randomness is needed in order to achieve a meaningful notion of privacy.
//! **Auth1** | A share obtained from an honest dealer commits it to a single underlying secret: that and only that value can be recovered.
//! **Auth2** | A share obtained even from a dishonest dealer commits it to a single underlying secret: that and only that value might be recovered. Implies Auth1.
//! **ErrDet** | An inauthentic set of shares produced by an adversary will be flagged as such when fed to the recovery algorithm.
//! **Repro** | Share reproducible: The scheme can produce shares in a deterministic way.
pub mod thss;
pub mod ss1;
mod metadata;
mod format;
mod random;
mod utils;
/// Define the access structure used to deal and recover the shares.
///
/// For example, if one wants to deal 10 shares, and require 7 of them to
/// recover the secret, one would express it as:
///
/// ```rust
/// # use rusty_secrets::dss::AccessStructure;
/// AccessStructure {
/// threshold: 7,
/// shares_count: 10,
/// };
/// ```
#[derive(Copy, Clone, Debug)]
pub struct AccessStructure {
/// The minimum amount of shares required to recover the secret.
pub threshold: u8,
/// The total number of shares generated when splitting up the secret.
/// Always greater than or equal to `threshold`.
pub shares_count: u8,
}

66
src/dss/random.rs Normal file
View File

@ -0,0 +1,66 @@
use std;
use errors::*;
use ring::error::Unspecified;
use ring::rand::SecureRandom;
/// We bound the message size at about 16MB to avoid overflow in `random_bytes_count`.
/// Moreover, given the current performances, it is almost unpractical to run
/// the sharing scheme on message larger than that.
pub(crate) const MAX_MESSAGE_SIZE: usize = std::usize::MAX / (std::u8::MAX - 1) as usize;
/// Minimum allowed message size in bytes
pub(crate) static MIN_MESSAGE_SIZE: usize = 1;
/// Returns the number of random bytes to read from the secure random number generator.
/// As defined in section 3.1 of the 'New Directions in Secret Sharing' paper.
pub(crate) fn random_bytes_count(threshold: u8, message_size: usize) -> usize {
assert!(threshold >= MIN_THRESHOLD);
assert!(message_size >= MIN_MESSAGE_SIZE);
assert!(message_size <= MAX_MESSAGE_SIZE);
(threshold as usize - 1) * message_size
}
/// Attempts to read `count` random bytes from the given secure random generator.
pub(crate) fn random_bytes(random: &SecureRandom, count: usize) -> Result<Vec<u8>> {
if count == 0 {
return Ok(Vec::new());
}
let mut rl = vec![0; count];
random
.fill(&mut rl)
.chain_err(|| ErrorKind::CannotGenerateRandomNumbers)?;
Ok(rl)
}
/// An implementation of SecureRandom that fills the output slice with the slice in `src`.
/// The length of `src` must be larger than any slice that we attempt to fill.
pub(crate) struct FixedRandom {
src: Vec<u8>,
}
impl FixedRandom {
/// Create a new fixed random generator.
/// The length of `src` must be larger than any slice that we attempt to fill.
pub(crate) fn new(src: Vec<u8>) -> Self {
if src.is_empty() {
panic!("The source slice of FixedRandom cannot be empty!");
}
FixedRandom { src }
}
}
impl SecureRandom for FixedRandom {
fn fill(&self, dst: &mut [u8]) -> std::result::Result<(), Unspecified> {
if dst.len() > self.src.len() {
return Err(Unspecified);
}
let len = dst.len();
dst.copy_from_slice(&self.src[0..len]);
Ok(())
}
}

194
src/dss/ss1/mod.rs Normal file
View File

@ -0,0 +1,194 @@
//! Implements the `SS1` deterministic threshold secret sharing scheme.
//!
//! This scheme is implemented as the *T2 transform* over the ThSS threshold sharing scheme.
//! found in the `rusty_secrets::dss::thss` module.
//!
//! # Security properties
//!
//! This scheme satisfies the following security properties:
//!
//! **Property** | **Satisifed?** | **Description**
//! -------------|----------------|----------------
//! **Basic** | Yes | Basic correctness: If you attempt to recover a secret from an authorized set of shares that were obtained by sharing out a secret **M** using an access structure **A**, you're sure to get back **A** and **M**.<br> <em>Note: in this implementation **A** is not actually returned, but definitely could.</em>
//! **Priv1** | Yes | Standard privacy notation: When the coins are used by the dealer are uniformly random, unauthorized sets of shares have no computationally extractable information about the underlying secret.
//! **Priv2** | Yes | Privacy for deterministic or hedged schemes: extract whatever entropy one can from the underlying secret. If its adequate, no additional randomness is needed in order to achieve a meaningful notion of privacy.
//! **Auth1** | Yes | A share obtained from an honest dealer commits it to a single underlying secret: that and only that value can be recovered.
//! **Auth2** | Yes | A share obtained even from a dishonest dealer commits it to a single underlying secret: that and only that value might be recovered. Implies Auth1.
//! **ErrDet** | Yes | An inauthentic set of shares produced by an adversary will be flagged as such when fed to the recovery algorithm.
//! **Repro** | Yes | Share reproducible: The scheme can produce shares in a deterministic way.
//!
//! # References
//!
//! - *New Directions in Secret Sharing* (TODO: Full reference)
use errors::*;
mod serialize;
mod share;
pub use self::share::*;
mod scheme;
use self::scheme::SS1;
pub use self::scheme::Reproducibility;
use dss::AccessStructure;
/// Performs threshold k-out-of-n deterministic secret sharing.
///
/// # Examples
///
/// ```
/// use rusty_secrets::dss::ss1::{self, Reproducibility, MetaData};
///
/// let secret = "These programs were never about terrorism: theyre about economic spying, \
/// social control, and diplomatic manipulation. Theyre about power.";
///
/// let mut metadata = MetaData::new();
/// metadata.tags.insert("mime_type".to_string(), "text/plain".to_string());
///
/// match ss1::split_secret(7, 10, &secret.as_bytes(), Reproducibility::reproducible(), &Some(metadata)) {
/// Ok(shares) => {
/// // Do something with the shares
/// },
/// Err(_) => {
/// // Deal with error
/// }
/// }
/// ```
pub fn split_secret(
k: u8,
n: u8,
secret: &[u8],
reproducibility: Reproducibility,
metadata: &Option<MetaData>,
) -> Result<Vec<Share>> {
SS1::default().split_secret(k, n, secret, reproducibility, metadata)
}
/// Recovers the secret from a k-out-of-n deterministic secret sharing scheme (`SS1`).
///
/// At least `k` distinct shares need to be provided to recover the secret.
///
/// # Examples
///
/// ```rust
/// use rusty_secrets::dss::ss1::{self, Reproducibility, MetaData};
///
/// let secret = "These programs were never about terrorism: theyre about economic spying, \
/// social control, and diplomatic manipulation. Theyre about power.";
///
/// let mut metadata = MetaData::new();
/// metadata.tags.insert("mime_type".to_string(), "text/plain".to_string());
///
/// let shares = ss1::split_secret(
/// 7,
/// 10,
/// &secret.as_bytes(),
/// Reproducibility::reproducible(),
/// &Some(metadata)
/// ).unwrap();
///
/// match ss1::recover_secret(&shares) {
/// Ok((secret, access_structure, metadata)) => {
/// // Do something with the secret and the metadata
/// },
/// Err(e) => {
/// // Deal with the error
/// }
/// }
/// ```
pub fn recover_secret(shares: &[Share]) -> Result<(Vec<u8>, AccessStructure, Option<MetaData>)> {
SS1::default().recover_secret(shares)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn nonreproducible_split_then_recover_yields_original_secret() {
let secret = "Hello, World!".to_string().into_bytes();
let shares = split_secret(7, 10, &secret, Reproducibility::none(), &None).unwrap();
assert_eq!(shares.len(), 10);
let (recovered, access_structure, metadata) = recover_secret(&shares[2..9]).unwrap();
assert_eq!(secret, recovered);
assert_eq!(access_structure.threshold, 7);
assert_eq!(access_structure.shares_count, 10);
assert_eq!(None, metadata);
}
#[test]
fn reproducible_split_then_recover_yields_original_secret() {
let secret = "Hello, World!".to_string().into_bytes();
let shares = split_secret(7, 10, &secret, Reproducibility::reproducible(), &None).unwrap();
assert_eq!(shares.len(), 10);
let (recovered, access_structure, metadata) = recover_secret(&shares[2..9]).unwrap();
assert_eq!(secret, recovered);
assert_eq!(access_structure.threshold, 7);
assert_eq!(access_structure.shares_count, 10);
assert_eq!(None, metadata);
}
#[test]
fn seeded_reproducible_split_then_recover_yields_original_secret() {
let secret = "Hello, World!".to_string().into_bytes();
let seed = vec![1, 2, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16u8];
let shares = split_secret(7, 10, &secret, Reproducibility::seeded(seed), &None).unwrap();
assert_eq!(shares.len(), 10);
let (recovered, access_structure, metadata) = recover_secret(&shares[2..9]).unwrap();
assert_eq!(secret, recovered);
assert_eq!(access_structure.threshold, 7);
assert_eq!(access_structure.shares_count, 10);
assert_eq!(None, metadata);
}
#[test]
fn reproducible_split() {
let secret = "Hello, World!".to_string().into_bytes();
let shares_1 =
split_secret(7, 10, &secret, Reproducibility::reproducible(), &None).unwrap();
let shares_2 =
split_secret(7, 10, &secret, Reproducibility::reproducible(), &None).unwrap();
assert_eq!(shares_1, shares_2);
}
#[test]
fn nonreproducible_split() {
let secret = "Hello, World!".to_string().into_bytes();
let shares_1 = split_secret(7, 10, &secret, Reproducibility::none(), &None).unwrap();
let shares_2 = split_secret(7, 10, &secret, Reproducibility::none(), &None).unwrap();
assert!(shares_1 != shares_2);
}
#[test]
fn seeded_split() {
let secret = "Hello, World!".to_string().into_bytes();
let seed = vec![1, 2, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16u8];
let shares_1 =
split_secret(7, 10, &secret, Reproducibility::seeded(seed.clone()), &None).unwrap();
let shares_2 =
split_secret(7, 10, &secret, Reproducibility::seeded(seed.clone()), &None).unwrap();
assert_eq!(shares_1, shares_2);
}
}

317
src/dss/ss1/scheme.rs Normal file
View File

@ -0,0 +1,317 @@
use std::collections::HashSet;
use ring::{hkdf, hmac};
use ring::rand::{SecureRandom, SystemRandom};
use ring::digest::{Context, SHA256};
use rand::{ChaChaRng, Rng, SeedableRng};
use errors::*;
use dss::{thss, AccessStructure};
use dss::thss::{MetaData, ThSS};
use dss::random::{random_bytes_count, FixedRandom, MAX_MESSAGE_SIZE};
use share::validation::{validate_share_count, validate_shares};
use super::share::*;
use dss::utils;
use vol_hash::VOLHash;
/// We bound the message size at about 16MB to avoid overflow in `random_bytes_count`.
/// Moreover, given the current performances, it is almost unpractical to run
/// the sharing scheme on message larger than that.
const MAX_SECRET_SIZE: usize = MAX_MESSAGE_SIZE;
const DEFAULT_PRESEED: &[u8] = b"rusty_secrets::dss::ss1";
/// There are situations where it's useful to generate shares in a reproducible manner.
/// In particular, this allows a secret thats in someones head, a passphrase,
/// to be shared out in a manner in which different shares can be given to
/// different people at different points in time.
///
/// On the other hand, there is some privacy cost.
/// For example, if you know the secret is one of two possibilities,
/// M0 or M1, in a share-reproducible scheme, acquiring a single share
/// will probably let you decide which of the two possibilities it was.
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub enum Reproducibility {
/// Shares will be produced in a deterministic way, using
/// a default, fixed seed for the internal random number generator
/// used to generate entropy.
Reproducible,
/// Shares will be produced in non-deterministic way, using
/// the system's random number generator to produce entropy.
None,
/// Shares will be produced in a deterministic way, using
/// the given seed for the internal random number generator used to
/// generate entropy.
Seeded(Vec<u8>),
/// Shares will be produced in a deterministic way, using
/// the given byte vector as the entropy source.
/// *Warning: Never use this variant unless you are sure of what you are doing*
WithEntropy(Vec<u8>),
}
impl Reproducibility {
/// Shares will be produced in a deterministic way, using
/// a default, fixed seed for the internal random number generator
/// used to generate entropy.
pub fn reproducible() -> Self {
Reproducibility::Reproducible
}
/// Shares will be produced in a deterministic way, using
/// the given seed for the internal random number generator used to
/// generate entropy.
pub fn seeded(seed: Vec<u8>) -> Self {
assert!(!seed.is_empty(), "Reproducibility: seed cannot be empty");
Reproducibility::Seeded(seed)
}
/// Shares will be produced in a deterministic way, using
/// the given byte vector as the entropy source.
/// *Warning: Never use this variant unless you are sure of what you are doing*
pub fn with_entropy(entropy: Vec<u8>) -> Self {
assert!(
!entropy.is_empty(),
"Reproducibility: entropy cannot be empty"
);
Reproducibility::WithEntropy(entropy)
}
/// Shares will be produced in non-deterministic way, using
/// the system's random number generator to produce entropy.
pub fn none() -> Self {
Reproducibility::None
}
}
/// Defines a `SS1` deterministic threshold secret sharing scheme.
///
/// This scheme is implemented as the *T2 transform* over the ThSS threshold sharing scheme.
/// found in the `rusty_secrets::dss::thss` module.
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub(crate) struct SS1 {
/// How many random bytes to read from `random` to use as
/// padding to the hash function (param `r` from the paper)
/// and to the message in the underlying ThSS scheme.
pub random_padding_len: usize,
/// The length of the hash used for all shares (param `s` from the paper)
pub hash_len: usize,
}
// TODO: Are those good parameters?
// TODO: Add max length ?
static DEFAULT_RANDOM_PADDING_LEN: usize = 512; // r
static MIN_RANDOM_PADDING_LEN: usize = 128; // r min
static DEFAULT_HASH_LEN: usize = 256; // s
static MIN_HASH_LEN: usize = 128; // s min
impl Default for SS1 {
fn default() -> Self {
Self::new(DEFAULT_RANDOM_PADDING_LEN, DEFAULT_HASH_LEN).unwrap()
}
}
impl SS1 {
/// Constructs a new sharing scheme
pub fn new(random_padding_len: usize, hash_len: usize) -> Result<Self> {
if random_padding_len < MIN_RANDOM_PADDING_LEN || hash_len < MIN_HASH_LEN {
bail!(ErrorKind::InvalidSS1Parameters(
random_padding_len,
hash_len,
));
}
Ok(Self {
random_padding_len,
hash_len,
})
}
/// Split a secret following a given sharing `scheme`,
/// with `threshold` being the number of shares necessary to recover the secret,
/// and `shares_count` the total number of shares to be dealt.
pub fn split_secret(
&self,
threshold: u8,
shares_count: u8,
secret: &[u8],
reproducibility: Reproducibility,
metadata: &Option<MetaData>,
) -> Result<Vec<Share>> {
let (threshold, shares_count) = validate_share_count(threshold, shares_count)?;
let secret_len = secret.len();
if secret_len == 0 {
bail!(ErrorKind::EmptySecret);
}
if secret_len > MAX_SECRET_SIZE {
bail!(ErrorKind::SecretTooBig(secret_len, MAX_SECRET_SIZE));
}
let random_padding = self.generate_random_padding(reproducibility, secret, metadata)?;
let mut vol_hash = VOLHash::new(&SHA256);
vol_hash.process(&[0]);
vol_hash.process(&[threshold, shares_count]);
vol_hash.process(secret);
vol_hash.process(&random_padding);
let randomness_len = random_bytes_count(threshold, secret.len() + self.random_padding_len);
let total_hash_len = self.hash_len + randomness_len;
let mut full_hash = vec![0; total_hash_len];
vol_hash.finish(&mut full_hash);
let (hash, randomness) = full_hash.split_at(self.hash_len);
let underlying = ThSS::new(Box::new(FixedRandom::new(randomness.to_vec())));
let message = [secret, &random_padding].concat();
let shares = underlying.split_secret(threshold, shares_count, &message, metadata)?;
let res = shares
.into_iter()
.map(|share| Share {
id: share.id,
threshold: share.threshold,
shares_count: share.shares_count,
data: share.data,
hash: hash.to_vec(),
metadata: share.metadata.clone(),
})
.collect();
Ok(res)
}
fn generate_random_padding(
&self,
reproducibility: Reproducibility,
secret: &[u8],
metadata: &Option<MetaData>,
) -> Result<Vec<u8>> {
match reproducibility {
Reproducibility::None => {
let rng = SystemRandom::new();
let mut result = vec![0u8; self.random_padding_len];
rng.fill(&mut result)
.chain_err(|| ErrorKind::CannotGenerateRandomNumbers)?;
Ok(result)
}
Reproducibility::Reproducible => {
let seed = self.generate_seed(DEFAULT_PRESEED, secret, metadata);
let mut rng = ChaChaRng::from_seed(&seed);
let mut result = vec![0u8; self.random_padding_len];
rng.fill_bytes(result.as_mut_slice());
Ok(result)
}
Reproducibility::Seeded(preseed) => {
let seed = self.generate_seed(&preseed, secret, metadata);
let mut rng = ChaChaRng::from_seed(&seed);
let mut result = vec![0u8; self.random_padding_len];
rng.fill_bytes(result.as_mut_slice());
Ok(result)
}
Reproducibility::WithEntropy(entropy) => Ok(entropy),
}
}
/// Generate a seed of 8 32-bits word for the ChaCha20 PRNG by hashing
/// together the preseed, secret, and metadata, in order to obtain a salt
/// for performing HKDF over the preseed.
fn generate_seed(
&self,
preseed: &[u8],
secret: &[u8],
metadata: &Option<MetaData>,
) -> Vec<u32> {
let mut ctx = Context::new(&SHA256);
ctx.update(preseed);
ctx.update(secret);
for md in metadata {
md.hash_into(&mut ctx);
}
let preseed_hash = ctx.finish();
let salt = hmac::SigningKey::new(&SHA256, &[]);
let mut seed_bytes = vec![0u8; 32];
hkdf::extract_and_expand(&salt, preseed_hash.as_ref(), &[], &mut seed_bytes);
// We can safely call `utils::slice_u8_to_slice_u32` because
// the `digest` produced with `SHA256` is 256 bits long, as is
// `seed_bytes`, and the latter can thus be represented both as a
// slice of 32 bytes or as a slice of 8 32-bit words.
utils::slice_u8_to_slice_u32(&seed_bytes).to_vec()
}
/// Recover the secret from the given set of shares
pub fn recover_secret(
&self,
shares: &[Share],
) -> Result<(Vec<u8>, AccessStructure, Option<MetaData>)> {
let (_, shares) = validate_shares(shares.to_vec())?;
let underlying_shares = shares
.iter()
.map(|share| thss::Share {
id: share.id,
threshold: share.threshold,
shares_count: share.shares_count,
data: share.data.clone(),
metadata: share.metadata.clone(),
})
.collect::<Vec<_>>();
let underlying = ThSS::default();
let (mut secret, _, metadata) = underlying.recover_secret(&underlying_shares)?;
let secret_len = secret.len() - self.random_padding_len;
let random_padding = secret.split_off(secret_len);
// `secret` nows holds the secret
let sub_scheme = Self::new(self.random_padding_len, self.hash_len)?;
let test_shares = sub_scheme.split_secret(
shares[0].threshold,
shares[0].shares_count,
&secret,
Reproducibility::WithEntropy(random_padding.to_vec()),
&metadata,
)?;
let access_structure = {
let first_share = shares.first().unwrap();
AccessStructure {
threshold: first_share.threshold,
shares_count: first_share.shares_count,
}
};
self.verify_test_shares(shares, test_shares)?;
Ok((secret, access_structure, metadata))
}
fn verify_test_shares(
&self,
mut shares: Vec<Share>,
mut test_shares: Vec<Share>,
) -> Result<()> {
shares.sort_by_key(|share| share.id);
test_shares.sort_by_key(|share| share.id);
let relevant_ids = shares.iter().map(|share| share.id).collect::<HashSet<_>>();
let relevant_test_shares = test_shares
.iter()
.filter(|share| relevant_ids.contains(&share.id));
let matching_shares = shares.iter().zip(relevant_test_shares);
for (share, test_share) in matching_shares {
if share != test_share {
bail!(ErrorKind::MismatchingShares(
share.clone(),
test_share.clone(),
));
}
}
Ok(())
}
}

80
src/dss/ss1/serialize.rs Normal file
View File

@ -0,0 +1,80 @@
use errors::*;
use super::{MetaData, Share};
use dss::format::{format_share_protobuf, parse_share_protobuf};
use proto::dss::{MetaDataProto, ShareProto};
use dss::utils::{btreemap_to_hashmap, hashmap_to_btreemap};
pub(crate) fn share_to_string(share: Share) -> String {
let proto = share_to_protobuf(share);
format_share_protobuf(&proto)
}
pub(crate) fn share_from_string(raw: &str) -> Result<Share> {
let mut proto = parse_share_protobuf(raw)?;
let metadata_proto = if proto.has_meta_data() {
Some(metadata_from_proto(proto.take_meta_data()))
} else {
None
};
let i = proto.get_id() as u8;
let k = proto.get_threshold() as u8;
let n = proto.get_shares_count() as u8;
if k < 1 || i < 1 {
bail! {
ErrorKind::ShareParsingError(
format!("Found illegal share info: threshold = {}, identifier = {}.", k, i),
)
}
}
if n < 1 || k > n || i > n {
bail! {
ErrorKind::ShareParsingError(
format!("Found illegal share info: shares_count = {}, threshold = {}, identifier = {}.", n, k, i),
)
}
}
let share = Share {
id: i,
threshold: k,
shares_count: n,
data: proto.take_data(),
hash: proto.take_hash(),
metadata: metadata_proto,
};
Ok(share)
}
pub(crate) fn share_to_protobuf(share: Share) -> ShareProto {
let mut proto = ShareProto::new();
proto.set_id(share.id.into());
proto.set_threshold(share.threshold.into());
proto.set_shares_count(share.shares_count.into());
proto.set_data(share.data);
proto.set_hash(share.hash);
if let Some(meta_data) = share.metadata {
let metadata_proto = metadata_to_proto(meta_data);
proto.set_meta_data(metadata_proto);
}
proto
}
fn metadata_to_proto(meta_data: MetaData) -> MetaDataProto {
let mut proto = MetaDataProto::new();
proto.set_tags(btreemap_to_hashmap(meta_data.tags));
proto
}
fn metadata_from_proto(mut proto: MetaDataProto) -> MetaData {
MetaData {
tags: hashmap_to_btreemap(proto.take_tags()),
}
}

57
src/dss/ss1/share.rs Normal file
View File

@ -0,0 +1,57 @@
use errors::*;
use share::IsShare;
use super::serialize::{share_from_string, share_to_string};
pub use dss::metadata::MetaData;
/// A share identified by an `id`, a threshold `k`, a number of total shares `n`,
/// the `data` held in the share, and the share's `metadata`.
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Share {
/// The identifier of the share (varies between 1 and n where n is the total number of generated shares)
pub id: u8,
/// The number of shares necessary to recover the secret, aka a threshold
pub threshold: u8,
/// The total number of shares that have been dealt
pub shares_count: u8,
/// The share data itself
pub data: Vec<u8>,
/// The hash value common to the whole deal
pub hash: Vec<u8>,
/// The metadata associated with this share
pub metadata: Option<MetaData>,
}
impl Share {
/// Format this share a string suitable for sharing
/// over an ASCII-encoded channel, such as a text file,
/// or an e-mail.
pub fn into_string(self) -> String {
share_to_string(self)
}
/// Parse the given string into a `Share`.
/// The `raw` string must have been generated by the
/// `Share::to_string` method for it to succeed.
pub fn from_string(raw: &str) -> Result<Self> {
share_from_string(raw)
}
}
impl IsShare for Share {
fn get_id(&self) -> u8 {
self.id
}
fn get_data(&self) -> &[u8] {
&self.data
}
fn get_threshold(&self) -> u8 {
self.threshold
}
fn get_shares_count(&self) -> Option<u8> {
Some(self.shares_count)
}
}

37
src/dss/thss/encode.rs Normal file
View File

@ -0,0 +1,37 @@
use gf256::Gf256;
use poly::Poly;
/// Encode the given `secret` using the `ThSS[N].Share` algorithm described
/// in the *New directions in Secret Sharing* paper.
///
/// Reference: Figure 7 from the *New Directions in Secret Sharing* paper.
pub(crate) fn encode_secret(secret: &[u8], k: u8, share_id: u8, rands: &[u8]) -> Vec<u8> {
secret
.into_iter()
.enumerate()
.map(|(i, m)| {
let k_pred = (k - 1) as usize;
let coeffs = (0..k_pred)
.map(|l| {
let n = rands[i * k_pred + l];
Gf256::from_byte(n)
})
.collect();
let poly = Poly::new(coeffs);
encode_secret_byte(*m, share_id, &poly)
})
.collect()
}
/// Encode the given secret byte `m`, by evaluating the given
/// polynomial at x = `j`, and adding the result to `m`.
///
/// Reference: Figure 7 from the *New Directions in Secret Sharing* paper.
pub(crate) fn encode_secret_byte(m: u8, j: u8, poly: &Poly) -> u8 {
let mut acc = Gf256::from_byte(m);
for (l, &r) in poly.coeffs.iter().enumerate() {
let s = Gf256::from_byte(j).pow(l as u8 + 1);
acc = acc + r * s;
}
acc.to_byte()
}

122
src/dss/thss/mod.rs Normal file
View File

@ -0,0 +1,122 @@
//! Implements the `ThSS` threshold secret sharing scheme.
//!
//! This scheme satisfies the following security properties:
//!
//! **Property** | **Satisifed?** | **Description**
//! -------------|----------------|----------------
//! **Basic** | Yes | Basic correctness: If you attempt to recover a secret from an authorized set of shares that were obtained by sharing out a secret **M** using an access structure **A**, you're sure to get back **A** and **M**.<br> <em>Note: in this implementation **A** is not actually returned, but definitely could.</em>
//! **Priv1** | Yes | Standard privacy notation: When the coins are used by the dealer are uniformly random, unauthorized sets of shares have no computationally extractable information about the underlying secret.
//! **Priv2** | No | Privacy for deterministic or hedged schemes: extract whatever entropy one can from the underlying secret. If its adequate, no additional randomness is needed in order to achieve a meaningful notion of privacy.
//! **Auth1** | No | A share obtained from an honest dealer commits it to a single underlying secret: that and only that value can be recovered.
//! **Auth2** | No | A share obtained even from a dishonest dealer commits it to a single underlying secret: that and only that value might be recovered. Implies Auth1.
//! **ErrDet** | Yes | An inauthentic set of shares produced by an adversary will be flagged as such when fed to the recovery algorithm.
//! **Repro** | No | Share reproducible: The scheme can produce shares in a deterministic way.
use errors::*;
mod encode;
mod serialize;
mod share;
pub use self::share::*;
mod scheme;
pub(crate) use self::scheme::ThSS;
use dss::AccessStructure;
/// Performs threshold k-out-of-n secret sharing using the `ThSS` scheme.
///
/// # Examples
///
/// ```rust
/// use rusty_secrets::dss::thss;
///
/// let secret = "These programs were never about terrorism: theyre about economic spying, \
/// social control, and diplomatic manipulation. Theyre about power.";
///
/// let mut metadata = thss::MetaData::new();
/// metadata.tags.insert("mime_type".to_string(), "text/plain".to_string());
///
/// let result = thss::split_secret(
/// 7,
/// 10,
/// &secret.as_bytes(),
/// &Some(metadata)
/// );
///
/// match result {
/// Ok(shares) => {
/// // Do something with the shares
/// },
/// Err(e) => {
/// // Deal with error
/// }
/// }
///
/// ```
pub fn split_secret(
k: u8,
n: u8,
secret: &[u8],
metadata: &Option<MetaData>,
) -> Result<Vec<Share>> {
ThSS::default().split_secret(k, n, secret, metadata)
}
/// Recovers the secret from a k-out-of-n secret sharing scheme (`ThSS`).
///
/// At least `k` distinct shares need to be provided to recover the secret.
///
/// # Examples
///
/// ```rust
/// use rusty_secrets::dss::thss;
///
/// let secret = "These programs were never about terrorism: theyre about economic spying, \
/// social control, and diplomatic manipulation. Theyre about power.";
///
/// let mut metadata = thss::MetaData::new();
/// metadata.tags.insert("mime_type".to_string(), "text/plain".to_string());
///
/// let shares = thss::split_secret(
/// 7,
/// 10,
/// &secret.as_bytes(),
/// &Some(metadata)
/// ).unwrap();
///
/// match thss::recover_secret(&shares) {
/// Ok((secret, access_structure, metadata)) => {
/// // Do something with the secret and the metadata
/// },
/// Err(e) => {
/// // Deal with the error
/// }
/// }
/// ```
pub fn recover_secret(shares: &[Share]) -> Result<(Vec<u8>, AccessStructure, Option<MetaData>)> {
ThSS::default().recover_secret(shares)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn split_then_recover_yields_original_secret() {
let secret = "Hello, World!".to_string().into_bytes();
let shares = split_secret(7, 10, &secret, &None).unwrap();
assert_eq!(shares.len(), 10);
let (recovered, access, metadata) = recover_secret(&shares[2..9]).unwrap();
assert_eq!(secret, recovered);
assert_eq!(access.threshold, 7);
assert_eq!(access.shares_count, 10);
assert_eq!(None, metadata);
}
}

134
src/dss/thss/scheme.rs Normal file
View File

@ -0,0 +1,134 @@
//! Simple threshold secret sharing scheme
use std::fmt;
use ring::rand::{SecureRandom, SystemRandom};
use errors::*;
use gf256::Gf256;
use dss::random::{random_bytes, random_bytes_count, MAX_MESSAGE_SIZE};
use share::validation::{validate_share_count, validate_shares};
use lagrange;
use super::AccessStructure;
use super::share::*;
use super::encode::encode_secret;
/// We bound the message size at about 16MB to avoid overflow in `random_bytes_count`.
/// Moreover, given the current performances, it is almost unpractical to run
/// the sharing scheme on message larger than that.
const MAX_SECRET_SIZE: usize = MAX_MESSAGE_SIZE;
/// A simple threshold sharing scheme
#[allow(missing_debug_implementations)]
pub(crate) struct ThSS {
/// The randomness source
random: Box<SecureRandom>,
}
impl fmt::Debug for ThSS {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "ThSS")
}
}
impl Default for ThSS {
fn default() -> Self {
Self::new(Box::new(SystemRandom::new()))
}
}
impl ThSS {
/// Constructs a new sharing scheme
pub fn new(random: Box<SecureRandom>) -> Self {
Self { random }
}
/// Split a secret following a given sharing `scheme`,
/// with `threshold` being the number of shares necessary to recover the secret,
/// and `shares_count` the total number of shares to be dealt.
pub fn split_secret(
&self,
threshold: u8,
shares_count: u8,
secret: &[u8],
metadata: &Option<MetaData>,
) -> Result<Vec<Share>> {
let (threshold, shares_count) = validate_share_count(threshold, shares_count)?;
let secret_len = secret.len();
if secret_len == 0 {
bail!(ErrorKind::EmptySecret);
}
if secret_len > MAX_SECRET_SIZE {
bail!(ErrorKind::SecretTooBig(secret_len, MAX_SECRET_SIZE));
}
let rands_len = random_bytes_count(threshold, secret_len);
let rands = random_bytes(self.random.as_ref(), rands_len)?;
let shares = (1..shares_count + 1)
.map(|id| {
let data = encode_secret(secret, threshold, id, &rands);
Share {
id,
threshold,
shares_count,
data,
metadata: metadata.clone(),
}
})
.collect();
Ok(shares)
}
/// Recover the secret from the given set of shares
pub fn recover_secret(
&self,
shares: &[Share],
) -> Result<(Vec<u8>, AccessStructure, Option<MetaData>)> {
let (threshold, shares) = validate_shares(shares.to_vec())?;
let cypher_len = shares[0].data.len();
let polys = (0..cypher_len)
.map(|i| {
let points = shares
.iter()
.take(threshold as usize)
.map(|share| (Gf256::from_byte(share.id), Gf256::from_byte(share.data[i])))
.collect::<Vec<_>>();
lagrange::interpolate(&points)
})
.collect::<Vec<_>>();
for (i, poly) in polys.iter().enumerate() {
// Check remaining shares for consistency.
// See Figure 7 of the paper
let remaining_shares = shares.iter().enumerate().skip(threshold as usize);
for (u, share) in remaining_shares {
let value = poly.evaluate_at(Gf256::from_byte(u as u8 + 1)).to_byte();
if value != share.data[i] {
bail!(ErrorKind::InconsistentShares);
}
}
}
let metadata = shares[0].metadata.clone();
let secret = polys
.iter()
.map(|p| p.evaluate_at_zero().to_byte())
.collect();
let access_structure = AccessStructure {
threshold: threshold,
shares_count: shares.first().unwrap().shares_count,
};
Ok((secret, access_structure, metadata))
}
}

78
src/dss/thss/serialize.rs Normal file
View File

@ -0,0 +1,78 @@
use errors::*;
use super::{MetaData, Share};
use dss::format::{format_share_protobuf, parse_share_protobuf};
use proto::dss::{MetaDataProto, ShareProto};
use dss::utils::{btreemap_to_hashmap, hashmap_to_btreemap};
pub(crate) fn share_to_string(share: Share) -> String {
let proto = share_to_protobuf(share);
format_share_protobuf(&proto)
}
pub(crate) fn share_from_string(raw: &str) -> Result<Share> {
let mut proto = parse_share_protobuf(raw)?;
let metadata_proto = if proto.has_meta_data() {
Some(metadata_from_proto(proto.take_meta_data()))
} else {
None
};
let i = proto.get_id() as u8;
let k = proto.get_threshold() as u8;
let n = proto.get_shares_count() as u8;
if k < 1 || i < 1 {
bail! {
ErrorKind::ShareParsingError(
format!("Found illegal share info: threshold = {}, identifier = {}.", k, i),
)
}
}
if n < 1 || k > n || i > n {
bail! {
ErrorKind::ShareParsingError(
format!("Found illegal share info: shares_count = {}, threshold = {}, identifier = {}.", n, k, i),
)
}
}
let share = Share {
id: i,
threshold: k,
shares_count: n,
data: proto.take_data(),
metadata: metadata_proto,
};
Ok(share)
}
pub(crate) fn share_to_protobuf(share: Share) -> ShareProto {
let mut proto = ShareProto::new();
proto.set_id(share.id.into());
proto.set_threshold(share.threshold.into());
proto.set_shares_count(share.shares_count.into());
proto.set_data(share.data);
if let Some(meta_data) = share.metadata {
let metadata_proto = metadata_to_proto(meta_data);
proto.set_meta_data(metadata_proto);
}
proto
}
fn metadata_to_proto(meta_data: MetaData) -> MetaDataProto {
let mut proto = MetaDataProto::new();
proto.set_tags(btreemap_to_hashmap(meta_data.tags));
proto
}
fn metadata_from_proto(mut proto: MetaDataProto) -> MetaData {
MetaData {
tags: hashmap_to_btreemap(proto.take_tags()),
}
}

55
src/dss/thss/share.rs Normal file
View File

@ -0,0 +1,55 @@
use errors::*;
use share::IsShare;
use super::serialize::{share_from_string, share_to_string};
pub use dss::metadata::MetaData;
/// A share identified by an `id`, a threshold `k`, a number of total shares `n`,
/// the `data` held in the share, and the share's `metadata`.
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct Share {
/// The identifier of the share (varies between 1 and n where n is the total number of generated shares)
pub id: u8,
/// The number of shares necessary to recover the secret, aka a threshold
pub threshold: u8,
/// The total number of shares that have been dealt
pub shares_count: u8,
/// The share data itself
pub data: Vec<u8>,
/// The metadata associated with this share
pub metadata: Option<MetaData>,
}
impl Share {
/// Format this share a string suitable for sharing
/// over an ASCII-encoded channel, such as a text file,
/// or an e-mail.
pub fn into_string(self) -> String {
share_to_string(self)
}
/// Parse the given string into a `Share`.
/// The `raw` string must have been generated by the
/// `Share::to_string` method for it to succeed.
pub fn from_string(raw: &str) -> Result<Self> {
share_from_string(raw)
}
}
impl IsShare for Share {
fn get_id(&self) -> u8 {
self.id
}
fn get_data(&self) -> &[u8] {
&self.data
}
fn get_threshold(&self) -> u8 {
self.threshold
}
fn get_shares_count(&self) -> Option<u8> {
Some(self.shares_count)
}
}

28
src/dss/utils.rs Normal file
View File

@ -0,0 +1,28 @@
use std;
use std::hash::Hash;
use std::collections::{BTreeMap, HashMap};
/// Transmutes a `&[u8]` into a `&[u32]`.
/// Despite `std::mem::transmute` being very unsafe in
/// general, this should actually be safe as long as
/// `input` contains a multiple of 4 bytes.
#[allow(unsafe_code)]
pub(crate) fn slice_u8_to_slice_u32(input: &[u8]) -> &[u32] {
assert_eq!(input.len() % 4, 0);
unsafe { std::mem::transmute(input) }
}
/// Creates a `HashMap` from a `BTreeMap`
pub(crate) fn btreemap_to_hashmap<A: Eq + Hash, B>(btree: BTreeMap<A, B>) -> HashMap<A, B> {
let mut hash = HashMap::new();
hash.extend(btree.into_iter());
hash
}
/// Creates a `BTreeMap` from a `HashMap`
pub(crate) fn hashmap_to_btreemap<A: Ord + Hash, B>(hash: HashMap<A, B>) -> BTreeMap<A, B> {
let mut btree = BTreeMap::new();
btree.extend(hash.into_iter());
btree
}

141
src/errors.rs Normal file
View File

@ -0,0 +1,141 @@
//! Define the various error kinds specific to deterministic secret sharing.
#![allow(unknown_lints, missing_docs)]
use std::collections::HashSet;
#[cfg(feature = "dss")]
use dss::ss1;
/// Minimum allowed number of shares (n)
pub(crate) static MIN_SHARES: u8 = 2;
/// Minimum allowed threshold (k)
pub(crate) static MIN_THRESHOLD: u8 = 2;
/// Maximum allowed number of shares (k,n)
pub(crate) static MAX_SHARES: u8 = 255;
/// SSS Shares should be structured as k-n-data hence 3 parts
pub(crate) static SSS_SHARE_PARTS_COUNT: usize = 3;
/// Create the Error, ErrorKind, ResultExt, and Result types
error_chain! {
errors {
ThresholdTooBig(k: u8, n: u8) {
description("Threshold k must be smaller than or equal to n")
display("Threshold k must be smaller than or equal to n, got: k = {}, n = {}.", k, n)
}
ThresholdTooSmall(k: u8) {
description("Threshold k must be bigger than or equal to 2")
display("Threshold k must be bigger than or equal to 2, got: k = {}", k)
}
SecretTooBig(len: usize, max: usize) {
description("The secret is too long")
display("The secret is too long, maximum allowed size = {} bytes, got {} bytes", max, len)
}
InvalidShareCountMax(nb_shares: u8, max: u8) {
description("Number of shares is too big")
display("Number of shares must be smaller than or equal {}, got: {} shares.", max, nb_shares)
}
InvalidShareCountMin(nb_shares: u8, min: u8) {
description("Number of shares is too small")
display("Number of shares must be larger than or equal {}, got: {} shares.", min, nb_shares)
}
EmptySecret {
description("The secret cannot be empty")
display("The secret cannot be empty")
}
EmptyShares {
description("No shares provided")
display("No shares were provided.")
}
IncompatibleSets(sets: Vec<HashSet<u8>>) {
description("The shares are incompatible with each other.")
display("The shares are incompatible with each other.")
}
ShareIdentifierTooBig(id: u8, n: u8) {
description("Share identifier too big")
display("Found share identifier ({}) bigger than the maximum number of shares ({}).", id, n)
}
MissingShares(provided: usize, required: usize) {
description("The number of shares provided is insufficient to recover the secret.")
display("{} shares are required to recover the secret, found only {}.", required, provided)
}
InvalidSignature(share_id: u8, signature: String) {
description("The signature of this share is not valid.")
}
MissingSignature(share_id: u8) {
description("Signature is missing while shares are required to be signed.")
}
SecretDeserializationError {
description("An issue was encountered deserializing the secret. \
Updating to the latest version of RustySecrets might help fix this.")
}
ShareParsingError(reason: String) {
description("This share is incorrectly formatted.")
display("This share is incorrectly formatted. Reason: {}", reason)
}
ShareParsingErrorEmptyShare(share_id: u8) {
description("This share is empty.")
display("Found empty share for share identifier ({})", share_id)
}
ShareParsingInvalidShareId(share_id: u8) {
description("Invalid share identifier.")
display("Found invalid share identifier ({})", share_id)
}
InvalidSS1Parameters(r: usize, s: usize) {
description("Invalid parameters for the SS1 sharing scheme")
display("Invalid parameters for the SS1 sharing scheme: r = {}, s = {}.", r, s)
}
InvalidSplitParametersZero(k: u8, n: u8) {
description("Parameters k and n must be greater than zero")
display("Parameters k and n must be greater than zero.")
}
#[cfg(feature = "dss")]
MismatchingShares(got: ss1::Share, expected: ss1::Share) {
description("Share mismatch during verification of secret recovery")
display("Share mismatch during verification of secret recovery.")
}
CannotGenerateRandomNumbers {
description("Cannot generate random numbers")
display("Cannot generate random numbers.")
}
DuplicateShareId(share_id: u8) {
description("This share number has already been used by a previous share.")
display("This share number ({}) has already been used by a previous share.", share_id)
}
DuplicateShareData(share_id: u8) {
description("The data encoded in this share is the same as the one found in a previous share")
display("The data encoded in share #{} is the same as the one found in a previous share.", share_id)
}
InconsistentShares {
description("The shares are inconsistent")
display("The shares are inconsistent")
}
}
foreign_links {
Io(::std::io::Error);
IntegerParsingError(::std::num::ParseIntError);
}
}

View File

@ -1,7 +1,7 @@
//! This module provides the Gf256 type which is used to represent
//! elements of a finite field with 256 elements.
use std::ops::{Add, Div, Mul, Sub};
use std::ops::{Add, Div, Mul, Neg, Sub};
include!(concat!(env!("OUT_DIR"), "/nothinghardcoded.rs"));
@ -10,7 +10,7 @@ fn get_tables() -> &'static Tables {
}
/// Type for elements of a finite field with 256 elements
#[derive(Copy,Clone,PartialEq,Eq)]
#[derive(Copy, Debug, Clone, PartialEq, Eq)]
pub struct Gf256 {
pub poly: u8,
}
@ -34,6 +34,10 @@ impl Gf256 {
pub fn to_byte(&self) -> u8 {
self.poly
}
pub fn exp(power: u8) -> Gf256 {
let tabs = get_tables();
Gf256::from_byte(tabs.exp[power as usize])
}
pub fn log(&self) -> Option<u8> {
if self.poly == 0 {
None
@ -42,9 +46,23 @@ impl Gf256 {
Some(tabs.log[self.poly as usize])
}
}
pub fn exp(power: u8) -> Gf256 {
let tabs = get_tables();
Gf256 { poly: tabs.exp[power as usize] }
pub fn pow(&self, mut exp: u8) -> Gf256 {
let mut base = *self;
let mut acc = Self::one();
while exp > 1 {
if (exp & 1) == 1 {
acc = acc * base;
}
exp /= 2;
base = base * base;
}
if exp == 1 {
acc = acc * base;
}
acc
}
}
@ -68,7 +86,7 @@ impl Mul<Gf256> for Gf256 {
type Output = Gf256;
fn mul(self, rhs: Gf256) -> Gf256 {
if let (Some(l1), Some(l2)) = (self.log(), rhs.log()) {
let tmp = ((l1 as u16) + (l2 as u16)) % 255;
let tmp = (u16::from(l1) + u16::from(l2)) % 255;
Gf256::exp(tmp as u8)
} else {
Gf256 { poly: 0 }
@ -81,10 +99,159 @@ impl Div<Gf256> for Gf256 {
fn div(self, rhs: Gf256) -> Gf256 {
let l2 = rhs.log().expect("division by zero");
if let Some(l1) = self.log() {
let tmp = ((l1 as u16) + 255 - (l2 as u16)) % 255;
let tmp = (u16::from(l1) + 255 - u16::from(l2)) % 255;
Gf256::exp(tmp as u8)
} else {
Gf256 { poly: 0 }
}
}
}
impl Neg for Gf256 {
type Output = Gf256;
fn neg(self) -> Gf256 {
Gf256::zero() - self
}
}
#[macro_export]
#[doc(hidden)]
macro_rules! gf256 {
($e:expr) => (Gf256::from_byte($e))
}
#[macro_export]
#[doc(hidden)]
macro_rules! gf256_vec {
( $( ($x:expr, $y:expr) ),* ) => {
{
let mut temp_vec = Vec::new();
$(
temp_vec.push((Gf256::from_byte($x), Gf256::from_byte($y)));
)*
temp_vec
}
};
( $( $x:expr ),* ) => {
{
let mut temp_vec = Vec::new();
$(
temp_vec.push(Gf256::from_byte($x));
)*
temp_vec
}
};
}
#[cfg(test)]
#[allow(trivial_casts)]
mod tests {
use super::*;
use quickcheck::*;
mod vectors {
use super::*;
use std::fs::File;
use std::io::{BufRead, BufReader};
use itertools::Itertools;
use flate2::read::GzDecoder;
macro_rules! mk_test {
($id:ident, $op:expr, $val:expr) => {
mk_test!($id, $op, $val, 0);
};
($id:ident, $op:expr, $val:expr, $y:expr) => {
#[test]
fn $id() {
let results = (0..256).cartesian_product($y..256).map(|(i, j)| {
let (i, j) = (Gf256::from_byte(i as u8), Gf256::from_byte(j as u8));
(i.to_byte(), j.to_byte(), $val(i, j).to_byte())
});
let ref_path = format!("tests/fixtures/gf256/gf256_{}.txt.gz", stringify!($id));
let reference = BufReader::new(GzDecoder::new(File::open(ref_path).unwrap()).unwrap());
for ((i, j, k), line) in results.zip(reference.lines()) {
let left = format!("{} {} {} = {}", i, $op, j, k);
let right = line.unwrap();
assert_eq!(left, right);
}
}
}
}
mk_test!(add, "+", |i: Gf256, j: Gf256| i + j);
mk_test!(sub, "-", |i: Gf256, j: Gf256| i - j);
mk_test!(mul, "*", |i: Gf256, j: Gf256| i * j);
mk_test!(div, "/", |i: Gf256, j: Gf256| i.div(j), 1);
mk_test!(pow, "^", |i: Gf256, j: Gf256| i.pow(j.to_byte()));
}
impl Arbitrary for Gf256 {
fn arbitrary<G: Gen>(gen: &mut G) -> Gf256 {
Gf256::from_byte(u8::arbitrary(gen))
}
}
mod addition {
use super::*;
quickcheck! {
fn law_associativity(a: Gf256, b: Gf256, c: Gf256) -> bool {
(a + b) + c == a + (b + c)
}
fn law_commutativity(a: Gf256, b: Gf256) -> bool {
a + b == b + a
}
fn law_distributivity(a: Gf256, b: Gf256, c: Gf256) -> bool {
a * (b + c) == a * b + a * c
}
fn law_identity(a: Gf256) -> bool {
a + Gf256::zero() == a && Gf256::zero() + a == a
}
fn law_inverses(a: Gf256) -> bool {
a + (-a) == Gf256::zero() && (-a) + a == Gf256::zero()
}
}
}
mod multiplication {
use super::*;
quickcheck! {
fn law_associativity(a: Gf256, b: Gf256, c: Gf256) -> bool {
(a * b) * c == a * (b * c)
}
fn law_commutativity(a: Gf256, b: Gf256) -> bool {
a * b == b * a
}
fn law_distributivity(a: Gf256, b: Gf256, c: Gf256) -> bool {
(a + b) * c == a * c + b * c
}
fn law_identity(a: Gf256) -> bool {
a * Gf256::one() == a && Gf256::one() * a == a
}
fn law_inverses(a: Gf256) -> TestResult {
if a == Gf256::zero() {
return TestResult::discard();
}
let left = a * (Gf256::one() / a) == Gf256::one();
let right = (Gf256::one() / a) * a == Gf256::one();
TestResult::from_bool(left && right)
}
}
}
}

View File

@ -1,40 +0,0 @@
use gf256::Gf256;
use std::io;
use std::io::prelude::*;
/// evaluates a polynomial at x=1, 2, 3, ... n (inclusive)
pub fn encode<W: Write>(src: &[u8], n: u8, w: &mut W) -> io::Result<()> {
for raw_x in 1..((n as u16) + 1) {
let x = Gf256::from_byte(raw_x as u8);
let mut fac = Gf256::one();
let mut acc = Gf256::zero();
for &coeff in src.iter() {
acc = acc + fac * Gf256::from_byte(coeff);
fac = fac * x;
}
try!(w.write(&[acc.to_byte()]));
}
Ok(())
}
/// evaluates an interpolated polynomial at `Gf256::zero()` where
/// the polynomial is determined using Lagrangian interpolation
/// based on the given x/y coordinates `src`.
pub fn lagrange_interpolate(src: &[(u8, u8)]) -> u8 {
let mut sum = Gf256::zero();
for (i, &(raw_xi, raw_yi)) in src.iter().enumerate() {
let xi = Gf256::from_byte(raw_xi);
let yi = Gf256::from_byte(raw_yi);
let mut prod = Gf256::one();
for (j, &(raw_xj, _)) in src.iter().enumerate() {
if i != j {
let xj = Gf256::from_byte(raw_xj);
let delta = xi - xj;
assert!(delta.poly != 0, "Duplicate shares");
prod = prod * xj / delta;
}
}
sum = sum + prod * yi;
}
sum.to_byte()
}

124
src/lagrange.rs Normal file
View File

@ -0,0 +1,124 @@
use gf256::Gf256;
use poly::Poly;
/// Evaluates an interpolated polynomial at `Gf256::zero()` where
/// the polynomial is determined using Lagrangian interpolation
/// based on the given `points` in the G(2^8) Galois field.
pub(crate) fn interpolate_at(points: &[(u8, u8)]) -> u8 {
let mut sum = Gf256::zero();
for (i, &(raw_xi, raw_yi)) in points.iter().enumerate() {
let xi = Gf256::from_byte(raw_xi);
let yi = Gf256::from_byte(raw_yi);
let mut prod = Gf256::one();
for (j, &(raw_xj, _)) in points.iter().enumerate() {
if i != j {
let xj = Gf256::from_byte(raw_xj);
let delta = xi - xj;
assert_ne!(delta.poly, 0, "Duplicate shares");
prod = prod * xj / delta;
}
}
sum = sum + prod * yi;
}
sum.to_byte()
}
/// Computeds the coefficient of the Lagrange polynomial interpolated
/// from the given `points`, in the G(2^8) Galois field.
pub(crate) fn interpolate(points: &[(Gf256, Gf256)]) -> Poly {
let len = points.len();
let mut poly = vec![Gf256::zero(); len];
for &(x, y) in points {
let mut coeffs = vec![Gf256::zero(); len];
coeffs[0] = y;
let mut prod = Gf256::one();
for &(x1, _) in points {
if x != x1 {
prod = prod * (x - x1);
let mut prec = Gf256::zero();
coeffs = coeffs
.into_iter()
.map(|coeff| {
let new_coeff = coeff * (-x1) + prec;
prec = coeff;
new_coeff
})
.collect();
}
}
poly = poly.iter()
.zip(coeffs.iter())
.map(|(&old_coeff, &add)| old_coeff + add / prod)
.collect();
}
Poly::new(poly)
}
#[cfg(test)]
#[allow(trivial_casts)]
mod tests {
use std;
use super::*;
use gf256::*;
use quickcheck::*;
quickcheck! {
fn evaluate_at_works(ys: Vec<u8>) -> TestResult {
if ys.is_empty() || ys.len() > std::u8::MAX as usize {
return TestResult::discard();
}
let points = ys.iter().enumerate().map(|(x, y)| (x as u8, *y)).collect::<Vec<_>>();
let equals = interpolate_at(points.as_slice()) == ys[0];
TestResult::from_bool(equals)
}
fn interpolate_evaluate_at_works(ys: Vec<Gf256>) -> TestResult {
if ys.is_empty() || ys.len() > std::u8::MAX as usize {
return TestResult::discard();
}
let points = ys.into_iter().enumerate().map(|(x, y)| (gf256!(x as u8), y)).collect::<Vec<_>>();
let poly = interpolate(&points);
for (x, y) in points {
if poly.evaluate_at(x) != y {
return TestResult::failed();
}
}
TestResult::passed()
}
fn interpolate_evaluate_at_0_eq_evaluate_at(ys: Vec<u8>) -> TestResult {
if ys.len() > std::u8::MAX as usize {
return TestResult::discard();
}
let points = ys.into_iter().enumerate().map(|(x, y)| (x as u8, y)).collect::<Vec<_>>();
let elems = points
.iter()
.map(|&(x, y)| (gf256!(x), gf256!(y)))
.collect::<Vec<_>>();
let poly = interpolate(&elems);
let equals = poly.evaluate_at(Gf256::zero()).to_byte() == interpolate_at(points.as_slice());
TestResult::from_bool(equals)
}
}
}

View File

@ -1,37 +1,42 @@
//! `RustySecrets` implements Shamir's secret sharing in Rust. It provides the possibility to sign shares.
#![deny(
missing_docs,
missing_debug_implementations, missing_copy_implementations,
trivial_casts, trivial_numeric_casts,
unsafe_code, unstable_features,
unused_import_braces, unused_qualifications
)]
#![deny(missing_docs, missing_debug_implementations, missing_copy_implementations, trivial_casts,
trivial_numeric_casts, unsafe_code, unstable_features, unused_import_braces,
unused_qualifications)]
#![cfg_attr(feature = "cargo-clippy", allow(doc_markdown))]
// `error_chain!` can recurse deeply
#![recursion_limit = "1024"]
extern crate protobuf;
extern crate rustc_serialize as serialize;
extern crate rand;
#[macro_use]
extern crate error_chain;
extern crate base64;
extern crate merkle_sigs;
extern crate protobuf;
extern crate rand;
extern crate ring;
use ring::digest::{Algorithm, SHA512};
#[allow(non_upper_case_globals)]
static digest: &'static Algorithm = &SHA512;
mod custom_error;
#[macro_use]
mod gf256;
mod interpolation;
#[allow(unused_qualifications)]
mod secret;
#[allow(unused_qualifications)]
mod share_data;
mod share_format;
mod validation;
pub use custom_error::RustyError;
mod share;
mod poly;
mod lagrange;
mod vol_hash;
pub mod errors;
pub mod sss;
pub mod wrapped_secrets;
pub mod proto;
#[cfg(feature = "dss")]
pub mod dss;
#[cfg(test)]
mod tests;
extern crate itertools;
#[cfg(test)]
extern crate flate2;
#[cfg(test)]
#[macro_use]
extern crate quickcheck;

29
src/poly.rs Normal file
View File

@ -0,0 +1,29 @@
use gf256::Gf256;
static MAX_COEFFS: usize = 256;
pub(crate) struct Poly {
pub coeffs: Vec<Gf256>,
}
impl Poly {
pub fn new(coeffs: Vec<Gf256>) -> Self {
Self { coeffs }
}
pub fn evaluate_at_zero(&self) -> Gf256 {
self.coeffs[0]
}
pub fn evaluate_at(&self, x: Gf256) -> Gf256 {
assert!(self.coeffs.len() < MAX_COEFFS);
let mut result = Gf256::zero();
for (i, c) in self.coeffs.iter().enumerate() {
result = result + *c * x.pow(i as u8);
}
result
}
}

253
src/proto/dss/metadata.rs Normal file
View File

@ -0,0 +1,253 @@
// This file is generated. Do not edit
// @generated
// https://github.com/Manishearth/rust-clippy/issues/702
#![allow(unknown_lints)]
#![allow(clippy)]
#![cfg_attr(rustfmt, rustfmt_skip)]
#![allow(box_pointers)]
#![allow(dead_code)]
#![allow(missing_docs)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(non_upper_case_globals)]
#![allow(trivial_casts)]
#![allow(unsafe_code)]
#![allow(unused_imports)]
#![allow(unused_results)]
use protobuf::Message as Message_imported_for_functions;
use protobuf::ProtobufEnum as ProtobufEnum_imported_for_functions;
#[derive(PartialEq, Clone, Default)]
pub struct MetaDataProto {
// message fields
pub tags: ::std::collections::HashMap<::std::string::String, ::std::string::String>,
// special fields
unknown_fields: ::protobuf::UnknownFields,
cached_size: ::protobuf::CachedSize,
}
// see codegen.rs for the explanation why impl Sync explicitly
unsafe impl ::std::marker::Sync for MetaDataProto {}
impl MetaDataProto {
pub fn new() -> MetaDataProto {
::std::default::Default::default()
}
pub fn default_instance() -> &'static MetaDataProto {
static mut instance: ::protobuf::lazy::Lazy<MetaDataProto> = ::protobuf::lazy::Lazy {
lock: ::protobuf::lazy::ONCE_INIT,
ptr: 0 as *const MetaDataProto,
};
unsafe { instance.get(MetaDataProto::new) }
}
// repeated .dss.MetaDataProto.TagsEntry tags = 1;
pub fn clear_tags(&mut self) {
self.tags.clear();
}
// Param is passed by value, moved
pub fn set_tags(
&mut self,
v: ::std::collections::HashMap<::std::string::String, ::std::string::String>,
) {
self.tags = v;
}
// Mutable pointer to the field.
pub fn mut_tags(
&mut self,
) -> &mut ::std::collections::HashMap<::std::string::String, ::std::string::String> {
&mut self.tags
}
// Take field
pub fn take_tags(
&mut self,
) -> ::std::collections::HashMap<::std::string::String, ::std::string::String> {
::std::mem::replace(&mut self.tags, ::std::collections::HashMap::new())
}
pub fn get_tags(
&self,
) -> &::std::collections::HashMap<::std::string::String, ::std::string::String> {
&self.tags
}
fn get_tags_for_reflect(
&self,
) -> &::std::collections::HashMap<::std::string::String, ::std::string::String> {
&self.tags
}
fn mut_tags_for_reflect(
&mut self,
) -> &mut ::std::collections::HashMap<::std::string::String, ::std::string::String> {
&mut self.tags
}
}
impl ::protobuf::Message for MetaDataProto {
fn is_initialized(&self) -> bool {
true
}
fn merge_from(
&mut self,
is: &mut ::protobuf::CodedInputStream,
) -> ::protobuf::ProtobufResult<()> {
while !is.eof()? {
let (field_number, wire_type) = is.read_tag_unpack()?;
match field_number {
1 => {
::protobuf::rt::read_map_into::<
::protobuf::types::ProtobufTypeString,
::protobuf::types::ProtobufTypeString,
>(wire_type, is, &mut self.tags)?;
}
_ => {
::protobuf::rt::read_unknown_or_skip_group(
field_number,
wire_type,
is,
self.mut_unknown_fields(),
)?;
}
};
}
::std::result::Result::Ok(())
}
// Compute sizes of nested messages
#[allow(unused_variables)]
fn compute_size(&self) -> u32 {
let mut my_size = 0;
my_size += ::protobuf::rt::compute_map_size::<
::protobuf::types::ProtobufTypeString,
::protobuf::types::ProtobufTypeString,
>(1, &self.tags);
my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
self.cached_size.set(my_size);
my_size
}
fn write_to_with_cached_sizes(
&self,
os: &mut ::protobuf::CodedOutputStream,
) -> ::protobuf::ProtobufResult<()> {
::protobuf::rt::write_map_with_cached_sizes::<
::protobuf::types::ProtobufTypeString,
::protobuf::types::ProtobufTypeString,
>(1, &self.tags, os)?;
os.write_unknown_fields(self.get_unknown_fields())?;
::std::result::Result::Ok(())
}
fn get_cached_size(&self) -> u32 {
self.cached_size.get()
}
fn get_unknown_fields(&self) -> &::protobuf::UnknownFields {
&self.unknown_fields
}
fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields {
&mut self.unknown_fields
}
fn as_any(&self) -> &::std::any::Any {
self as &::std::any::Any
}
fn as_any_mut(&mut self) -> &mut ::std::any::Any {
self as &mut ::std::any::Any
}
fn into_any(self: Box<Self>) -> ::std::boxed::Box<::std::any::Any> {
self
}
fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor {
::protobuf::MessageStatic::descriptor_static(None::<Self>)
}
}
impl ::protobuf::MessageStatic for MetaDataProto {
fn new() -> MetaDataProto {
MetaDataProto::new()
}
fn descriptor_static(
_: ::std::option::Option<MetaDataProto>,
) -> &'static ::protobuf::reflect::MessageDescriptor {
static mut descriptor: ::protobuf::lazy::Lazy<::protobuf::reflect::MessageDescriptor> =
::protobuf::lazy::Lazy {
lock: ::protobuf::lazy::ONCE_INIT,
ptr: 0 as *const ::protobuf::reflect::MessageDescriptor,
};
unsafe {
descriptor.get(|| {
let mut fields = ::std::vec::Vec::new();
fields.push(::protobuf::reflect::accessor::make_map_accessor::<_, ::protobuf::types::ProtobufTypeString, ::protobuf::types::ProtobufTypeString>(
"tags",
MetaDataProto::get_tags_for_reflect,
MetaDataProto::mut_tags_for_reflect,
));
::protobuf::reflect::MessageDescriptor::new::<MetaDataProto>(
"MetaDataProto",
fields,
file_descriptor_proto()
)
})
}
}
}
impl ::protobuf::Clear for MetaDataProto {
fn clear(&mut self) {
self.clear_tags();
self.unknown_fields.clear();
}
}
impl ::std::fmt::Debug for MetaDataProto {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
::protobuf::text_format::fmt(self, f)
}
}
impl ::protobuf::reflect::ProtobufValue for MetaDataProto {
fn as_ref(&self) -> ::protobuf::reflect::ProtobufValueRef {
::protobuf::reflect::ProtobufValueRef::Message(self)
}
}
static file_descriptor_proto_data: &'static [u8] = b"\
\n\x12dss/metadata.proto\x12\x03dss\"z\n\rMetaDataProto\x120\n\x04tags\
\x18\x01\x20\x03(\x0b2\x1c.dss.MetaDataProto.TagsEntryR\x04tags\x1a7\n\t\
TagsEntry\x12\x10\n\x03key\x18\x01\x20\x01(\tR\x03key\x12\x14\n\x05value\
\x18\x02\x20\x01(\tR\x05value:\x028\x01Jz\n\x06\x12\x04\0\0\x06\x01\n\
\x08\n\x01\x0c\x12\x03\0\0\x12\n\x08\n\x01\x02\x12\x03\x02\x08\x0b\n\n\n\
\x02\x04\0\x12\x04\x04\0\x06\x01\n\n\n\x03\x04\0\x01\x12\x03\x04\x08\x15\
\n\x0b\n\x04\x04\0\x02\0\x12\x03\x05\x02\x1f\n\r\n\x05\x04\0\x02\0\x04\
\x12\x04\x05\x02\x04\x17\n\x0c\n\x05\x04\0\x02\0\x06\x12\x03\x05\x02\x15\
\n\x0c\n\x05\x04\0\x02\0\x01\x12\x03\x05\x16\x1a\n\x0c\n\x05\x04\0\x02\0\
\x03\x12\x03\x05\x1d\x1eb\x06proto3\
";
static mut file_descriptor_proto_lazy: ::protobuf::lazy::Lazy<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::lazy::Lazy {
lock: ::protobuf::lazy::ONCE_INIT,
ptr: 0 as *const ::protobuf::descriptor::FileDescriptorProto,
};
fn parse_descriptor_proto() -> ::protobuf::descriptor::FileDescriptorProto {
::protobuf::parse_from_bytes(file_descriptor_proto_data).unwrap()
}
pub fn file_descriptor_proto() -> &'static ::protobuf::descriptor::FileDescriptorProto {
unsafe { file_descriptor_proto_lazy.get(|| parse_descriptor_proto()) }
}

13
src/proto/dss/mod.rs Normal file
View File

@ -0,0 +1,13 @@
#[allow(unused_qualifications, deprecated, missing_docs)]
mod secret;
pub use self::secret::SecretProto;
#[allow(unused_qualifications, deprecated, missing_docs)]
mod share;
pub use self::share::ShareProto;
#[allow(unused_qualifications, deprecated, missing_docs)]
mod metadata;
pub use self::metadata::MetaDataProto;
pub use super::version;

369
src/proto/dss/secret.rs Normal file
View File

@ -0,0 +1,369 @@
// This file is generated. Do not edit
// @generated
// https://github.com/Manishearth/rust-clippy/issues/702
#![allow(unknown_lints)]
#![allow(clippy)]
#![cfg_attr(rustfmt, rustfmt_skip)]
#![allow(box_pointers)]
#![allow(dead_code)]
#![allow(missing_docs)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(non_upper_case_globals)]
#![allow(trivial_casts)]
#![allow(unsafe_code)]
#![allow(unused_imports)]
#![allow(unused_results)]
use protobuf::Message as Message_imported_for_functions;
use protobuf::ProtobufEnum as ProtobufEnum_imported_for_functions;
#[derive(PartialEq, Clone, Default)]
pub struct SecretProto {
// message fields
pub version: super::version::VersionProto,
pub secret: ::std::vec::Vec<u8>,
pub meta_data: ::protobuf::SingularPtrField<super::metadata::MetaDataProto>,
// special fields
unknown_fields: ::protobuf::UnknownFields,
cached_size: ::protobuf::CachedSize,
}
// see codegen.rs for the explanation why impl Sync explicitly
unsafe impl ::std::marker::Sync for SecretProto {}
impl SecretProto {
pub fn new() -> SecretProto {
::std::default::Default::default()
}
pub fn default_instance() -> &'static SecretProto {
static mut instance: ::protobuf::lazy::Lazy<SecretProto> = ::protobuf::lazy::Lazy {
lock: ::protobuf::lazy::ONCE_INIT,
ptr: 0 as *const SecretProto,
};
unsafe { instance.get(SecretProto::new) }
}
// .VersionProto version = 1;
pub fn clear_version(&mut self) {
self.version = super::version::VersionProto::INITIAL_RELEASE;
}
// Param is passed by value, moved
pub fn set_version(&mut self, v: super::version::VersionProto) {
self.version = v;
}
pub fn get_version(&self) -> super::version::VersionProto {
self.version
}
fn get_version_for_reflect(&self) -> &super::version::VersionProto {
&self.version
}
fn mut_version_for_reflect(&mut self) -> &mut super::version::VersionProto {
&mut self.version
}
// bytes secret = 2;
pub fn clear_secret(&mut self) {
self.secret.clear();
}
// Param is passed by value, moved
pub fn set_secret(&mut self, v: ::std::vec::Vec<u8>) {
self.secret = v;
}
// Mutable pointer to the field.
// If field is not initialized, it is initialized with default value first.
pub fn mut_secret(&mut self) -> &mut ::std::vec::Vec<u8> {
&mut self.secret
}
// Take field
pub fn take_secret(&mut self) -> ::std::vec::Vec<u8> {
::std::mem::replace(&mut self.secret, ::std::vec::Vec::new())
}
pub fn get_secret(&self) -> &[u8] {
&self.secret
}
fn get_secret_for_reflect(&self) -> &::std::vec::Vec<u8> {
&self.secret
}
fn mut_secret_for_reflect(&mut self) -> &mut ::std::vec::Vec<u8> {
&mut self.secret
}
// .dss.MetaDataProto meta_data = 3;
pub fn clear_meta_data(&mut self) {
self.meta_data.clear();
}
pub fn has_meta_data(&self) -> bool {
self.meta_data.is_some()
}
// Param is passed by value, moved
pub fn set_meta_data(&mut self, v: super::metadata::MetaDataProto) {
self.meta_data = ::protobuf::SingularPtrField::some(v);
}
// Mutable pointer to the field.
// If field is not initialized, it is initialized with default value first.
pub fn mut_meta_data(&mut self) -> &mut super::metadata::MetaDataProto {
if self.meta_data.is_none() {
self.meta_data.set_default();
}
self.meta_data.as_mut().unwrap()
}
// Take field
pub fn take_meta_data(&mut self) -> super::metadata::MetaDataProto {
self.meta_data.take().unwrap_or_else(|| {
super::metadata::MetaDataProto::new()
})
}
pub fn get_meta_data(&self) -> &super::metadata::MetaDataProto {
self.meta_data.as_ref().unwrap_or_else(|| {
super::metadata::MetaDataProto::default_instance()
})
}
fn get_meta_data_for_reflect(
&self,
) -> &::protobuf::SingularPtrField<super::metadata::MetaDataProto> {
&self.meta_data
}
fn mut_meta_data_for_reflect(
&mut self,
) -> &mut ::protobuf::SingularPtrField<super::metadata::MetaDataProto> {
&mut self.meta_data
}
}
impl ::protobuf::Message for SecretProto {
fn is_initialized(&self) -> bool {
for v in &self.meta_data {
if !v.is_initialized() {
return false;
}
}
true
}
fn merge_from(
&mut self,
is: &mut ::protobuf::CodedInputStream,
) -> ::protobuf::ProtobufResult<()> {
while !is.eof()? {
let (field_number, wire_type) = is.read_tag_unpack()?;
match field_number {
1 => {
if wire_type != ::protobuf::wire_format::WireTypeVarint {
return ::std::result::Result::Err(
::protobuf::rt::unexpected_wire_type(wire_type),
);
}
let tmp = is.read_enum()?;
self.version = tmp;
}
2 => {
::protobuf::rt::read_singular_proto3_bytes_into(
wire_type,
is,
&mut self.secret,
)?;
}
3 => {
::protobuf::rt::read_singular_message_into(wire_type, is, &mut self.meta_data)?;
}
_ => {
::protobuf::rt::read_unknown_or_skip_group(
field_number,
wire_type,
is,
self.mut_unknown_fields(),
)?;
}
};
}
::std::result::Result::Ok(())
}
// Compute sizes of nested messages
#[allow(unused_variables)]
fn compute_size(&self) -> u32 {
let mut my_size = 0;
if self.version != super::version::VersionProto::INITIAL_RELEASE {
my_size += ::protobuf::rt::enum_size(1, self.version);
}
if !self.secret.is_empty() {
my_size += ::protobuf::rt::bytes_size(2, &self.secret);
}
if let Some(ref v) = self.meta_data.as_ref() {
let len = v.compute_size();
my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len;
}
my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
self.cached_size.set(my_size);
my_size
}
fn write_to_with_cached_sizes(
&self,
os: &mut ::protobuf::CodedOutputStream,
) -> ::protobuf::ProtobufResult<()> {
if self.version != super::version::VersionProto::INITIAL_RELEASE {
os.write_enum(1, self.version.value())?;
}
if !self.secret.is_empty() {
os.write_bytes(2, &self.secret)?;
}
if let Some(ref v) = self.meta_data.as_ref() {
os.write_tag(
3,
::protobuf::wire_format::WireTypeLengthDelimited,
)?;
os.write_raw_varint32(v.get_cached_size())?;
v.write_to_with_cached_sizes(os)?;
}
os.write_unknown_fields(self.get_unknown_fields())?;
::std::result::Result::Ok(())
}
fn get_cached_size(&self) -> u32 {
self.cached_size.get()
}
fn get_unknown_fields(&self) -> &::protobuf::UnknownFields {
&self.unknown_fields
}
fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields {
&mut self.unknown_fields
}
fn as_any(&self) -> &::std::any::Any {
self as &::std::any::Any
}
fn as_any_mut(&mut self) -> &mut ::std::any::Any {
self as &mut ::std::any::Any
}
fn into_any(self: Box<Self>) -> ::std::boxed::Box<::std::any::Any> {
self
}
fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor {
::protobuf::MessageStatic::descriptor_static(None::<Self>)
}
}
impl ::protobuf::MessageStatic for SecretProto {
fn new() -> SecretProto {
SecretProto::new()
}
fn descriptor_static(
_: ::std::option::Option<SecretProto>,
) -> &'static ::protobuf::reflect::MessageDescriptor {
static mut descriptor: ::protobuf::lazy::Lazy<::protobuf::reflect::MessageDescriptor> =
::protobuf::lazy::Lazy {
lock: ::protobuf::lazy::ONCE_INIT,
ptr: 0 as *const ::protobuf::reflect::MessageDescriptor,
};
unsafe {
descriptor.get(|| {
let mut fields = ::std::vec::Vec::new();
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeEnum<super::version::VersionProto>>(
"version",
SecretProto::get_version_for_reflect,
SecretProto::mut_version_for_reflect,
));
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBytes>(
"secret",
SecretProto::get_secret_for_reflect,
SecretProto::mut_secret_for_reflect,
));
fields.push(::protobuf::reflect::accessor::make_singular_ptr_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage<super::metadata::MetaDataProto>>(
"meta_data",
SecretProto::get_meta_data_for_reflect,
SecretProto::mut_meta_data_for_reflect,
));
::protobuf::reflect::MessageDescriptor::new::<SecretProto>(
"SecretProto",
fields,
file_descriptor_proto()
)
})
}
}
}
impl ::protobuf::Clear for SecretProto {
fn clear(&mut self) {
self.clear_version();
self.clear_secret();
self.clear_meta_data();
self.unknown_fields.clear();
}
}
impl ::std::fmt::Debug for SecretProto {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
::protobuf::text_format::fmt(self, f)
}
}
impl ::protobuf::reflect::ProtobufValue for SecretProto {
fn as_ref(&self) -> ::protobuf::reflect::ProtobufValueRef {
::protobuf::reflect::ProtobufValueRef::Message(self)
}
}
static file_descriptor_proto_data: &'static [u8] = b"\
\n\x10dss/secret.proto\x1a\rversion.proto\x1a\x12dss/metadata.proto\"\
\x7f\n\x0bSecretProto\x12'\n\x07version\x18\x01\x20\x01(\x0e2\r.VersionP\
rotoR\x07version\x12\x16\n\x06secret\x18\x02\x20\x01(\x0cR\x06secret\x12\
/\n\tmeta_data\x18\x03\x20\x01(\x0b2\x12.dss.MetaDataProtoR\x08metaDataJ\
\x92\x02\n\x06\x12\x04\0\0\t\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\t\n\
\x02\x03\0\x12\x03\x02\x07\x16\n\t\n\x02\x03\x01\x12\x03\x03\x07\x1b\n\n\
\n\x02\x04\0\x12\x04\x05\0\t\x01\n\n\n\x03\x04\0\x01\x12\x03\x05\x08\x13\
\n\x0b\n\x04\x04\0\x02\0\x12\x03\x06\x08!\n\r\n\x05\x04\0\x02\0\x04\x12\
\x04\x06\x08\x05\x15\n\x0c\n\x05\x04\0\x02\0\x06\x12\x03\x06\x08\x14\n\
\x0c\n\x05\x04\0\x02\0\x01\x12\x03\x06\x15\x1c\n\x0c\n\x05\x04\0\x02\0\
\x03\x12\x03\x06\x1f\x20\n\x0b\n\x04\x04\0\x02\x01\x12\x03\x07\x08\x19\n\
\r\n\x05\x04\0\x02\x01\x04\x12\x04\x07\x08\x06!\n\x0c\n\x05\x04\0\x02\
\x01\x05\x12\x03\x07\x08\r\n\x0c\n\x05\x04\0\x02\x01\x01\x12\x03\x07\x0e\
\x14\n\x0c\n\x05\x04\0\x02\x01\x03\x12\x03\x07\x17\x18\n\x0b\n\x04\x04\0\
\x02\x02\x12\x03\x08\x08(\n\r\n\x05\x04\0\x02\x02\x04\x12\x04\x08\x08\
\x07\x19\n\x0c\n\x05\x04\0\x02\x02\x06\x12\x03\x08\x08\x19\n\x0c\n\x05\
\x04\0\x02\x02\x01\x12\x03\x08\x1a#\n\x0c\n\x05\x04\0\x02\x02\x03\x12\
\x03\x08&'b\x06proto3\
";
static mut file_descriptor_proto_lazy: ::protobuf::lazy::Lazy<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::lazy::Lazy {
lock: ::protobuf::lazy::ONCE_INIT,
ptr: 0 as *const ::protobuf::descriptor::FileDescriptorProto,
};
fn parse_descriptor_proto() -> ::protobuf::descriptor::FileDescriptorProto {
::protobuf::parse_from_bytes(file_descriptor_proto_data).unwrap()
}
pub fn file_descriptor_proto() -> &'static ::protobuf::descriptor::FileDescriptorProto {
unsafe { file_descriptor_proto_lazy.get(|| parse_descriptor_proto()) }
}

492
src/proto/dss/share.rs Normal file
View File

@ -0,0 +1,492 @@
// This file is generated. Do not edit
// @generated
// https://github.com/Manishearth/rust-clippy/issues/702
#![allow(unknown_lints)]
#![allow(clippy)]
#![cfg_attr(rustfmt, rustfmt_skip)]
#![allow(box_pointers)]
#![allow(dead_code)]
#![allow(missing_docs)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(non_upper_case_globals)]
#![allow(trivial_casts)]
#![allow(unsafe_code)]
#![allow(unused_imports)]
#![allow(unused_results)]
use protobuf::Message as Message_imported_for_functions;
use protobuf::ProtobufEnum as ProtobufEnum_imported_for_functions;
#[derive(PartialEq,Clone,Default)]
pub struct ShareProto {
// message fields
pub id: u32,
pub threshold: u32,
pub shares_count: u32,
pub data: ::std::vec::Vec<u8>,
pub hash: ::std::vec::Vec<u8>,
pub meta_data: ::protobuf::SingularPtrField<super::metadata::MetaDataProto>,
// special fields
unknown_fields: ::protobuf::UnknownFields,
cached_size: ::protobuf::CachedSize,
}
// see codegen.rs for the explanation why impl Sync explicitly
unsafe impl ::std::marker::Sync for ShareProto {}
impl ShareProto {
pub fn new() -> ShareProto {
::std::default::Default::default()
}
pub fn default_instance() -> &'static ShareProto {
static mut instance: ::protobuf::lazy::Lazy<ShareProto> = ::protobuf::lazy::Lazy {
lock: ::protobuf::lazy::ONCE_INIT,
ptr: 0 as *const ShareProto,
};
unsafe {
instance.get(ShareProto::new)
}
}
// uint32 id = 1;
pub fn clear_id(&mut self) {
self.id = 0;
}
// Param is passed by value, moved
pub fn set_id(&mut self, v: u32) {
self.id = v;
}
pub fn get_id(&self) -> u32 {
self.id
}
fn get_id_for_reflect(&self) -> &u32 {
&self.id
}
fn mut_id_for_reflect(&mut self) -> &mut u32 {
&mut self.id
}
// uint32 threshold = 2;
pub fn clear_threshold(&mut self) {
self.threshold = 0;
}
// Param is passed by value, moved
pub fn set_threshold(&mut self, v: u32) {
self.threshold = v;
}
pub fn get_threshold(&self) -> u32 {
self.threshold
}
fn get_threshold_for_reflect(&self) -> &u32 {
&self.threshold
}
fn mut_threshold_for_reflect(&mut self) -> &mut u32 {
&mut self.threshold
}
// uint32 shares_count = 3;
pub fn clear_shares_count(&mut self) {
self.shares_count = 0;
}
// Param is passed by value, moved
pub fn set_shares_count(&mut self, v: u32) {
self.shares_count = v;
}
pub fn get_shares_count(&self) -> u32 {
self.shares_count
}
fn get_shares_count_for_reflect(&self) -> &u32 {
&self.shares_count
}
fn mut_shares_count_for_reflect(&mut self) -> &mut u32 {
&mut self.shares_count
}
// bytes data = 4;
pub fn clear_data(&mut self) {
self.data.clear();
}
// Param is passed by value, moved
pub fn set_data(&mut self, v: ::std::vec::Vec<u8>) {
self.data = v;
}
// Mutable pointer to the field.
// If field is not initialized, it is initialized with default value first.
pub fn mut_data(&mut self) -> &mut ::std::vec::Vec<u8> {
&mut self.data
}
// Take field
pub fn take_data(&mut self) -> ::std::vec::Vec<u8> {
::std::mem::replace(&mut self.data, ::std::vec::Vec::new())
}
pub fn get_data(&self) -> &[u8] {
&self.data
}
fn get_data_for_reflect(&self) -> &::std::vec::Vec<u8> {
&self.data
}
fn mut_data_for_reflect(&mut self) -> &mut ::std::vec::Vec<u8> {
&mut self.data
}
// bytes hash = 5;
pub fn clear_hash(&mut self) {
self.hash.clear();
}
// Param is passed by value, moved
pub fn set_hash(&mut self, v: ::std::vec::Vec<u8>) {
self.hash = v;
}
// Mutable pointer to the field.
// If field is not initialized, it is initialized with default value first.
pub fn mut_hash(&mut self) -> &mut ::std::vec::Vec<u8> {
&mut self.hash
}
// Take field
pub fn take_hash(&mut self) -> ::std::vec::Vec<u8> {
::std::mem::replace(&mut self.hash, ::std::vec::Vec::new())
}
pub fn get_hash(&self) -> &[u8] {
&self.hash
}
fn get_hash_for_reflect(&self) -> &::std::vec::Vec<u8> {
&self.hash
}
fn mut_hash_for_reflect(&mut self) -> &mut ::std::vec::Vec<u8> {
&mut self.hash
}
// .dss.MetaDataProto meta_data = 6;
pub fn clear_meta_data(&mut self) {
self.meta_data.clear();
}
pub fn has_meta_data(&self) -> bool {
self.meta_data.is_some()
}
// Param is passed by value, moved
pub fn set_meta_data(&mut self, v: super::metadata::MetaDataProto) {
self.meta_data = ::protobuf::SingularPtrField::some(v);
}
// Mutable pointer to the field.
// If field is not initialized, it is initialized with default value first.
pub fn mut_meta_data(&mut self) -> &mut super::metadata::MetaDataProto {
if self.meta_data.is_none() {
self.meta_data.set_default();
}
self.meta_data.as_mut().unwrap()
}
// Take field
pub fn take_meta_data(&mut self) -> super::metadata::MetaDataProto {
self.meta_data.take().unwrap_or_else(|| super::metadata::MetaDataProto::new())
}
pub fn get_meta_data(&self) -> &super::metadata::MetaDataProto {
self.meta_data.as_ref().unwrap_or_else(|| super::metadata::MetaDataProto::default_instance())
}
fn get_meta_data_for_reflect(&self) -> &::protobuf::SingularPtrField<super::metadata::MetaDataProto> {
&self.meta_data
}
fn mut_meta_data_for_reflect(&mut self) -> &mut ::protobuf::SingularPtrField<super::metadata::MetaDataProto> {
&mut self.meta_data
}
}
impl ::protobuf::Message for ShareProto {
fn is_initialized(&self) -> bool {
for v in &self.meta_data {
if !v.is_initialized() {
return false;
}
};
true
}
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream) -> ::protobuf::ProtobufResult<()> {
while !is.eof()? {
let (field_number, wire_type) = is.read_tag_unpack()?;
match field_number {
1 => {
if wire_type != ::protobuf::wire_format::WireTypeVarint {
return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
}
let tmp = is.read_uint32()?;
self.id = tmp;
},
2 => {
if wire_type != ::protobuf::wire_format::WireTypeVarint {
return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
}
let tmp = is.read_uint32()?;
self.threshold = tmp;
},
3 => {
if wire_type != ::protobuf::wire_format::WireTypeVarint {
return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
}
let tmp = is.read_uint32()?;
self.shares_count = tmp;
},
4 => {
::protobuf::rt::read_singular_proto3_bytes_into(wire_type, is, &mut self.data)?;
},
5 => {
::protobuf::rt::read_singular_proto3_bytes_into(wire_type, is, &mut self.hash)?;
},
6 => {
::protobuf::rt::read_singular_message_into(wire_type, is, &mut self.meta_data)?;
},
_ => {
::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
},
};
}
::std::result::Result::Ok(())
}
// Compute sizes of nested messages
#[allow(unused_variables)]
fn compute_size(&self) -> u32 {
let mut my_size = 0;
if self.id != 0 {
my_size += ::protobuf::rt::value_size(1, self.id, ::protobuf::wire_format::WireTypeVarint);
}
if self.threshold != 0 {
my_size += ::protobuf::rt::value_size(2, self.threshold, ::protobuf::wire_format::WireTypeVarint);
}
if self.shares_count != 0 {
my_size += ::protobuf::rt::value_size(3, self.shares_count, ::protobuf::wire_format::WireTypeVarint);
}
if !self.data.is_empty() {
my_size += ::protobuf::rt::bytes_size(4, &self.data);
}
if !self.hash.is_empty() {
my_size += ::protobuf::rt::bytes_size(5, &self.hash);
}
if let Some(ref v) = self.meta_data.as_ref() {
let len = v.compute_size();
my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len;
}
my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
self.cached_size.set(my_size);
my_size
}
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream) -> ::protobuf::ProtobufResult<()> {
if self.id != 0 {
os.write_uint32(1, self.id)?;
}
if self.threshold != 0 {
os.write_uint32(2, self.threshold)?;
}
if self.shares_count != 0 {
os.write_uint32(3, self.shares_count)?;
}
if !self.data.is_empty() {
os.write_bytes(4, &self.data)?;
}
if !self.hash.is_empty() {
os.write_bytes(5, &self.hash)?;
}
if let Some(ref v) = self.meta_data.as_ref() {
os.write_tag(6, ::protobuf::wire_format::WireTypeLengthDelimited)?;
os.write_raw_varint32(v.get_cached_size())?;
v.write_to_with_cached_sizes(os)?;
}
os.write_unknown_fields(self.get_unknown_fields())?;
::std::result::Result::Ok(())
}
fn get_cached_size(&self) -> u32 {
self.cached_size.get()
}
fn get_unknown_fields(&self) -> &::protobuf::UnknownFields {
&self.unknown_fields
}
fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields {
&mut self.unknown_fields
}
fn as_any(&self) -> &::std::any::Any {
self as &::std::any::Any
}
fn as_any_mut(&mut self) -> &mut ::std::any::Any {
self as &mut ::std::any::Any
}
fn into_any(self: Box<Self>) -> ::std::boxed::Box<::std::any::Any> {
self
}
fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor {
::protobuf::MessageStatic::descriptor_static(None::<Self>)
}
}
impl ::protobuf::MessageStatic for ShareProto {
fn new() -> ShareProto {
ShareProto::new()
}
fn descriptor_static(_: ::std::option::Option<ShareProto>) -> &'static ::protobuf::reflect::MessageDescriptor {
static mut descriptor: ::protobuf::lazy::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::lazy::Lazy {
lock: ::protobuf::lazy::ONCE_INIT,
ptr: 0 as *const ::protobuf::reflect::MessageDescriptor,
};
unsafe {
descriptor.get(|| {
let mut fields = ::std::vec::Vec::new();
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeUint32>(
"id",
ShareProto::get_id_for_reflect,
ShareProto::mut_id_for_reflect,
));
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeUint32>(
"threshold",
ShareProto::get_threshold_for_reflect,
ShareProto::mut_threshold_for_reflect,
));
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeUint32>(
"shares_count",
ShareProto::get_shares_count_for_reflect,
ShareProto::mut_shares_count_for_reflect,
));
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBytes>(
"data",
ShareProto::get_data_for_reflect,
ShareProto::mut_data_for_reflect,
));
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBytes>(
"hash",
ShareProto::get_hash_for_reflect,
ShareProto::mut_hash_for_reflect,
));
fields.push(::protobuf::reflect::accessor::make_singular_ptr_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage<super::metadata::MetaDataProto>>(
"meta_data",
ShareProto::get_meta_data_for_reflect,
ShareProto::mut_meta_data_for_reflect,
));
::protobuf::reflect::MessageDescriptor::new::<ShareProto>(
"ShareProto",
fields,
file_descriptor_proto()
)
})
}
}
}
impl ::protobuf::Clear for ShareProto {
fn clear(&mut self) {
self.clear_id();
self.clear_threshold();
self.clear_shares_count();
self.clear_data();
self.clear_hash();
self.clear_meta_data();
self.unknown_fields.clear();
}
}
impl ::std::fmt::Debug for ShareProto {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
::protobuf::text_format::fmt(self, f)
}
}
impl ::protobuf::reflect::ProtobufValue for ShareProto {
fn as_ref(&self) -> ::protobuf::reflect::ProtobufValueRef {
::protobuf::reflect::ProtobufValueRef::Message(self)
}
}
static file_descriptor_proto_data: &'static [u8] = b"\
\n\x0fdss/share.proto\x12\x03dss\x1a\x12dss/metadata.proto\"\xb6\x01\n\n\
ShareProto\x12\x0e\n\x02id\x18\x01\x20\x01(\rR\x02id\x12\x1c\n\tthreshol\
d\x18\x02\x20\x01(\rR\tthreshold\x12!\n\x0cshares_count\x18\x03\x20\x01(\
\rR\x0bsharesCount\x12\x12\n\x04data\x18\x04\x20\x01(\x0cR\x04data\x12\
\x12\n\x04hash\x18\x05\x20\x01(\x0cR\x04hash\x12/\n\tmeta_data\x18\x06\
\x20\x01(\x0b2\x12.dss.MetaDataProtoR\x08metaDataJ\xe3\x03\n\x06\x12\x04\
\0\0\r\x01\n\x08\n\x01\x0c\x12\x03\0\0\x12\n\x08\n\x01\x02\x12\x03\x02\
\x08\x0b\n\t\n\x02\x03\0\x12\x03\x04\x07\x1b\n\n\n\x02\x04\0\x12\x04\x06\
\0\r\x01\n\n\n\x03\x04\0\x01\x12\x03\x06\x08\x12\n\x0b\n\x04\x04\0\x02\0\
\x12\x03\x07\x02\x10\n\r\n\x05\x04\0\x02\0\x04\x12\x04\x07\x02\x06\x14\n\
\x0c\n\x05\x04\0\x02\0\x05\x12\x03\x07\x02\x08\n\x0c\n\x05\x04\0\x02\0\
\x01\x12\x03\x07\t\x0b\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x07\x0e\x0f\n\
\x0b\n\x04\x04\0\x02\x01\x12\x03\x08\x02\x17\n\r\n\x05\x04\0\x02\x01\x04\
\x12\x04\x08\x02\x07\x10\n\x0c\n\x05\x04\0\x02\x01\x05\x12\x03\x08\x02\
\x08\n\x0c\n\x05\x04\0\x02\x01\x01\x12\x03\x08\t\x12\n\x0c\n\x05\x04\0\
\x02\x01\x03\x12\x03\x08\x15\x16\n\x0b\n\x04\x04\0\x02\x02\x12\x03\t\x02\
\x1a\n\r\n\x05\x04\0\x02\x02\x04\x12\x04\t\x02\x08\x17\n\x0c\n\x05\x04\0\
\x02\x02\x05\x12\x03\t\x02\x08\n\x0c\n\x05\x04\0\x02\x02\x01\x12\x03\t\t\
\x15\n\x0c\n\x05\x04\0\x02\x02\x03\x12\x03\t\x18\x19\n\x0b\n\x04\x04\0\
\x02\x03\x12\x03\n\x02\x11\n\r\n\x05\x04\0\x02\x03\x04\x12\x04\n\x02\t\
\x1a\n\x0c\n\x05\x04\0\x02\x03\x05\x12\x03\n\x02\x07\n\x0c\n\x05\x04\0\
\x02\x03\x01\x12\x03\n\x08\x0c\n\x0c\n\x05\x04\0\x02\x03\x03\x12\x03\n\
\x0f\x10\n\x0b\n\x04\x04\0\x02\x04\x12\x03\x0b\x02\x11\n\r\n\x05\x04\0\
\x02\x04\x04\x12\x04\x0b\x02\n\x11\n\x0c\n\x05\x04\0\x02\x04\x05\x12\x03\
\x0b\x02\x07\n\x0c\n\x05\x04\0\x02\x04\x01\x12\x03\x0b\x08\x0c\n\x0c\n\
\x05\x04\0\x02\x04\x03\x12\x03\x0b\x0f\x10\n\x0b\n\x04\x04\0\x02\x05\x12\
\x03\x0c\x02\"\n\r\n\x05\x04\0\x02\x05\x04\x12\x04\x0c\x02\x0b\x11\n\x0c\
\n\x05\x04\0\x02\x05\x06\x12\x03\x0c\x02\x13\n\x0c\n\x05\x04\0\x02\x05\
\x01\x12\x03\x0c\x14\x1d\n\x0c\n\x05\x04\0\x02\x05\x03\x12\x03\x0c\x20!b\
\x06proto3\
";
static mut file_descriptor_proto_lazy: ::protobuf::lazy::Lazy<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::lazy::Lazy {
lock: ::protobuf::lazy::ONCE_INIT,
ptr: 0 as *const ::protobuf::descriptor::FileDescriptorProto,
};
fn parse_descriptor_proto() -> ::protobuf::descriptor::FileDescriptorProto {
::protobuf::parse_from_bytes(file_descriptor_proto_data).unwrap()
}
pub fn file_descriptor_proto() -> &'static ::protobuf::descriptor::FileDescriptorProto {
unsafe {
file_descriptor_proto_lazy.get(|| {
parse_descriptor_proto()
})
}
}

12
src/proto/mod.rs Normal file
View File

@ -0,0 +1,12 @@
//! Protocol buffer definitions
#[allow(unused_qualifications, deprecated, missing_docs)]
pub mod wrapped;
#[allow(unused_qualifications, deprecated, missing_docs)]
pub mod dss;
#[doc(hidden)]
#[allow(unused_qualifications, deprecated, missing_docs)]
pub mod version;
pub use self::version::VersionProto;

100
src/proto/version.rs Normal file
View File

@ -0,0 +1,100 @@
// This file is generated. Do not edit
// @generated
// https://github.com/Manishearth/rust-clippy/issues/702
#![allow(unknown_lints)]
#![allow(clippy)]
#![cfg_attr(rustfmt, rustfmt_skip)]
#![allow(box_pointers)]
#![allow(dead_code)]
#![allow(missing_docs)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(non_upper_case_globals)]
#![allow(trivial_casts)]
#![allow(unsafe_code)]
#![allow(unused_imports)]
#![allow(unused_results)]
use protobuf::Message as Message_imported_for_functions;
use protobuf::ProtobufEnum as ProtobufEnum_imported_for_functions;
#[derive(Clone,PartialEq,Eq,Debug,Hash)]
pub enum VersionProto {
INITIAL_RELEASE = 0,
}
impl ::protobuf::ProtobufEnum for VersionProto {
fn value(&self) -> i32 {
*self as i32
}
fn from_i32(value: i32) -> ::std::option::Option<VersionProto> {
match value {
0 => ::std::option::Option::Some(VersionProto::INITIAL_RELEASE),
_ => ::std::option::Option::None
}
}
fn values() -> &'static [Self] {
static values: &'static [VersionProto] = &[
VersionProto::INITIAL_RELEASE,
];
values
}
fn enum_descriptor_static(_: ::std::option::Option<VersionProto>) -> &'static ::protobuf::reflect::EnumDescriptor {
static mut descriptor: ::protobuf::lazy::Lazy<::protobuf::reflect::EnumDescriptor> = ::protobuf::lazy::Lazy {
lock: ::protobuf::lazy::ONCE_INIT,
ptr: 0 as *const ::protobuf::reflect::EnumDescriptor,
};
unsafe {
descriptor.get(|| {
::protobuf::reflect::EnumDescriptor::new("VersionProto", file_descriptor_proto())
})
}
}
}
impl ::std::marker::Copy for VersionProto {
}
impl ::std::default::Default for VersionProto {
fn default() -> Self {
VersionProto::INITIAL_RELEASE
}
}
impl ::protobuf::reflect::ProtobufValue for VersionProto {
fn as_ref(&self) -> ::protobuf::reflect::ProtobufValueRef {
::protobuf::reflect::ProtobufValueRef::Enum(self.descriptor())
}
}
static file_descriptor_proto_data: &'static [u8] = b"\
\n\rversion.proto*#\n\x0cVersionProto\x12\x13\n\x0fINITIAL_RELEASE\x10\0\
JS\n\x06\x12\x04\x01\0\x05\x01\n\x08\n\x01\x0c\x12\x03\x01\0\x12\n\n\n\
\x02\x05\0\x12\x04\x03\0\x05\x01\n\n\n\x03\x05\0\x01\x12\x03\x03\x05\x11\
\n\x0b\n\x04\x05\0\x02\0\x12\x03\x04\x02\x16\n\x0c\n\x05\x05\0\x02\0\x01\
\x12\x03\x04\x02\x11\n\x0c\n\x05\x05\0\x02\0\x02\x12\x03\x04\x14\x15b\
\x06proto3\
";
static mut file_descriptor_proto_lazy: ::protobuf::lazy::Lazy<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::lazy::Lazy {
lock: ::protobuf::lazy::ONCE_INIT,
ptr: 0 as *const ::protobuf::descriptor::FileDescriptorProto,
};
fn parse_descriptor_proto() -> ::protobuf::descriptor::FileDescriptorProto {
::protobuf::parse_from_bytes(file_descriptor_proto_data).unwrap()
}
pub fn file_descriptor_proto() -> &'static ::protobuf::descriptor::FileDescriptorProto {
unsafe {
file_descriptor_proto_lazy.get(|| {
parse_descriptor_proto()
})
}
}

9
src/proto/wrapped/mod.rs Normal file
View File

@ -0,0 +1,9 @@
#[allow(unused_qualifications, deprecated, missing_docs)]
mod secret;
pub use self::secret::SecretProto;
#[allow(unused_qualifications, deprecated, missing_docs)]
mod share;
pub use self::share::ShareProto;
pub use super::version;

328
src/proto/wrapped/secret.rs Normal file
View File

@ -0,0 +1,328 @@
// This file is generated. Do not edit
// @generated
// https://github.com/Manishearth/rust-clippy/issues/702
#![allow(unknown_lints)]
#![allow(clippy)]
#![cfg_attr(rustfmt, rustfmt_skip)]
#![allow(box_pointers)]
#![allow(dead_code)]
#![allow(missing_docs)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(non_upper_case_globals)]
#![allow(trivial_casts)]
#![allow(unsafe_code)]
#![allow(unused_imports)]
#![allow(unused_results)]
use protobuf::Message as Message_imported_for_functions;
use protobuf::ProtobufEnum as ProtobufEnum_imported_for_functions;
#[derive(PartialEq,Clone,Default)]
pub struct SecretProto {
// message fields
pub version: super::version::VersionProto,
pub secret: ::std::vec::Vec<u8>,
pub mime_type: ::std::string::String,
// special fields
unknown_fields: ::protobuf::UnknownFields,
cached_size: ::protobuf::CachedSize,
}
// see codegen.rs for the explanation why impl Sync explicitly
unsafe impl ::std::marker::Sync for SecretProto {}
impl SecretProto {
pub fn new() -> SecretProto {
::std::default::Default::default()
}
pub fn default_instance() -> &'static SecretProto {
static mut instance: ::protobuf::lazy::Lazy<SecretProto> = ::protobuf::lazy::Lazy {
lock: ::protobuf::lazy::ONCE_INIT,
ptr: 0 as *const SecretProto,
};
unsafe {
instance.get(SecretProto::new)
}
}
// .VersionProto version = 1;
pub fn clear_version(&mut self) {
self.version = super::version::VersionProto::INITIAL_RELEASE;
}
// Param is passed by value, moved
pub fn set_version(&mut self, v: super::version::VersionProto) {
self.version = v;
}
pub fn get_version(&self) -> super::version::VersionProto {
self.version
}
fn get_version_for_reflect(&self) -> &super::version::VersionProto {
&self.version
}
fn mut_version_for_reflect(&mut self) -> &mut super::version::VersionProto {
&mut self.version
}
// bytes secret = 2;
pub fn clear_secret(&mut self) {
self.secret.clear();
}
// Param is passed by value, moved
pub fn set_secret(&mut self, v: ::std::vec::Vec<u8>) {
self.secret = v;
}
// Mutable pointer to the field.
// If field is not initialized, it is initialized with default value first.
pub fn mut_secret(&mut self) -> &mut ::std::vec::Vec<u8> {
&mut self.secret
}
// Take field
pub fn take_secret(&mut self) -> ::std::vec::Vec<u8> {
::std::mem::replace(&mut self.secret, ::std::vec::Vec::new())
}
pub fn get_secret(&self) -> &[u8] {
&self.secret
}
fn get_secret_for_reflect(&self) -> &::std::vec::Vec<u8> {
&self.secret
}
fn mut_secret_for_reflect(&mut self) -> &mut ::std::vec::Vec<u8> {
&mut self.secret
}
// string mime_type = 3;
pub fn clear_mime_type(&mut self) {
self.mime_type.clear();
}
// Param is passed by value, moved
pub fn set_mime_type(&mut self, v: ::std::string::String) {
self.mime_type = v;
}
// Mutable pointer to the field.
// If field is not initialized, it is initialized with default value first.
pub fn mut_mime_type(&mut self) -> &mut ::std::string::String {
&mut self.mime_type
}
// Take field
pub fn take_mime_type(&mut self) -> ::std::string::String {
::std::mem::replace(&mut self.mime_type, ::std::string::String::new())
}
pub fn get_mime_type(&self) -> &str {
&self.mime_type
}
fn get_mime_type_for_reflect(&self) -> &::std::string::String {
&self.mime_type
}
fn mut_mime_type_for_reflect(&mut self) -> &mut ::std::string::String {
&mut self.mime_type
}
}
impl ::protobuf::Message for SecretProto {
fn is_initialized(&self) -> bool {
true
}
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream) -> ::protobuf::ProtobufResult<()> {
while !is.eof()? {
let (field_number, wire_type) = is.read_tag_unpack()?;
match field_number {
1 => {
if wire_type != ::protobuf::wire_format::WireTypeVarint {
return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
}
let tmp = is.read_enum()?;
self.version = tmp;
},
2 => {
::protobuf::rt::read_singular_proto3_bytes_into(wire_type, is, &mut self.secret)?;
},
3 => {
::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.mime_type)?;
},
_ => {
::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
},
};
}
::std::result::Result::Ok(())
}
// Compute sizes of nested messages
#[allow(unused_variables)]
fn compute_size(&self) -> u32 {
let mut my_size = 0;
if self.version != super::version::VersionProto::INITIAL_RELEASE {
my_size += ::protobuf::rt::enum_size(1, self.version);
}
if !self.secret.is_empty() {
my_size += ::protobuf::rt::bytes_size(2, &self.secret);
}
if !self.mime_type.is_empty() {
my_size += ::protobuf::rt::string_size(3, &self.mime_type);
}
my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
self.cached_size.set(my_size);
my_size
}
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream) -> ::protobuf::ProtobufResult<()> {
if self.version != super::version::VersionProto::INITIAL_RELEASE {
os.write_enum(1, self.version.value())?;
}
if !self.secret.is_empty() {
os.write_bytes(2, &self.secret)?;
}
if !self.mime_type.is_empty() {
os.write_string(3, &self.mime_type)?;
}
os.write_unknown_fields(self.get_unknown_fields())?;
::std::result::Result::Ok(())
}
fn get_cached_size(&self) -> u32 {
self.cached_size.get()
}
fn get_unknown_fields(&self) -> &::protobuf::UnknownFields {
&self.unknown_fields
}
fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields {
&mut self.unknown_fields
}
fn as_any(&self) -> &::std::any::Any {
self as &::std::any::Any
}
fn as_any_mut(&mut self) -> &mut ::std::any::Any {
self as &mut ::std::any::Any
}
fn into_any(self: Box<Self>) -> ::std::boxed::Box<::std::any::Any> {
self
}
fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor {
::protobuf::MessageStatic::descriptor_static(None::<Self>)
}
}
impl ::protobuf::MessageStatic for SecretProto {
fn new() -> SecretProto {
SecretProto::new()
}
fn descriptor_static(_: ::std::option::Option<SecretProto>) -> &'static ::protobuf::reflect::MessageDescriptor {
static mut descriptor: ::protobuf::lazy::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::lazy::Lazy {
lock: ::protobuf::lazy::ONCE_INIT,
ptr: 0 as *const ::protobuf::reflect::MessageDescriptor,
};
unsafe {
descriptor.get(|| {
let mut fields = ::std::vec::Vec::new();
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeEnum<super::version::VersionProto>>(
"version",
SecretProto::get_version_for_reflect,
SecretProto::mut_version_for_reflect,
));
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBytes>(
"secret",
SecretProto::get_secret_for_reflect,
SecretProto::mut_secret_for_reflect,
));
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
"mime_type",
SecretProto::get_mime_type_for_reflect,
SecretProto::mut_mime_type_for_reflect,
));
::protobuf::reflect::MessageDescriptor::new::<SecretProto>(
"SecretProto",
fields,
file_descriptor_proto()
)
})
}
}
}
impl ::protobuf::Clear for SecretProto {
fn clear(&mut self) {
self.clear_version();
self.clear_secret();
self.clear_mime_type();
self.unknown_fields.clear();
}
}
impl ::std::fmt::Debug for SecretProto {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
::protobuf::text_format::fmt(self, f)
}
}
impl ::protobuf::reflect::ProtobufValue for SecretProto {
fn as_ref(&self) -> ::protobuf::reflect::ProtobufValueRef {
::protobuf::reflect::ProtobufValueRef::Message(self)
}
}
static file_descriptor_proto_data: &'static [u8] = b"\
\n\x14wrapped/secret.proto\x12\x07wrapped\x1a\rversion.proto\"k\n\x0bSec\
retProto\x12'\n\x07version\x18\x01\x20\x01(\x0e2\r.VersionProtoR\x07vers\
ion\x12\x16\n\x06secret\x18\x02\x20\x01(\x0cR\x06secret\x12\x1b\n\tmime_\
type\x18\x03\x20\x01(\tR\x08mimeTypeJ\x91\x02\n\x06\x12\x04\0\0\n\x01\n\
\x08\n\x01\x0c\x12\x03\0\0\x12\n\x08\n\x01\x02\x12\x03\x02\x08\x0f\n\t\n\
\x02\x03\0\x12\x03\x04\x07\x16\n\n\n\x02\x04\0\x12\x04\x06\0\n\x01\n\n\n\
\x03\x04\0\x01\x12\x03\x06\x08\x13\n\x0b\n\x04\x04\0\x02\0\x12\x03\x07\
\x08!\n\r\n\x05\x04\0\x02\0\x04\x12\x04\x07\x08\x06\x15\n\x0c\n\x05\x04\
\0\x02\0\x06\x12\x03\x07\x08\x14\n\x0c\n\x05\x04\0\x02\0\x01\x12\x03\x07\
\x15\x1c\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x07\x1f\x20\n\x0b\n\x04\x04\
\0\x02\x01\x12\x03\x08\x08\x19\n\r\n\x05\x04\0\x02\x01\x04\x12\x04\x08\
\x08\x07!\n\x0c\n\x05\x04\0\x02\x01\x05\x12\x03\x08\x08\r\n\x0c\n\x05\
\x04\0\x02\x01\x01\x12\x03\x08\x0e\x14\n\x0c\n\x05\x04\0\x02\x01\x03\x12\
\x03\x08\x17\x18\n\x0b\n\x04\x04\0\x02\x02\x12\x03\t\x08\x1d\n\r\n\x05\
\x04\0\x02\x02\x04\x12\x04\t\x08\x08\x19\n\x0c\n\x05\x04\0\x02\x02\x05\
\x12\x03\t\x08\x0e\n\x0c\n\x05\x04\0\x02\x02\x01\x12\x03\t\x0f\x18\n\x0c\
\n\x05\x04\0\x02\x02\x03\x12\x03\t\x1b\x1cb\x06proto3\
";
static mut file_descriptor_proto_lazy: ::protobuf::lazy::Lazy<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::lazy::Lazy {
lock: ::protobuf::lazy::ONCE_INIT,
ptr: 0 as *const ::protobuf::descriptor::FileDescriptorProto,
};
fn parse_descriptor_proto() -> ::protobuf::descriptor::FileDescriptorProto {
::protobuf::parse_from_bytes(file_descriptor_proto_data).unwrap()
}
pub fn file_descriptor_proto() -> &'static ::protobuf::descriptor::FileDescriptorProto {
unsafe {
file_descriptor_proto_lazy.get(|| {
parse_descriptor_proto()
})
}
}

333
src/proto/wrapped/share.rs Normal file
View File

@ -0,0 +1,333 @@
// This file is generated. Do not edit
// @generated
// https://github.com/Manishearth/rust-clippy/issues/702
#![allow(unknown_lints)]
#![allow(clippy)]
#![cfg_attr(rustfmt, rustfmt_skip)]
#![allow(box_pointers)]
#![allow(dead_code)]
#![allow(missing_docs)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(non_upper_case_globals)]
#![allow(trivial_casts)]
#![allow(unsafe_code)]
#![allow(unused_imports)]
#![allow(unused_results)]
use protobuf::Message as Message_imported_for_functions;
use protobuf::ProtobufEnum as ProtobufEnum_imported_for_functions;
#[derive(PartialEq,Clone,Default)]
pub struct ShareProto {
// message fields
pub shamir_data: ::std::vec::Vec<u8>,
pub signature: ::protobuf::RepeatedField<::std::vec::Vec<u8>>,
pub proof: ::std::vec::Vec<u8>,
// special fields
unknown_fields: ::protobuf::UnknownFields,
cached_size: ::protobuf::CachedSize,
}
// see codegen.rs for the explanation why impl Sync explicitly
unsafe impl ::std::marker::Sync for ShareProto {}
impl ShareProto {
pub fn new() -> ShareProto {
::std::default::Default::default()
}
pub fn default_instance() -> &'static ShareProto {
static mut instance: ::protobuf::lazy::Lazy<ShareProto> = ::protobuf::lazy::Lazy {
lock: ::protobuf::lazy::ONCE_INIT,
ptr: 0 as *const ShareProto,
};
unsafe {
instance.get(ShareProto::new)
}
}
// bytes shamir_data = 1;
pub fn clear_shamir_data(&mut self) {
self.shamir_data.clear();
}
// Param is passed by value, moved
pub fn set_shamir_data(&mut self, v: ::std::vec::Vec<u8>) {
self.shamir_data = v;
}
// Mutable pointer to the field.
// If field is not initialized, it is initialized with default value first.
pub fn mut_shamir_data(&mut self) -> &mut ::std::vec::Vec<u8> {
&mut self.shamir_data
}
// Take field
pub fn take_shamir_data(&mut self) -> ::std::vec::Vec<u8> {
::std::mem::replace(&mut self.shamir_data, ::std::vec::Vec::new())
}
pub fn get_shamir_data(&self) -> &[u8] {
&self.shamir_data
}
fn get_shamir_data_for_reflect(&self) -> &::std::vec::Vec<u8> {
&self.shamir_data
}
fn mut_shamir_data_for_reflect(&mut self) -> &mut ::std::vec::Vec<u8> {
&mut self.shamir_data
}
// repeated bytes signature = 2;
pub fn clear_signature(&mut self) {
self.signature.clear();
}
// Param is passed by value, moved
pub fn set_signature(&mut self, v: ::protobuf::RepeatedField<::std::vec::Vec<u8>>) {
self.signature = v;
}
// Mutable pointer to the field.
pub fn mut_signature(&mut self) -> &mut ::protobuf::RepeatedField<::std::vec::Vec<u8>> {
&mut self.signature
}
// Take field
pub fn take_signature(&mut self) -> ::protobuf::RepeatedField<::std::vec::Vec<u8>> {
::std::mem::replace(&mut self.signature, ::protobuf::RepeatedField::new())
}
pub fn get_signature(&self) -> &[::std::vec::Vec<u8>] {
&self.signature
}
fn get_signature_for_reflect(&self) -> &::protobuf::RepeatedField<::std::vec::Vec<u8>> {
&self.signature
}
fn mut_signature_for_reflect(&mut self) -> &mut ::protobuf::RepeatedField<::std::vec::Vec<u8>> {
&mut self.signature
}
// bytes proof = 3;
pub fn clear_proof(&mut self) {
self.proof.clear();
}
// Param is passed by value, moved
pub fn set_proof(&mut self, v: ::std::vec::Vec<u8>) {
self.proof = v;
}
// Mutable pointer to the field.
// If field is not initialized, it is initialized with default value first.
pub fn mut_proof(&mut self) -> &mut ::std::vec::Vec<u8> {
&mut self.proof
}
// Take field
pub fn take_proof(&mut self) -> ::std::vec::Vec<u8> {
::std::mem::replace(&mut self.proof, ::std::vec::Vec::new())
}
pub fn get_proof(&self) -> &[u8] {
&self.proof
}
fn get_proof_for_reflect(&self) -> &::std::vec::Vec<u8> {
&self.proof
}
fn mut_proof_for_reflect(&mut self) -> &mut ::std::vec::Vec<u8> {
&mut self.proof
}
}
impl ::protobuf::Message for ShareProto {
fn is_initialized(&self) -> bool {
true
}
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream) -> ::protobuf::ProtobufResult<()> {
while !is.eof()? {
let (field_number, wire_type) = is.read_tag_unpack()?;
match field_number {
1 => {
::protobuf::rt::read_singular_proto3_bytes_into(wire_type, is, &mut self.shamir_data)?;
},
2 => {
::protobuf::rt::read_repeated_bytes_into(wire_type, is, &mut self.signature)?;
},
3 => {
::protobuf::rt::read_singular_proto3_bytes_into(wire_type, is, &mut self.proof)?;
},
_ => {
::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
},
};
}
::std::result::Result::Ok(())
}
// Compute sizes of nested messages
#[allow(unused_variables)]
fn compute_size(&self) -> u32 {
let mut my_size = 0;
if !self.shamir_data.is_empty() {
my_size += ::protobuf::rt::bytes_size(1, &self.shamir_data);
}
for value in &self.signature {
my_size += ::protobuf::rt::bytes_size(2, &value);
};
if !self.proof.is_empty() {
my_size += ::protobuf::rt::bytes_size(3, &self.proof);
}
my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
self.cached_size.set(my_size);
my_size
}
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream) -> ::protobuf::ProtobufResult<()> {
if !self.shamir_data.is_empty() {
os.write_bytes(1, &self.shamir_data)?;
}
for v in &self.signature {
os.write_bytes(2, &v)?;
};
if !self.proof.is_empty() {
os.write_bytes(3, &self.proof)?;
}
os.write_unknown_fields(self.get_unknown_fields())?;
::std::result::Result::Ok(())
}
fn get_cached_size(&self) -> u32 {
self.cached_size.get()
}
fn get_unknown_fields(&self) -> &::protobuf::UnknownFields {
&self.unknown_fields
}
fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields {
&mut self.unknown_fields
}
fn as_any(&self) -> &::std::any::Any {
self as &::std::any::Any
}
fn as_any_mut(&mut self) -> &mut ::std::any::Any {
self as &mut ::std::any::Any
}
fn into_any(self: Box<Self>) -> ::std::boxed::Box<::std::any::Any> {
self
}
fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor {
::protobuf::MessageStatic::descriptor_static(None::<Self>)
}
}
impl ::protobuf::MessageStatic for ShareProto {
fn new() -> ShareProto {
ShareProto::new()
}
fn descriptor_static(_: ::std::option::Option<ShareProto>) -> &'static ::protobuf::reflect::MessageDescriptor {
static mut descriptor: ::protobuf::lazy::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::lazy::Lazy {
lock: ::protobuf::lazy::ONCE_INIT,
ptr: 0 as *const ::protobuf::reflect::MessageDescriptor,
};
unsafe {
descriptor.get(|| {
let mut fields = ::std::vec::Vec::new();
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBytes>(
"shamir_data",
ShareProto::get_shamir_data_for_reflect,
ShareProto::mut_shamir_data_for_reflect,
));
fields.push(::protobuf::reflect::accessor::make_repeated_field_accessor::<_, ::protobuf::types::ProtobufTypeBytes>(
"signature",
ShareProto::get_signature_for_reflect,
ShareProto::mut_signature_for_reflect,
));
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeBytes>(
"proof",
ShareProto::get_proof_for_reflect,
ShareProto::mut_proof_for_reflect,
));
::protobuf::reflect::MessageDescriptor::new::<ShareProto>(
"ShareProto",
fields,
file_descriptor_proto()
)
})
}
}
}
impl ::protobuf::Clear for ShareProto {
fn clear(&mut self) {
self.clear_shamir_data();
self.clear_signature();
self.clear_proof();
self.unknown_fields.clear();
}
}
impl ::std::fmt::Debug for ShareProto {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
::protobuf::text_format::fmt(self, f)
}
}
impl ::protobuf::reflect::ProtobufValue for ShareProto {
fn as_ref(&self) -> ::protobuf::reflect::ProtobufValueRef {
::protobuf::reflect::ProtobufValueRef::Message(self)
}
}
static file_descriptor_proto_data: &'static [u8] = b"\
\n\x13wrapped/share.proto\x12\x07wrapped\"a\n\nShareProto\x12\x1f\n\x0bs\
hamir_data\x18\x01\x20\x01(\x0cR\nshamirData\x12\x1c\n\tsignature\x18\
\x02\x20\x03(\x0cR\tsignature\x12\x14\n\x05proof\x18\x03\x20\x01(\x0cR\
\x05proofJ\x85\x02\n\x06\x12\x04\0\0\x08\x01\n\x08\n\x01\x0c\x12\x03\0\0\
\x12\n\x08\n\x01\x02\x12\x03\x02\x08\x0f\n\n\n\x02\x04\0\x12\x04\x04\0\
\x08\x01\n\n\n\x03\x04\0\x01\x12\x03\x04\x08\x12\n\x0b\n\x04\x04\0\x02\0\
\x12\x03\x05\x08\x1e\n\r\n\x05\x04\0\x02\0\x04\x12\x04\x05\x08\x04\x14\n\
\x0c\n\x05\x04\0\x02\0\x05\x12\x03\x05\x08\r\n\x0c\n\x05\x04\0\x02\0\x01\
\x12\x03\x05\x0e\x19\n\x0c\n\x05\x04\0\x02\0\x03\x12\x03\x05\x1c\x1d\n\
\x0b\n\x04\x04\0\x02\x01\x12\x03\x06\x08%\n\x0c\n\x05\x04\0\x02\x01\x04\
\x12\x03\x06\x08\x10\n\x0c\n\x05\x04\0\x02\x01\x05\x12\x03\x06\x11\x16\n\
\x0c\n\x05\x04\0\x02\x01\x01\x12\x03\x06\x17\x20\n\x0c\n\x05\x04\0\x02\
\x01\x03\x12\x03\x06#$\n\x0b\n\x04\x04\0\x02\x02\x12\x03\x07\x08\x18\n\r\
\n\x05\x04\0\x02\x02\x04\x12\x04\x07\x08\x06%\n\x0c\n\x05\x04\0\x02\x02\
\x05\x12\x03\x07\x08\r\n\x0c\n\x05\x04\0\x02\x02\x01\x12\x03\x07\x0e\x13\
\n\x0c\n\x05\x04\0\x02\x02\x03\x12\x03\x07\x16\x17b\x06proto3\
";
static mut file_descriptor_proto_lazy: ::protobuf::lazy::Lazy<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::lazy::Lazy {
lock: ::protobuf::lazy::ONCE_INIT,
ptr: 0 as *const ::protobuf::descriptor::FileDescriptorProto,
};
fn parse_descriptor_proto() -> ::protobuf::descriptor::FileDescriptorProto {
::protobuf::parse_from_bytes(file_descriptor_proto_data).unwrap()
}
pub fn file_descriptor_proto() -> &'static ::protobuf::descriptor::FileDescriptorProto {
unsafe {
file_descriptor_proto_lazy.get(|| {
parse_descriptor_proto()
})
}
}

View File

@ -1,391 +0,0 @@
// This file is generated. Do not edit
// @generated
// https://github.com/Manishearth/rust-clippy/issues/702
#![allow(unknown_lints)]
#![allow(clippy)]
#![cfg_attr(rustfmt, rustfmt_skip)]
#![allow(box_pointers)]
#![allow(dead_code)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(non_upper_case_globals)]
#![allow(trivial_casts)]
#![allow(unsafe_code)]
#![allow(unused_imports)]
#![allow(unused_results)]
use protobuf::Message as Message_imported_for_functions;
use protobuf::ProtobufEnum as ProtobufEnum_imported_for_functions;
#[derive(Clone,Default)]
pub struct RustySecret {
// message fields
version: ::std::option::Option<RustySecretsVersions>,
secret: ::protobuf::SingularField<::std::vec::Vec<u8>>,
mime_type: ::protobuf::SingularField<::std::string::String>,
// special fields
unknown_fields: ::protobuf::UnknownFields,
cached_size: ::std::cell::Cell<u32>,
}
// see codegen.rs for the explanation why impl Sync explicitly
unsafe impl ::std::marker::Sync for RustySecret {}
impl RustySecret {
pub fn new() -> RustySecret {
::std::default::Default::default()
}
pub fn default_instance() -> &'static RustySecret {
static mut instance: ::protobuf::lazy::Lazy<RustySecret> = ::protobuf::lazy::Lazy {
lock: ::protobuf::lazy::ONCE_INIT,
ptr: 0 as *const RustySecret,
};
unsafe {
instance.get(|| {
RustySecret {
version: ::std::option::Option::None,
secret: ::protobuf::SingularField::none(),
mime_type: ::protobuf::SingularField::none(),
unknown_fields: ::protobuf::UnknownFields::new(),
cached_size: ::std::cell::Cell::new(0),
}
})
}
}
// optional .RustySecretsVersions version = 1;
pub fn clear_version(&mut self) {
self.version = ::std::option::Option::None;
}
pub fn has_version(&self) -> bool {
self.version.is_some()
}
// Param is passed by value, moved
pub fn set_version(&mut self, v: RustySecretsVersions) {
self.version = ::std::option::Option::Some(v);
}
pub fn get_version(&self) -> RustySecretsVersions {
self.version.unwrap_or(RustySecretsVersions::INITIAL_RELEASE)
}
// optional bytes secret = 2;
pub fn clear_secret(&mut self) {
self.secret.clear();
}
pub fn has_secret(&self) -> bool {
self.secret.is_some()
}
// Param is passed by value, moved
pub fn set_secret(&mut self, v: ::std::vec::Vec<u8>) {
self.secret = ::protobuf::SingularField::some(v);
}
// Mutable pointer to the field.
// If field is not initialized, it is initialized with default value first.
pub fn mut_secret(&mut self) -> &mut ::std::vec::Vec<u8> {
if self.secret.is_none() {
self.secret.set_default();
};
self.secret.as_mut().unwrap()
}
// Take field
pub fn take_secret(&mut self) -> ::std::vec::Vec<u8> {
self.secret.take().unwrap_or_else(|| ::std::vec::Vec::new())
}
pub fn get_secret(&self) -> &[u8] {
match self.secret.as_ref() {
Some(v) => &v,
None => &[],
}
}
// optional string mime_type = 3;
pub fn clear_mime_type(&mut self) {
self.mime_type.clear();
}
pub fn has_mime_type(&self) -> bool {
self.mime_type.is_some()
}
// Param is passed by value, moved
pub fn set_mime_type(&mut self, v: ::std::string::String) {
self.mime_type = ::protobuf::SingularField::some(v);
}
// Mutable pointer to the field.
// If field is not initialized, it is initialized with default value first.
pub fn mut_mime_type(&mut self) -> &mut ::std::string::String {
if self.mime_type.is_none() {
self.mime_type.set_default();
};
self.mime_type.as_mut().unwrap()
}
// Take field
pub fn take_mime_type(&mut self) -> ::std::string::String {
self.mime_type.take().unwrap_or_else(|| ::std::string::String::new())
}
pub fn get_mime_type(&self) -> &str {
match self.mime_type.as_ref() {
Some(v) => &v,
None => "",
}
}
}
impl ::protobuf::Message for RustySecret {
fn is_initialized(&self) -> bool {
true
}
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream) -> ::protobuf::ProtobufResult<()> {
while !try!(is.eof()) {
let (field_number, wire_type) = try!(is.read_tag_unpack());
match field_number {
1 => {
if wire_type != ::protobuf::wire_format::WireTypeVarint {
return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
};
let tmp = try!(is.read_enum());
self.version = ::std::option::Option::Some(tmp);
},
2 => {
try!(::protobuf::rt::read_singular_bytes_into(wire_type, is, &mut self.secret));
},
3 => {
try!(::protobuf::rt::read_singular_string_into(wire_type, is, &mut self.mime_type));
},
_ => {
try!(::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields()));
},
};
}
::std::result::Result::Ok(())
}
// Compute sizes of nested messages
#[allow(unused_variables)]
fn compute_size(&self) -> u32 {
let mut my_size = 0;
for value in &self.version {
my_size += ::protobuf::rt::enum_size(1, *value);
};
for value in &self.secret {
my_size += ::protobuf::rt::bytes_size(2, &value);
};
for value in &self.mime_type {
my_size += ::protobuf::rt::string_size(3, &value);
};
my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
self.cached_size.set(my_size);
my_size
}
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream) -> ::protobuf::ProtobufResult<()> {
if let Some(v) = self.version {
try!(os.write_enum(1, v.value()));
};
if let Some(v) = self.secret.as_ref() {
try!(os.write_bytes(2, &v));
};
if let Some(v) = self.mime_type.as_ref() {
try!(os.write_string(3, &v));
};
try!(os.write_unknown_fields(self.get_unknown_fields()));
::std::result::Result::Ok(())
}
fn get_cached_size(&self) -> u32 {
self.cached_size.get()
}
fn get_unknown_fields(&self) -> &::protobuf::UnknownFields {
&self.unknown_fields
}
fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields {
&mut self.unknown_fields
}
fn type_id(&self) -> ::std::any::TypeId {
::std::any::TypeId::of::<RustySecret>()
}
fn as_any(&self) -> &::std::any::Any {
self as &::std::any::Any
}
fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor {
::protobuf::MessageStatic::descriptor_static(None::<Self>)
}
}
impl ::protobuf::MessageStatic for RustySecret {
fn new() -> RustySecret {
RustySecret::new()
}
fn descriptor_static(_: ::std::option::Option<RustySecret>) -> &'static ::protobuf::reflect::MessageDescriptor {
static mut descriptor: ::protobuf::lazy::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::lazy::Lazy {
lock: ::protobuf::lazy::ONCE_INIT,
ptr: 0 as *const ::protobuf::reflect::MessageDescriptor,
};
unsafe {
descriptor.get(|| {
let mut fields = ::std::vec::Vec::new();
fields.push(::protobuf::reflect::accessor::make_singular_enum_accessor(
"version",
RustySecret::has_version,
RustySecret::get_version,
));
fields.push(::protobuf::reflect::accessor::make_singular_bytes_accessor(
"secret",
RustySecret::has_secret,
RustySecret::get_secret,
));
fields.push(::protobuf::reflect::accessor::make_singular_string_accessor(
"mime_type",
RustySecret::has_mime_type,
RustySecret::get_mime_type,
));
::protobuf::reflect::MessageDescriptor::new::<RustySecret>(
"RustySecret",
fields,
file_descriptor_proto()
)
})
}
}
}
impl ::protobuf::Clear for RustySecret {
fn clear(&mut self) {
self.clear_version();
self.clear_secret();
self.clear_mime_type();
self.unknown_fields.clear();
}
}
impl ::std::cmp::PartialEq for RustySecret {
fn eq(&self, other: &RustySecret) -> bool {
self.version == other.version &&
self.secret == other.secret &&
self.mime_type == other.mime_type &&
self.unknown_fields == other.unknown_fields
}
}
impl ::std::fmt::Debug for RustySecret {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
::protobuf::text_format::fmt(self, f)
}
}
#[derive(Clone,PartialEq,Eq,Debug,Hash)]
pub enum RustySecretsVersions {
INITIAL_RELEASE = 0,
}
impl ::protobuf::ProtobufEnum for RustySecretsVersions {
fn value(&self) -> i32 {
*self as i32
}
fn from_i32(value: i32) -> ::std::option::Option<RustySecretsVersions> {
match value {
0 => ::std::option::Option::Some(RustySecretsVersions::INITIAL_RELEASE),
_ => ::std::option::Option::None
}
}
fn values() -> &'static [Self] {
static values: &'static [RustySecretsVersions] = &[
RustySecretsVersions::INITIAL_RELEASE,
];
values
}
fn enum_descriptor_static(_: Option<RustySecretsVersions>) -> &'static ::protobuf::reflect::EnumDescriptor {
static mut descriptor: ::protobuf::lazy::Lazy<::protobuf::reflect::EnumDescriptor> = ::protobuf::lazy::Lazy {
lock: ::protobuf::lazy::ONCE_INIT,
ptr: 0 as *const ::protobuf::reflect::EnumDescriptor,
};
unsafe {
descriptor.get(|| {
::protobuf::reflect::EnumDescriptor::new("RustySecretsVersions", file_descriptor_proto())
})
}
}
}
impl ::std::marker::Copy for RustySecretsVersions {
}
static file_descriptor_proto_data: &'static [u8] = &[
0x0a, 0x0c, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x73,
0x0a, 0x0b, 0x52, 0x75, 0x73, 0x74, 0x79, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x2f, 0x0a,
0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x15,
0x2e, 0x52, 0x75, 0x73, 0x74, 0x79, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x73, 0x56, 0x65, 0x72,
0x73, 0x69, 0x6f, 0x6e, 0x73, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x16,
0x0a, 0x06, 0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06,
0x73, 0x65, 0x63, 0x72, 0x65, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x69, 0x6d, 0x65, 0x5f, 0x74,
0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6d, 0x69, 0x6d, 0x65, 0x54,
0x79, 0x70, 0x65, 0x2a, 0x2b, 0x0a, 0x14, 0x52, 0x75, 0x73, 0x74, 0x79, 0x53, 0x65, 0x63, 0x72,
0x65, 0x74, 0x73, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x13, 0x0a, 0x0f, 0x49,
0x4e, 0x49, 0x54, 0x49, 0x41, 0x4c, 0x5f, 0x52, 0x45, 0x4c, 0x45, 0x41, 0x53, 0x45, 0x10, 0x00,
0x4a, 0xbd, 0x02, 0x0a, 0x06, 0x12, 0x04, 0x00, 0x00, 0x0a, 0x01, 0x0a, 0x08, 0x0a, 0x01, 0x0c,
0x12, 0x03, 0x00, 0x00, 0x12, 0x0a, 0x0a, 0x0a, 0x02, 0x05, 0x00, 0x12, 0x04, 0x02, 0x00, 0x04,
0x01, 0x0a, 0x0a, 0x0a, 0x03, 0x05, 0x00, 0x01, 0x12, 0x03, 0x02, 0x05, 0x19, 0x0a, 0x0b, 0x0a,
0x04, 0x05, 0x00, 0x02, 0x00, 0x12, 0x03, 0x03, 0x08, 0x1c, 0x0a, 0x0c, 0x0a, 0x05, 0x05, 0x00,
0x02, 0x00, 0x01, 0x12, 0x03, 0x03, 0x08, 0x17, 0x0a, 0x0c, 0x0a, 0x05, 0x05, 0x00, 0x02, 0x00,
0x02, 0x12, 0x03, 0x03, 0x1a, 0x1b, 0x0a, 0x0a, 0x0a, 0x02, 0x04, 0x00, 0x12, 0x04, 0x06, 0x00,
0x0a, 0x01, 0x0a, 0x0a, 0x0a, 0x03, 0x04, 0x00, 0x01, 0x12, 0x03, 0x06, 0x08, 0x13, 0x0a, 0x0b,
0x0a, 0x04, 0x04, 0x00, 0x02, 0x00, 0x12, 0x03, 0x07, 0x08, 0x29, 0x0a, 0x0d, 0x0a, 0x05, 0x04,
0x00, 0x02, 0x00, 0x04, 0x12, 0x04, 0x07, 0x08, 0x06, 0x15, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00,
0x02, 0x00, 0x06, 0x12, 0x03, 0x07, 0x08, 0x1c, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00,
0x01, 0x12, 0x03, 0x07, 0x1d, 0x24, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x03, 0x12,
0x03, 0x07, 0x27, 0x28, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x01, 0x12, 0x03, 0x08, 0x08,
0x19, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, 0x04, 0x12, 0x04, 0x08, 0x08, 0x07, 0x29,
0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, 0x05, 0x12, 0x03, 0x08, 0x08, 0x0d, 0x0a, 0x0c,
0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, 0x01, 0x12, 0x03, 0x08, 0x0e, 0x14, 0x0a, 0x0c, 0x0a, 0x05,
0x04, 0x00, 0x02, 0x01, 0x03, 0x12, 0x03, 0x08, 0x17, 0x18, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x00,
0x02, 0x02, 0x12, 0x03, 0x09, 0x08, 0x1d, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x02, 0x04,
0x12, 0x04, 0x09, 0x08, 0x08, 0x19, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x02, 0x05, 0x12,
0x03, 0x09, 0x08, 0x0e, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x02, 0x01, 0x12, 0x03, 0x09,
0x0f, 0x18, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x02, 0x03, 0x12, 0x03, 0x09, 0x1b, 0x1c,
0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
];
static mut file_descriptor_proto_lazy: ::protobuf::lazy::Lazy<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::lazy::Lazy {
lock: ::protobuf::lazy::ONCE_INIT,
ptr: 0 as *const ::protobuf::descriptor::FileDescriptorProto,
};
fn parse_descriptor_proto() -> ::protobuf::descriptor::FileDescriptorProto {
::protobuf::parse_from_bytes(file_descriptor_proto_data).unwrap()
}
pub fn file_descriptor_proto() -> &'static ::protobuf::descriptor::FileDescriptorProto {
unsafe {
file_descriptor_proto_lazy.get(|| {
parse_descriptor_proto()
})
}
}

40
src/share/mod.rs Normal file
View File

@ -0,0 +1,40 @@
//! Define the traits used to distinguish the various
//! kind of shares internally used by the library.
//! These traits are currently not exposed, but this might
//! change in the future.
use errors::*;
pub(crate) mod validation;
/// All types of share should implement this trait.
pub(crate) trait IsShare: Sized {
/// Returns the identifier of the share.
/// Varies between 1 and n where n is the total number of generated shares.
fn get_id(&self) -> u8;
/// Returns the share data itself
fn get_data(&self) -> &[u8];
/// Returns the number of shares necessary to recover the secret, aka the threshold
fn get_threshold(&self) -> u8;
/// Returns the total number of shares that have been dealt
fn get_shares_count(&self) -> Option<u8>;
}
/// This trait must be implemented by shares' types wich can be signed.
pub(crate) trait IsSignedShare: IsShare {
/// The type of shares' sigature.
type Signature;
/// Returns whether this share is signed or not.
fn is_signed(&self) -> bool;
/// Return the signature itself.
fn get_signature(&self) -> &Self::Signature;
/// Verify the signatures of the given batch of shares.
/// Returns `Ok(())` if validation succeeds, and an `Err` otherwise.
fn verify_signatures(shares: &[Self]) -> Result<()>;
}

113
src/share/validation.rs Normal file
View File

@ -0,0 +1,113 @@
use std::collections::{HashMap, HashSet};
use errors::*;
use share::{IsShare, IsSignedShare};
// The order of validation that we think makes the most sense is the following:
// 1) Validate shares individually
// 2) Validate duplicate shares share num && data
// 2) Validate group consistency
// 3) Validate other properties, in no specific order
/// TODO: Doc
pub(crate) fn validate_signed_shares<S: IsSignedShare>(
shares: Vec<S>,
verify_signatures: bool,
) -> Result<(u8, Vec<S>)> {
let (threshold, shares) = validate_shares(shares)?;
if verify_signatures {
S::verify_signatures(&shares)?;
}
Ok((threshold, shares))
}
/// TODO: Doc
pub(crate) fn validate_shares<S: IsShare>(shares: Vec<S>) -> Result<(u8, Vec<S>)> {
if shares.is_empty() {
bail!(ErrorKind::EmptyShares);
}
let shares_count = shares.len();
let mut result: Vec<S> = Vec::with_capacity(shares_count);
let mut k_compatibility_sets = HashMap::new();
for share in shares {
let (id, threshold) = (share.get_id(), share.get_threshold());
if id > MAX_SHARES {
bail!(ErrorKind::ShareIdentifierTooBig(id, MAX_SHARES))
}
if id < 1 {
bail!(ErrorKind::ShareParsingInvalidShareId(id))
}
k_compatibility_sets
.entry(threshold)
.or_insert_with(HashSet::new);
let k_set = k_compatibility_sets.get_mut(&threshold).unwrap();
k_set.insert(id);
if result.iter().any(|s| s.get_id() == id) {
bail!(ErrorKind::DuplicateShareId(id));
}
if share.get_data().is_empty() {
bail!(ErrorKind::ShareParsingErrorEmptyShare(id))
}
if result.iter().any(|s| s.get_data() == share.get_data()) && share.get_threshold() != 1 {
// When threshold = 1, shares data can be the same
bail!(ErrorKind::DuplicateShareData(id));
}
result.push(share);
}
// Validate threshold
let k_sets = k_compatibility_sets.keys().count();
match k_sets {
0 => bail!(ErrorKind::EmptyShares),
1 => {} // All shares have the same roothash.
_ => {
bail! {
ErrorKind::IncompatibleSets(
k_compatibility_sets
.values()
.map(|x| x.to_owned())
.collect(),
)
}
}
}
// It is safe to unwrap because k_sets == 1
let threshold = k_compatibility_sets.keys().last().unwrap().to_owned();
if shares_count < threshold as usize {
bail!(ErrorKind::MissingShares(threshold as usize, shares_count));
}
Ok((threshold, result))
}
pub(crate) fn validate_share_count(threshold: u8, shares_count: u8) -> Result<(u8, u8)> {
if threshold < MIN_SHARES {
bail!(ErrorKind::ThresholdTooSmall(threshold));
}
if shares_count > MAX_SHARES {
bail!(ErrorKind::InvalidShareCountMax(shares_count, MAX_SHARES));
}
if shares_count < MIN_SHARES {
bail!(ErrorKind::InvalidShareCountMin(shares_count, MIN_SHARES));
}
if threshold > shares_count {
bail!(ErrorKind::ThresholdTooBig(threshold, shares_count));
}
Ok((threshold, shares_count))
}

View File

@ -1,345 +0,0 @@
// This file is generated. Do not edit
// @generated
// https://github.com/Manishearth/rust-clippy/issues/702
#![allow(unknown_lints)]
#![allow(clippy)]
#![cfg_attr(rustfmt, rustfmt_skip)]
#![allow(box_pointers)]
#![allow(dead_code)]
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(non_upper_case_globals)]
#![allow(trivial_casts)]
#![allow(unsafe_code)]
#![allow(unused_imports)]
#![allow(unused_results)]
use protobuf::Message as Message_imported_for_functions;
use protobuf::ProtobufEnum as ProtobufEnum_imported_for_functions;
#[derive(Clone,Default)]
pub struct ShareData {
// message fields
shamir_data: ::protobuf::SingularField<::std::vec::Vec<u8>>,
signature: ::protobuf::RepeatedField<::std::vec::Vec<u8>>,
proof: ::protobuf::SingularField<::std::vec::Vec<u8>>,
// special fields
unknown_fields: ::protobuf::UnknownFields,
cached_size: ::std::cell::Cell<u32>,
}
// see codegen.rs for the explanation why impl Sync explicitly
unsafe impl ::std::marker::Sync for ShareData {}
impl ShareData {
pub fn new() -> ShareData {
::std::default::Default::default()
}
pub fn default_instance() -> &'static ShareData {
static mut instance: ::protobuf::lazy::Lazy<ShareData> = ::protobuf::lazy::Lazy {
lock: ::protobuf::lazy::ONCE_INIT,
ptr: 0 as *const ShareData,
};
unsafe {
instance.get(|| {
ShareData {
shamir_data: ::protobuf::SingularField::none(),
signature: ::protobuf::RepeatedField::new(),
proof: ::protobuf::SingularField::none(),
unknown_fields: ::protobuf::UnknownFields::new(),
cached_size: ::std::cell::Cell::new(0),
}
})
}
}
// optional bytes shamir_data = 1;
pub fn clear_shamir_data(&mut self) {
self.shamir_data.clear();
}
pub fn has_shamir_data(&self) -> bool {
self.shamir_data.is_some()
}
// Param is passed by value, moved
pub fn set_shamir_data(&mut self, v: ::std::vec::Vec<u8>) {
self.shamir_data = ::protobuf::SingularField::some(v);
}
// Mutable pointer to the field.
// If field is not initialized, it is initialized with default value first.
pub fn mut_shamir_data(&mut self) -> &mut ::std::vec::Vec<u8> {
if self.shamir_data.is_none() {
self.shamir_data.set_default();
};
self.shamir_data.as_mut().unwrap()
}
// Take field
pub fn take_shamir_data(&mut self) -> ::std::vec::Vec<u8> {
self.shamir_data.take().unwrap_or_else(|| ::std::vec::Vec::new())
}
pub fn get_shamir_data(&self) -> &[u8] {
match self.shamir_data.as_ref() {
Some(v) => &v,
None => &[],
}
}
// repeated bytes signature = 2;
pub fn clear_signature(&mut self) {
self.signature.clear();
}
// Param is passed by value, moved
pub fn set_signature(&mut self, v: ::protobuf::RepeatedField<::std::vec::Vec<u8>>) {
self.signature = v;
}
// Mutable pointer to the field.
pub fn mut_signature(&mut self) -> &mut ::protobuf::RepeatedField<::std::vec::Vec<u8>> {
&mut self.signature
}
// Take field
pub fn take_signature(&mut self) -> ::protobuf::RepeatedField<::std::vec::Vec<u8>> {
::std::mem::replace(&mut self.signature, ::protobuf::RepeatedField::new())
}
pub fn get_signature(&self) -> &[::std::vec::Vec<u8>] {
&self.signature
}
// optional bytes proof = 3;
pub fn clear_proof(&mut self) {
self.proof.clear();
}
pub fn has_proof(&self) -> bool {
self.proof.is_some()
}
// Param is passed by value, moved
pub fn set_proof(&mut self, v: ::std::vec::Vec<u8>) {
self.proof = ::protobuf::SingularField::some(v);
}
// Mutable pointer to the field.
// If field is not initialized, it is initialized with default value first.
pub fn mut_proof(&mut self) -> &mut ::std::vec::Vec<u8> {
if self.proof.is_none() {
self.proof.set_default();
};
self.proof.as_mut().unwrap()
}
// Take field
pub fn take_proof(&mut self) -> ::std::vec::Vec<u8> {
self.proof.take().unwrap_or_else(|| ::std::vec::Vec::new())
}
pub fn get_proof(&self) -> &[u8] {
match self.proof.as_ref() {
Some(v) => &v,
None => &[],
}
}
}
impl ::protobuf::Message for ShareData {
fn is_initialized(&self) -> bool {
true
}
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream) -> ::protobuf::ProtobufResult<()> {
while !try!(is.eof()) {
let (field_number, wire_type) = try!(is.read_tag_unpack());
match field_number {
1 => {
try!(::protobuf::rt::read_singular_bytes_into(wire_type, is, &mut self.shamir_data));
},
2 => {
try!(::protobuf::rt::read_repeated_bytes_into(wire_type, is, &mut self.signature));
},
3 => {
try!(::protobuf::rt::read_singular_bytes_into(wire_type, is, &mut self.proof));
},
_ => {
try!(::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields()));
},
};
}
::std::result::Result::Ok(())
}
// Compute sizes of nested messages
#[allow(unused_variables)]
fn compute_size(&self) -> u32 {
let mut my_size = 0;
for value in &self.shamir_data {
my_size += ::protobuf::rt::bytes_size(1, &value);
};
for value in &self.signature {
my_size += ::protobuf::rt::bytes_size(2, &value);
};
for value in &self.proof {
my_size += ::protobuf::rt::bytes_size(3, &value);
};
my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
self.cached_size.set(my_size);
my_size
}
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream) -> ::protobuf::ProtobufResult<()> {
if let Some(v) = self.shamir_data.as_ref() {
try!(os.write_bytes(1, &v));
};
for v in &self.signature {
try!(os.write_bytes(2, &v));
};
if let Some(v) = self.proof.as_ref() {
try!(os.write_bytes(3, &v));
};
try!(os.write_unknown_fields(self.get_unknown_fields()));
::std::result::Result::Ok(())
}
fn get_cached_size(&self) -> u32 {
self.cached_size.get()
}
fn get_unknown_fields(&self) -> &::protobuf::UnknownFields {
&self.unknown_fields
}
fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields {
&mut self.unknown_fields
}
fn type_id(&self) -> ::std::any::TypeId {
::std::any::TypeId::of::<ShareData>()
}
fn as_any(&self) -> &::std::any::Any {
self as &::std::any::Any
}
fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor {
::protobuf::MessageStatic::descriptor_static(None::<Self>)
}
}
impl ::protobuf::MessageStatic for ShareData {
fn new() -> ShareData {
ShareData::new()
}
fn descriptor_static(_: ::std::option::Option<ShareData>) -> &'static ::protobuf::reflect::MessageDescriptor {
static mut descriptor: ::protobuf::lazy::Lazy<::protobuf::reflect::MessageDescriptor> = ::protobuf::lazy::Lazy {
lock: ::protobuf::lazy::ONCE_INIT,
ptr: 0 as *const ::protobuf::reflect::MessageDescriptor,
};
unsafe {
descriptor.get(|| {
let mut fields = ::std::vec::Vec::new();
fields.push(::protobuf::reflect::accessor::make_singular_bytes_accessor(
"shamir_data",
ShareData::has_shamir_data,
ShareData::get_shamir_data,
));
fields.push(::protobuf::reflect::accessor::make_repeated_bytes_accessor(
"signature",
ShareData::get_signature,
));
fields.push(::protobuf::reflect::accessor::make_singular_bytes_accessor(
"proof",
ShareData::has_proof,
ShareData::get_proof,
));
::protobuf::reflect::MessageDescriptor::new::<ShareData>(
"ShareData",
fields,
file_descriptor_proto()
)
})
}
}
}
impl ::protobuf::Clear for ShareData {
fn clear(&mut self) {
self.clear_shamir_data();
self.clear_signature();
self.clear_proof();
self.unknown_fields.clear();
}
}
impl ::std::cmp::PartialEq for ShareData {
fn eq(&self, other: &ShareData) -> bool {
self.shamir_data == other.shamir_data &&
self.signature == other.signature &&
self.proof == other.proof &&
self.unknown_fields == other.unknown_fields
}
}
impl ::std::fmt::Debug for ShareData {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
::protobuf::text_format::fmt(self, f)
}
}
static file_descriptor_proto_data: &'static [u8] = &[
0x0a, 0x18, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x53, 0x68, 0x61, 0x72, 0x65,
0x44, 0x61, 0x74, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0x60, 0x0a, 0x09, 0x53, 0x68,
0x61, 0x72, 0x65, 0x44, 0x61, 0x74, 0x61, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x68, 0x61, 0x6d, 0x69,
0x72, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x73, 0x68,
0x61, 0x6d, 0x69, 0x72, 0x44, 0x61, 0x74, 0x61, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e,
0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0c, 0x52, 0x09, 0x73, 0x69, 0x67,
0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x18,
0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x70, 0x72, 0x6f, 0x6f, 0x66, 0x4a, 0xfb, 0x01, 0x0a,
0x06, 0x12, 0x04, 0x00, 0x00, 0x06, 0x01, 0x0a, 0x08, 0x0a, 0x01, 0x0c, 0x12, 0x03, 0x00, 0x00,
0x12, 0x0a, 0x0a, 0x0a, 0x02, 0x04, 0x00, 0x12, 0x04, 0x02, 0x00, 0x06, 0x01, 0x0a, 0x0a, 0x0a,
0x03, 0x04, 0x00, 0x01, 0x12, 0x03, 0x02, 0x08, 0x11, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x00, 0x02,
0x00, 0x12, 0x03, 0x03, 0x08, 0x1e, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x04, 0x12,
0x04, 0x03, 0x08, 0x02, 0x13, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x05, 0x12, 0x03,
0x03, 0x08, 0x0d, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x01, 0x12, 0x03, 0x03, 0x0e,
0x19, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x00, 0x03, 0x12, 0x03, 0x03, 0x1c, 0x1d, 0x0a,
0x0b, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x01, 0x12, 0x03, 0x04, 0x08, 0x25, 0x0a, 0x0c, 0x0a, 0x05,
0x04, 0x00, 0x02, 0x01, 0x04, 0x12, 0x03, 0x04, 0x08, 0x10, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00,
0x02, 0x01, 0x05, 0x12, 0x03, 0x04, 0x11, 0x16, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01,
0x01, 0x12, 0x03, 0x04, 0x17, 0x20, 0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x01, 0x03, 0x12,
0x03, 0x04, 0x23, 0x24, 0x0a, 0x0b, 0x0a, 0x04, 0x04, 0x00, 0x02, 0x02, 0x12, 0x03, 0x05, 0x08,
0x18, 0x0a, 0x0d, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x02, 0x04, 0x12, 0x04, 0x05, 0x08, 0x04, 0x25,
0x0a, 0x0c, 0x0a, 0x05, 0x04, 0x00, 0x02, 0x02, 0x05, 0x12, 0x03, 0x05, 0x08, 0x0d, 0x0a, 0x0c,
0x0a, 0x05, 0x04, 0x00, 0x02, 0x02, 0x01, 0x12, 0x03, 0x05, 0x0e, 0x13, 0x0a, 0x0c, 0x0a, 0x05,
0x04, 0x00, 0x02, 0x02, 0x03, 0x12, 0x03, 0x05, 0x16, 0x17, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x33,
];
static mut file_descriptor_proto_lazy: ::protobuf::lazy::Lazy<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::lazy::Lazy {
lock: ::protobuf::lazy::ONCE_INIT,
ptr: 0 as *const ::protobuf::descriptor::FileDescriptorProto,
};
fn parse_descriptor_proto() -> ::protobuf::descriptor::FileDescriptorProto {
::protobuf::parse_from_bytes(file_descriptor_proto_data).unwrap()
}
pub fn file_descriptor_proto() -> &'static ::protobuf::descriptor::FileDescriptorProto {
unsafe {
file_descriptor_proto_lazy.get(|| {
parse_descriptor_proto()
})
}
}

View File

@ -1,87 +0,0 @@
use custom_error::{RustyError, RustyErrorTypes};
use custom_error::pie2error;
use digest;
use merkle_sigs::{MerklePublicKey, Proof, PublicKey};
use protobuf;
use protobuf::{Message, RepeatedField};
use serialize;
use serialize::base64::{self, FromBase64, ToBase64};
use share_data::ShareData;
use std::error::Error;
type ParsedShare = Result<(Vec<u8>, u8, u8, Option<(Vec<Vec<u8>>, Proof<MerklePublicKey>)>), RustyError>;
fn base64_config() -> serialize::base64::Config {
base64::Config { pad: false, ..base64::STANDARD }
}
pub fn share_string_from(share: Vec<u8>, threshold: u8, share_num: u8,
signature_pair: Option<(Vec<Vec<u8>>, Proof<MerklePublicKey>)>)
-> String {
let mut share_protobuf = ShareData::new();
share_protobuf.set_shamir_data(share);
if signature_pair.is_some() {
let (signature, proof) = signature_pair.unwrap();
share_protobuf.set_signature(RepeatedField::from_vec(signature));
share_protobuf.set_proof(proof.write_to_bytes().unwrap());
}
let b64_share = share_protobuf.write_to_bytes().unwrap().to_base64(base64_config());
format!("{}-{}-{}", threshold, share_num, b64_share)
}
pub fn share_from_string
(s: &str,
index: u8,
is_signed: bool)
-> ParsedShare {
let parts: Vec<_> = s.trim().split('-').collect();
if parts.len() != 3 {
return Err(RustyError::with_type(RustyErrorTypes::ShareParsingError(index, format!("Expected 3 parts separated by a minus sign. Found {}.", s))));
}
let (k, n, p3) = {
let mut iter = parts.into_iter();
let k = try!(iter.next().unwrap().parse::<u8>().map_err(pie2error));
let n = try!(iter.next().unwrap().parse::<u8>().map_err(pie2error));
let p3 = iter.next().unwrap();
(k, n, p3)
};
if k < 1 || n < 1 {
return Err(RustyError::with_type(RustyErrorTypes::ShareParsingError(index, format!("Found illegal parameters K: {} N: {}.", k, n))));
}
let raw_data = try!(p3.from_base64().map_err(|_| {
RustyError::with_type(RustyErrorTypes::ShareParsingError(index, "Base64 decoding of data block failed".to_owned()))
}));
let protobuf_data = try!(protobuf::parse_from_bytes::<ShareData>(raw_data.as_slice())
.map_err(|e| RustyError::with_type(RustyErrorTypes::ShareParsingError(index, format!("Protobuf decoding of data block failed with error: {} .", e.description())))));
let share = Vec::from(protobuf_data.get_shamir_data());
if is_signed {
let p_result = Proof::parse_from_bytes(protobuf_data.get_proof(), digest);
let p_opt = p_result.unwrap();
let p = p_opt.unwrap();
let proof = Proof {
algorithm: digest,
lemma: p.lemma,
root_hash: p.root_hash,
value: MerklePublicKey::new(PublicKey::from_vec(p.value, digest).unwrap()),
};
let signature = protobuf_data.get_signature();
Ok((share, k, n, Some((Vec::from(signature), proof))))
} else {
Ok((share, k, n, None))
}
}
pub fn format_share_for_signing(k: u8, i: u8, data: &[u8]) -> Vec<u8> {
format!("{}-{}-{}", k, i, data.to_base64(base64_config())).into_bytes()
}

View File

@ -1,128 +0,0 @@
//! SSS provides Shamir's secret sharing with raw data.
use custom_error::{RustyError, other_io_err};
use digest;
use interpolation::{encode, lagrange_interpolate};
use merkle_sigs::sign_data_vec;
use rand::{OsRng, Rng};
use share_format::format_share_for_signing;
use share_format::share_string_from;
use std::io;
use std::iter::repeat;
use validation::process_and_validate_shares;
fn new_vec<T: Clone>(n: usize, x: T) -> Vec<T> {
repeat(x).take(n).collect()
}
/// Performs threshold k-out-of-n Shamir's secret sharing.
///
/// # Examples
///
/// ```
/// use rusty_secrets::sss::generate_shares;
/// let secret = "These programs were never about terrorism: theyre about economic spying,
/// social control, and diplomatic manipulation. Theyre about power.".to_string();
///
/// match generate_shares(7, 10, &secret.into_bytes(), true){
/// Ok(shares) => {
/// // Do something with the shares
/// },
/// Err(_) => {}// Deal with error}
/// }
/// ```
pub fn generate_shares(k: u8, n: u8, secret: &[u8], sign_shares: bool) -> io::Result<Vec<String>> {
if k > n {
return Err(other_io_err("Threshold K can not be larger than N", None, None, None));
}
let shares = try!(secret_share(secret, k, n));
let signatures = if sign_shares {
let shares_to_sign = shares.iter()
.enumerate()
.map(|(i, x)| format_share_for_signing(k, (i + 1) as u8, x))
.collect::<Vec<_>>();
let sign = sign_data_vec(&shares_to_sign, digest)
.unwrap()
.into_iter()
.map(Some)
.collect::<Vec<_>>();
Some(sign)
} else {
None
};
let mut result = Vec::with_capacity(n as usize);
for ((index, share), signature_pair) in
shares.into_iter()
.enumerate()
.zip(signatures.unwrap_or_else(|| vec![None; n as usize]).into_iter()) {
let share_string = share_string_from(share, k, (index + 1) as u8, signature_pair);
result.push(share_string);
}
Ok(result)
}
fn secret_share(src: &[u8], k: u8, n: u8) -> Result<Vec<Vec<u8>>, RustyError> {
let mut result = Vec::with_capacity(n as usize);
for _ in 0..(n as usize) {
result.push(new_vec(src.len(), 0u8));
}
let mut col_in = new_vec(k as usize, 0u8);
let mut col_out = Vec::with_capacity(n as usize);
let mut osrng = try!(OsRng::new());
for (c, &s) in src.iter().enumerate() {
col_in[0] = s;
osrng.fill_bytes(&mut col_in[1..]);
col_out.clear();
try!(encode(&*col_in, n, &mut col_out));
for (&y, share) in col_out.iter().zip(result.iter_mut()) {
share[c] = y;
}
}
Ok(result)
}
/// Recovers the secret from a k-out-of-n Shamir's secret sharing.
///
/// At least `k` distinct shares need to be provided to recover the share.
///
/// # Examples
///
/// ```
/// use rusty_secrets::sss::recover_secret;
/// let share1 = "2-1-Cha7s14Q/mSwWko0ittr+/Uf79RHQMIP".to_string();
/// let share2 = "2-4-ChaydsUJDypD9ZWxwvIICh/cmZvzusOF".to_string();
/// let shares = vec![share1, share2];
///
/// match recover_secret(shares, false) {
/// Ok(secret) => {
/// // Do something with the secret
/// },
/// Err(e) => {
/// // Deal with the error
/// }
/// }
/// ```
pub fn recover_secret(shares: Vec<String>, verify_signatures: bool) -> Result<Vec<u8>, RustyError> {
let (k, shares) = try!(process_and_validate_shares(shares, verify_signatures));
let slen = shares[0].1.len();
let mut col_in = Vec::with_capacity(k as usize);
let mut secret = Vec::with_capacity(slen);
for byteindex in 0..slen {
col_in.clear();
for s in shares.iter().take(k as usize) {
col_in.push((s.0, s.1[byteindex]));
}
secret.push(lagrange_interpolate(&*col_in));
}
Ok(secret)
}

18
src/sss/encode.rs Normal file
View File

@ -0,0 +1,18 @@
use gf256::Gf256;
use std::io;
use std::io::prelude::*;
/// evaluates a polynomial at x=1, 2, 3, ... n (inclusive)
pub(crate) fn encode_secret_byte<W: Write>(src: &[u8], n: u8, w: &mut W) -> io::Result<()> {
for raw_x in 1..(u16::from(n) + 1) {
let x = Gf256::from_byte(raw_x as u8);
let mut fac = Gf256::one();
let mut acc = Gf256::zero();
for &coeff in src.iter() {
acc = acc + fac * Gf256::from_byte(coeff);
fac = fac * x;
}
w.write_all(&[acc.to_byte()])?;
}
Ok(())
}

104
src/sss/format.rs Normal file
View File

@ -0,0 +1,104 @@
use errors::*;
use merkle_sigs::{MerklePublicKey, Proof, PublicKey};
use protobuf::{self, Message, RepeatedField};
use base64;
use sss::{Share, HASH_ALGO};
use proto::wrapped::ShareProto;
use std::error::Error;
const BASE64_CONFIG: base64::Config = base64::STANDARD_NO_PAD;
pub(crate) fn share_to_string(
share: Vec<u8>,
threshold: u8,
share_num: u8,
signature_pair: Option<(Vec<Vec<u8>>, Proof<MerklePublicKey>)>,
) -> String {
let mut share_protobuf = ShareProto::new();
share_protobuf.set_shamir_data(share);
if signature_pair.is_some() {
let (signature, proof) = signature_pair.unwrap();
share_protobuf.set_signature(RepeatedField::from_vec(signature));
share_protobuf.set_proof(proof.write_to_bytes().unwrap());
}
let proto_buf = share_protobuf.write_to_bytes().unwrap();
let b64_share = base64::encode_config(&proto_buf, BASE64_CONFIG);
format!("{}-{}-{}", threshold, share_num, b64_share)
}
pub(crate) fn share_from_string(s: &str, is_signed: bool) -> Result<Share> {
let parts: Vec<_> = s.trim().split('-').collect();
if parts.len() != SSS_SHARE_PARTS_COUNT {
bail! {
ErrorKind::ShareParsingError(
format!(
"Expected 3 parts separated by a minus sign. Found {}.",
s
),
)
};
}
let (k, i, p3) = {
let mut iter = parts.into_iter();
let k = iter.next().unwrap().parse::<u8>()?;
let i = iter.next().unwrap().parse::<u8>()?;
let p3 = iter.next().unwrap();
(k, i, p3)
};
if k < 1 || i < 1 {
bail! {
ErrorKind::ShareParsingError(
format!("Found illegal share info: threshold = {}, identifier = {}.", k, i),
)
}
}
let raw_data = base64::decode_config(p3, BASE64_CONFIG).chain_err(|| {
ErrorKind::ShareParsingError("Base64 decoding of data block failed".to_owned())
})?;
let protobuf_data =
protobuf::parse_from_bytes::<ShareProto>(raw_data.as_slice()).map_err(|e| {
ErrorKind::ShareParsingError(format!(
"Protobuf decoding of data block failed with error: {} .",
e.description()
))
})?;
let data = Vec::from(protobuf_data.get_shamir_data());
let signature_pair = if is_signed {
let p_result = Proof::parse_from_bytes(protobuf_data.get_proof(), HASH_ALGO);
let p_opt = p_result.unwrap();
let p = p_opt.unwrap();
let proof = Proof {
algorithm: HASH_ALGO,
lemma: p.lemma,
root_hash: p.root_hash,
value: MerklePublicKey::new(PublicKey::from_vec(p.value, HASH_ALGO).unwrap()),
};
let signature = protobuf_data.get_signature();
Some((Vec::from(signature), proof).into())
} else {
None
};
Ok(Share {
id: i,
data,
threshold: k,
signature_pair,
})
}
pub(crate) fn format_share_for_signing(k: u8, i: u8, data: &[u8]) -> Vec<u8> {
let b64_data = base64::encode_config(data, BASE64_CONFIG);
format!("{}-{}-{}", k, i, b64_data).into_bytes()
}

69
src/sss/mod.rs Normal file
View File

@ -0,0 +1,69 @@
//! SSS provides Shamir's secret sharing with raw data.
use errors::*;
mod share;
pub(crate) use self::share::*;
mod format;
// pub use self::format::*;
mod scheme;
pub(crate) use self::scheme::*;
mod encode;
use ring::digest::{Algorithm, SHA512};
static HASH_ALGO: &'static Algorithm = &SHA512;
/// Performs threshold k-out-of-n Shamir's secret sharing.
///
/// # Examples
///
/// ```
/// use rusty_secrets::sss::split_secret;
///
/// let secret = "These programs were never about terrorism: theyre about economic spying, \
/// social control, and diplomatic manipulation. Theyre about power.";
///
/// match split_secret(7, 10, &secret.as_bytes(), true) {
/// Ok(shares) => {
/// // Do something with the shares
/// },
/// Err(_) => {
/// // Deal with error
/// }
/// }
/// ```
pub fn split_secret(k: u8, n: u8, secret: &[u8], sign_shares: bool) -> Result<Vec<String>> {
SSS::default()
.split_secret(k, n, secret, sign_shares)
.map(|shares| shares.into_iter().map(Share::into_string).collect())
}
/// Recovers the secret from a k-out-of-n Shamir's secret sharing scheme.
///
/// At least `k` distinct shares need to be provided to recover the secret.
///
/// # Examples
///
/// ```
/// use rusty_secrets::sss::recover_secret;
///
/// let share1 = "2-1-Cha7s14Q/mSwWko0ittr+/Uf79RHQMIP".to_string();
/// let share2 = "2-4-ChaydsUJDypD9ZWxwvIICh/cmZvzusOF".to_string();
/// let shares = vec![share1, share2];
///
/// match recover_secret(&shares, false) {
/// Ok(secret) => {
/// // Do something with the secret
/// },
/// Err(e) => {
/// // Deal with the error
/// }
/// }
/// ```
pub fn recover_secret(shares: &[String], verify_signatures: bool) -> Result<Vec<u8>> {
let shares = Share::parse_all(shares, verify_signatures)?;
SSS::recover_secret(shares, verify_signatures)
}

109
src/sss/scheme.rs Normal file
View File

@ -0,0 +1,109 @@
//! SSS provides Shamir's secret sharing with raw data.
use rand::{OsRng, Rng};
use merkle_sigs::sign_data_vec;
use errors::*;
use sss::{Share, HASH_ALGO};
use sss::format::format_share_for_signing;
use share::validation::{validate_share_count, validate_signed_shares};
use lagrange::interpolate_at;
use super::encode::encode_secret_byte;
/// SSS provides Shamir's secret sharing with raw data.
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
pub(crate) struct SSS;
impl SSS {
/// Performs threshold k-out-of-n Shamir's secret sharing.
pub fn split_secret(
&self,
threshold: u8,
shares_count: u8,
secret: &[u8],
sign_shares: bool,
) -> Result<Vec<Share>> {
let (threshold, shares_count) = validate_share_count(threshold, shares_count)?;
let shares = Self::secret_share(secret, threshold, shares_count)?;
let signatures = if sign_shares {
let shares_to_sign = shares
.iter()
.enumerate()
.map(|(i, x)| format_share_for_signing(threshold, (i + 1) as u8, x))
.collect::<Vec<_>>();
let sign = sign_data_vec(&shares_to_sign, HASH_ALGO)
.unwrap()
.into_iter()
.map(Some)
.collect::<Vec<_>>();
Some(sign)
} else {
None
};
let sig_pairs = signatures
.unwrap_or_else(|| vec![None; shares_count as usize])
.into_iter()
.map(|sig_pair| sig_pair.map(From::from));
let shares_and_sigs = shares.into_iter().enumerate().zip(sig_pairs);
let result = shares_and_sigs.map(|((index, data), signature_pair)| {
// This is actually safe since we alwaays generate less than 256 shares.
let id = (index + 1) as u8;
Share {
id,
threshold,
data,
signature_pair,
}
});
Ok(result.collect())
}
fn secret_share(src: &[u8], threshold: u8, shares_count: u8) -> Result<Vec<Vec<u8>>> {
let mut result = Vec::with_capacity(shares_count as usize);
for _ in 0..(shares_count as usize) {
result.push(vec![0u8; src.len()]);
}
let mut col_in = vec![0u8, threshold];
let mut col_out = Vec::with_capacity(shares_count as usize);
let mut osrng = OsRng::new()?;
for (c, &s) in src.iter().enumerate() {
col_in[0] = s;
osrng.fill_bytes(&mut col_in[1..]);
col_out.clear();
encode_secret_byte(&*col_in, shares_count, &mut col_out)?;
for (&y, share) in col_out.iter().zip(result.iter_mut()) {
share[c] = y;
}
}
Ok(result)
}
/// Recovers the secret from a k-out-of-n Shamir's secret sharing.
///
/// At least `k` distinct shares need to be provided to recover the share.
pub fn recover_secret(shares: Vec<Share>, verify_signatures: bool) -> Result<Vec<u8>> {
let (threshold, shares) = validate_signed_shares(shares, verify_signatures)?;
let slen = shares[0].data.len();
let mut col_in = Vec::with_capacity(threshold as usize);
let mut secret = Vec::with_capacity(slen);
for byteindex in 0..slen {
col_in.clear();
for s in shares.iter().take(threshold as usize) {
col_in.push((s.id, s.data[byteindex]));
}
secret.push(interpolate_at(&*col_in));
}
Ok(secret)
}
}

177
src/sss/share.rs Normal file
View File

@ -0,0 +1,177 @@
use std::error::Error;
use std::collections::{HashMap, HashSet};
use merkle_sigs::{MerklePublicKey, Proof};
use merkle_sigs::verify_data_vec_signature;
use errors::*;
use share::{IsShare, IsSignedShare};
use sss::format::{format_share_for_signing, share_from_string, share_to_string};
/// A share identified by an `id`, a threshold `k`, a number of total shares `n`,
/// the `data` held in the share, and the share's `metadata`.
// #[derive(Clone, Debug, Hash, PartialEq, Eq)]
// TODO: Write manual instances which ignore the signature / fix merkle_sigs+merkle.rs
#[derive(Clone, Debug)]
pub(crate) struct Share {
/// The identifier of the share (varies between 1 and n where n is the total number of generated shares)
pub id: u8,
/// The number of shares necessary to recover the secret, aka a threshold
pub threshold: u8,
/// The share data itself
pub data: Vec<u8>,
/// If the share is signed, this fields holds the signature
/// along with the proof of inclusion into the underlying MerkleTree.
pub signature_pair: Option<SignaturePair>,
}
impl Share {
/// Attempts to parse the given string into a share which should have the given `id`.
/// The string `raw` should follow the format of `Share::into_string`.
pub(crate) fn from_string(raw: &str, is_signed: bool) -> Result<Self> {
share_from_string(raw, is_signed)
}
/// Attempts to parse all the given strings into shares.
/// Calls out to `Share::from_string`.
pub(crate) fn parse_all(raws: &[String], is_signed: bool) -> Result<Vec<Share>> {
raws.into_iter()
.map(|raw| Self::from_string(raw, is_signed))
.collect()
}
/// Format the share as a string suitable for being stored in a file.
/// The format is the following:
///
/// ```text
/// 2-1-LiTyeXwEP71IUA
/// ^ ^ ^^^^^^^^^^^^^^
/// K N D
///
/// It is built out of three parts separated with a dash: K-N-D.
///
/// - K specifies the number of shares necessary to recover the secret.
/// - N is the identifier of the share and varies between 1 and n where
/// n is the total number of generated shares.
/// - D is a Base64 encoding of a ShareData protobuf containing
/// information about the share, and if signed, the signature.
/// ```
pub fn into_string(self) -> String {
share_to_string(
self.data,
self.threshold,
self.id,
self.signature_pair.map(Into::into),
)
}
}
impl IsShare for Share {
fn get_id(&self) -> u8 {
self.id
}
fn get_data(&self) -> &[u8] {
&self.data
}
fn get_threshold(&self) -> u8 {
self.threshold
}
fn get_shares_count(&self) -> Option<u8> {
None
}
}
impl IsSignedShare for Share {
type Signature = Option<SignaturePair>;
fn verify_signatures(shares: &[Self]) -> Result<()> {
let mut rh_compatibility_sets = HashMap::new();
for share in shares {
if !share.is_signed() {
bail!(ErrorKind::MissingSignature(share.get_id()));
}
let sig_pair = share.signature_pair.as_ref().unwrap();
let signature = &sig_pair.signature;
let proof = &sig_pair.proof;
let root_hash = &proof.root_hash;
verify_data_vec_signature(
format_share_for_signing(share.threshold, share.id, share.data.as_slice()),
&(signature.to_vec(), proof.clone()),
root_hash,
).map_err(|e| ErrorKind::InvalidSignature(share.id, String::from(e.description())))?;
rh_compatibility_sets
.entry(root_hash)
.or_insert_with(HashSet::new);
let rh_set = rh_compatibility_sets.get_mut(&root_hash).unwrap();
rh_set.insert(share.id);
}
let rh_sets = rh_compatibility_sets.keys().count();
match rh_sets {
0 => bail!(ErrorKind::EmptyShares),
1 => {} // All shares have the same roothash.
_ => {
bail! {
ErrorKind::IncompatibleSets(
rh_compatibility_sets
.values()
.map(|x| x.to_owned())
.collect(),
)
}
}
}
Ok(())
}
fn is_signed(&self) -> bool {
self.signature_pair.is_some()
}
fn get_signature(&self) -> &Self::Signature {
&self.signature_pair
}
}
#[derive(Clone, Debug)]
/// Holds the signature along with the proof of inclusion
/// in the underlying Merkle tree used in the Lamport signature scheme.
pub struct SignaturePair {
/// The signature
pub signature: Vec<Vec<u8>>,
/// The proof of inclusion
pub proof: Proof<MerklePublicKey>,
}
impl From<SignaturePair> for (Vec<Vec<u8>>, Proof<MerklePublicKey>) {
fn from(pair: SignaturePair) -> Self {
(pair.signature, pair.proof)
}
}
impl From<(Vec<Vec<u8>>, Proof<MerklePublicKey>)> for SignaturePair {
fn from(pair: (Vec<Vec<u8>>, Proof<MerklePublicKey>)) -> Self {
Self {
signature: pair.0,
proof: pair.1,
}
}
}
// TODO: Uncomment when re-implementating standard traits for `Share`
// impl Hash for SignaturePair {
// fn hash<H: Hasher>(&self, state: &mut H) {
// self.signature.hash(state);
// self.proof.root_hash.hash(state);
// }
// }

View File

@ -1 +0,0 @@
mod test_vectors;

View File

@ -1,102 +0,0 @@
use custom_error::{RustyError, RustyErrorTypes};
use merkle_sigs::verify_data_vec_signature;
use share_format;
use share_format::format_share_for_signing;
use std::collections::HashMap;
use std::error::Error;
type ProcessedShares = Result<(u8, Vec<(u8, Vec<u8>)>), RustyError>;
// The order of validation that we think makes the most sense is the following:
// 1) Validate shares individually
// 2) Validate duplicate shares share num && data
// 2) Validate group consistency
// 3) Validate other properties, in no specific order
pub fn process_and_validate_shares(shares_strings: Vec<String>,
verify_signatures: bool)
-> ProcessedShares {
let mut shares: Vec<(u8, Vec<u8>)> = Vec::new();
let mut k_compatibility_sets = HashMap::new();
let mut rh_compatibility_sets = HashMap::new();
for (counter, line) in shares_strings.iter().enumerate() {
let share_index = counter as u8;
let (share_data, k, n, sig_pair) = try!(share_format::share_from_string(line,
counter as u8,
verify_signatures));
if verify_signatures {
if sig_pair.is_none() {
return Err(RustyError::with_type(RustyErrorTypes::MissingSignature(share_index)));
}
let (signature, p) = sig_pair.unwrap();
let root_hash = p.root_hash.clone();
try!(verify_data_vec_signature(format_share_for_signing(k,
n,
&share_data.as_slice()),
&(signature.to_vec(), p),
&root_hash)
.map_err(|e| RustyError::with_type(RustyErrorTypes::InvalidSignature(share_index, String::from(e.description())))));
rh_compatibility_sets.entry(root_hash.clone()).or_insert_with(Vec::new);
let vec = rh_compatibility_sets.get_mut(&root_hash).unwrap();
vec.push(share_index);
}
k_compatibility_sets.entry(k).or_insert_with(Vec::new);
let vec = k_compatibility_sets.get_mut(&k).unwrap();
vec.push(share_index);
if shares.iter().any(|s| s.0 == n) {
return Err(RustyError::with_type(RustyErrorTypes::DuplicateShareNum(share_index)));
};
if shares.iter().any(|s| s.1 == share_data) && k != 1 { // When k = 1, shares data can be the same
return Err(RustyError::with_type(RustyErrorTypes::DuplicateShareData(share_index)));
};
shares.push((n, share_data));
}
// Validate k
let k_sets = k_compatibility_sets.keys().count();
let rh_sets = rh_compatibility_sets.keys().count();
if verify_signatures {
match rh_sets {
0 => {
return Err(RustyError::with_type(RustyErrorTypes::EmptyShares))
}
1 => { } // All shares have the same roothash.
_ => {
return Err(RustyError::with_type(RustyErrorTypes::IncompatibleSets(rh_compatibility_sets.values()
.map(|x| x.to_owned()).collect())))
}
}
}
match k_sets {
0 => {
return Err(RustyError::with_type(RustyErrorTypes::EmptyShares))
}
1 => { } // All shares have the same roothash.
_ => {
return Err(RustyError::with_type(RustyErrorTypes::IncompatibleSets(k_compatibility_sets.values()
.map(|x| x.to_owned()).collect())))
}
}
// It is safe to unwrap because k_sets == 1
let k = *k_compatibility_sets.keys().last().unwrap();
let shares_num = shares.len();
if shares_num >= k as usize {
shares.truncate(k as usize);
Ok((k, shares))
} else {
Err(RustyError::with_type(RustyErrorTypes::MissingShares(k, shares_num)))
}
}

55
src/vol_hash.rs Normal file
View File

@ -0,0 +1,55 @@
use std;
use std::mem::transmute;
use ring::digest::{Algorithm, Context};
#[allow(unsafe_code)]
fn u32_to_bytes(x: u32) -> [u8; 4] {
unsafe { transmute(x.to_be()) }
}
pub struct VOLHash {
algorithm: &'static Algorithm,
bytes: Vec<u8>,
}
impl VOLHash {
pub fn new(algorithm: &'static Algorithm) -> VOLHash {
Self {
algorithm,
bytes: Vec::new(),
}
}
pub fn process(&mut self, bytes: &[u8]) {
self.bytes.extend_from_slice(bytes)
}
pub fn finish(self, dest: &mut [u8]) {
let len = dest.len();
assert!(len < std::u32::MAX as usize);
let mut ctx = Context::new(self.algorithm);
ctx.update(&[0u8]);
ctx.update(&u32_to_bytes(len as u32));
ctx.update(&self.bytes);
let mut state = ctx.finish().as_ref().to_vec();
let iter_num = len / self.algorithm.output_len;
for i in 0..iter_num {
let mut inner_ctx = Context::new(self.algorithm);
inner_ctx.update(&[255u8]);
inner_ctx.update(&u32_to_bytes(1 + i as u32));
inner_ctx.update(&state);
state.extend_from_slice(inner_ctx.finish().as_ref())
}
assert!(state.len() >= len);
let src = state.drain(0..len).collect::<Vec<_>>();
dest.copy_from_slice(&src);
}
}

View File

@ -1,64 +0,0 @@
//! (Beta) `wrapped_secrets` provides Shamir's secret sharing with a wrapped secret. It currently offers versioning and MIME information about the data.
use custom_error::{RustyError, RustyErrorTypes};
use protobuf;
use protobuf::Message;
use secret::{RustySecret, RustySecretsVersions};
use sss;
use std::io;
/// Performs threshold k-out-of-n Shamir's secret sharing.
///
/// # Examples
///
/// ```
/// use rusty_secrets::wrapped_secrets::generate_shares;
/// let secret = "These programs were never about terrorism: theyre about economic spying,
/// social control, and diplomatic manipulation. Theyre about power.".to_string();
///
/// match generate_shares(7, 10, &secret.into_bytes(), Some("text/html".to_string()), true){
/// Ok(shares) => {
/// // Do something with the shares
/// },
/// Err(_) => {}// Deal with error}
/// }
/// ```
pub fn generate_shares(k: u8, n: u8, secret: &[u8], mime_type: Option<String>, sign_shares: bool) -> io::Result<Vec<String>> {
let mut rusty_secret = RustySecret::new();
rusty_secret.set_version(RustySecretsVersions::INITIAL_RELEASE);
rusty_secret.set_secret(secret.to_owned());
for mt in mime_type {
rusty_secret.set_mime_type(mt);
}
sss::generate_shares(k, n, rusty_secret.write_to_bytes().unwrap().as_slice(), sign_shares)
}
/// Recovers the secret from a k-out-of-n Shamir's secret sharing.
///
/// At least `k` distinct shares need to be provided to recover the share.
///
/// # Examples
///
/// ```
/// use rusty_secrets::wrapped_secrets::recover_secret;
/// let share1 = "2-1-Cha7s14Q/mSwWko0ittr+/Uf79RHQMIP".to_string();
/// let share2 = "2-4-ChaydsUJDypD9ZWxwvIICh/cmZvzusOF".to_string();
/// let shares = vec![share1, share2];
///
/// match recover_secret(shares, false) {
/// Ok(secret) => {
/// // Do something with the secret
/// },
/// Err(e) => {
/// // Deal with the error
/// }
/// }
/// ```
pub fn recover_secret(shares: Vec<String>, verify_signatures: bool) -> Result<RustySecret, RustyError> {
let secret = try!(sss::recover_secret(shares, verify_signatures));
protobuf::parse_from_bytes::<RustySecret>(secret.as_slice())
.map_err(|_| RustyError::with_type(RustyErrorTypes::SecretDeserializationIssue))
}

View File

@ -0,0 +1,73 @@
//! (Beta) `wrapped_secrets` provides Shamir's secret sharing with a wrapped secret. It currently offers versioning and MIME information about the data.
use errors::*;
use proto::wrapped::SecretProto;
mod scheme;
pub(crate) use self::scheme::*;
/// Performs threshold k-out-of-n Shamir's secret sharing.
///
/// # Examples
///
/// ```
/// use rusty_secrets::wrapped_secrets::split_secret;
///
/// let secret = "These programs were never about terrorism: theyre about economic spying, \
/// social control, and diplomatic manipulation. Theyre about power.";
///
/// let result = split_secret(
/// 7,
/// 10,
/// &secret.as_bytes(),
/// Some("text/html".to_string()),
/// true,
/// );
///
/// match result {
/// Ok(shares) => {
/// // Do something with the shares
/// },
/// Err(_) => {
/// // Deal with error
/// }
/// }
/// ```
pub fn split_secret(
k: u8,
n: u8,
secret: &[u8],
mime_type: Option<String>,
sign_shares: bool,
) -> Result<Vec<String>> {
WrappedSecrets::default()
.split_secret(k, n, secret, mime_type, sign_shares)
.map(|shares| shares.into_iter().map(Share::into_string).collect())
}
/// Recovers the secret from a k-out-of-n Shamir's secret sharing.
///
/// At least `k` distinct shares need to be provided to recover the share.
///
/// # Examples
///
/// ```rust
/// use rusty_secrets::wrapped_secrets::recover_secret;
///
/// let share1 = "2-1-Cha7s14Q/mSwWko0ittr+/Uf79RHQMIP".to_string();
/// let share2 = "2-4-ChaydsUJDypD9ZWxwvIICh/cmZvzusOF".to_string();
/// let shares = vec![share1, share2];
///
/// match recover_secret(&shares, false) {
/// Ok(secret) => {
/// // Do something with the secret
/// },
/// Err(e) => {
/// // Deal with the error
/// }
/// }
/// ```
pub fn recover_secret(shares: &[String], verify_signatures: bool) -> Result<SecretProto> {
let shares = Share::parse_all(shares, verify_signatures)?;
WrappedSecrets::recover_secret(shares, verify_signatures)
}

View File

@ -0,0 +1,45 @@
use errors::*;
use protobuf;
use protobuf::Message;
use proto::VersionProto;
use proto::wrapped::SecretProto;
use sss::SSS;
pub(crate) use sss::Share;
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
pub(crate) struct WrappedSecrets;
impl WrappedSecrets {
/// Performs threshold k-out-of-n Shamir's secret sharing.
pub fn split_secret(
&self,
k: u8,
n: u8,
secret: &[u8],
mime_type: Option<String>,
sign_shares: bool,
) -> Result<Vec<Share>> {
let mut rusty_secret = SecretProto::new();
rusty_secret.set_version(VersionProto::INITIAL_RELEASE);
rusty_secret.set_secret(secret.to_owned());
if let Some(mt) = mime_type {
rusty_secret.set_mime_type(mt);
}
let data = rusty_secret.write_to_bytes().unwrap();
SSS::default().split_secret(k, n, data.as_slice(), sign_shares)
}
/// Recovers the secret from a k-out-of-n Shamir's secret sharing.
///
/// At least `k` distinct shares need to be provided to recover the share.
pub fn recover_secret(shares: Vec<Share>, verify_signatures: bool) -> Result<SecretProto> {
let secret = SSS::recover_secret(shares, verify_signatures)?;
protobuf::parse_from_bytes::<SecretProto>(secret.as_slice())
.chain_err(|| ErrorKind::SecretDeserializationError)
}
}

3
tests/fixtures/gf256/.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
*.py
*.pyc
*.sage.py

18
tests/fixtures/gf256/Makefile vendored Normal file
View File

@ -0,0 +1,18 @@
SAGE = sage
TARGETS = gf256_add.txt.gz gf256_sub.txt.gz gf256_div.txt.gz gf256_mul.txt.gz gf256_pow.txt.gz
.PHONY: all clean
all: $(TARGETS)
%.txt.gz: %.sage common.py
$(SAGE) $< | gzip > $@
common.py: common.sage
$(SAGE) --preparse $<
mv common.sage.py common.py
clean:
$(RM) $(TARGETS) common.py

2
tests/fixtures/gf256/common.sage vendored Normal file
View File

@ -0,0 +1,2 @@
field = GF(2**8, name='a', modulus=x^8+x^4+x^3+x^2+1, repr='int')

5
tests/fixtures/gf256/gf256_add.sage vendored Normal file
View File

@ -0,0 +1,5 @@
from common import field
for i in sorted(field):
for j in sorted(field):
print("{} + {} = {}".format(i, j, i + j))

BIN
tests/fixtures/gf256/gf256_add.txt.gz vendored Normal file

Binary file not shown.

5
tests/fixtures/gf256/gf256_div.sage vendored Normal file
View File

@ -0,0 +1,5 @@
from common import field
for i in sorted(field):
for j in sorted(field)[1:]:
print("{} / {} = {}".format(i, j, i / j))

BIN
tests/fixtures/gf256/gf256_div.txt.gz vendored Normal file

Binary file not shown.

5
tests/fixtures/gf256/gf256_mul.sage vendored Normal file
View File

@ -0,0 +1,5 @@
from common import field
for i in sorted(field):
for j in sorted(field):
print("{} * {} = {}".format(i, j, i * j))

BIN
tests/fixtures/gf256/gf256_mul.txt.gz vendored Normal file

Binary file not shown.

5
tests/fixtures/gf256/gf256_pow.sage vendored Normal file
View File

@ -0,0 +1,5 @@
from common import field
for i in sorted(field):
for j in range(0, 256):
print("{} ^ {} = {}".format(i, j, i ^ j))

BIN
tests/fixtures/gf256/gf256_pow.txt.gz vendored Normal file

Binary file not shown.

5
tests/fixtures/gf256/gf256_sub.sage vendored Normal file
View File

@ -0,0 +1,5 @@
from common import field
for i in sorted(field):
for j in sorted(field):
print("{} - {} = {}".format(i, j, i - j))

BIN
tests/fixtures/gf256/gf256_sub.txt.gz vendored Normal file

Binary file not shown.

View File

@ -1,11 +1,11 @@
extern crate rusty_secrets;
use rusty_secrets::sss::generate_shares;
use rusty_secrets::sss;
#[test]
#[should_panic(expected = "Threshold K can not be larger than N")]
#[should_panic(expected = "ThresholdTooBig")]
fn test_generate_invalid_k() {
let share1 = "2-1-1YAYwmOHqZ69jA".to_string().into_bytes();
generate_shares(10, 5, share1.as_slice(), true).unwrap();
sss::split_secret(10, 5, share1.as_slice(), true).unwrap();
}

View File

@ -1,6 +1,6 @@
extern crate rusty_secrets;
use rusty_secrets::*;
use rusty_secrets::wrapped_secrets;
#[ignore]
#[test]
@ -19,12 +19,17 @@ fn test_reasonable_splits() {
for is_signing in &[true, false] {
for k in 1..max_shares {
for n in k..max_shares {
let shares = wrapped_secrets::generate_shares(k, n, &secret, Some(mime_type.clone()), *is_signing).unwrap();
let shares = wrapped_secrets::split_secret(
k,
n,
&secret,
Some(mime_type.clone()),
*is_signing,
).unwrap();
println!("Testing {} out-of- {}", k, n);
let s = wrapped_secrets::recover_secret(shares, *is_signing).unwrap();
let s = wrapped_secrets::recover_secret(&shares, *is_signing).unwrap();
assert_eq!(s.get_secret().to_owned(), secret);
assert!(s.has_mime_type());
assert_eq!(mime_type, s.get_mime_type());
}
}

View File

@ -3,92 +3,87 @@ extern crate rusty_secrets;
use rusty_secrets::sss::recover_secret;
#[test]
#[should_panic(expected = "No shares were provided.")]
#[should_panic(expected = "EmptyShares")]
fn test_recover_no_shares() {
let shares = vec![];
recover_secret(shares, false).unwrap();
for signed in &[true, false] {
let shares = vec![];
recover_secret(&shares, *signed).unwrap();
}
}
#[test]
#[should_panic(expected = "No shares were provided.")]
fn test_recover_no_shares_signed() {
let shares = vec![];
recover_secret(shares, true).unwrap();
}
#[test]
#[should_panic(expected = "This share is incorrectly formatted.")]
#[should_panic(expected = "ShareParsingError")]
fn test_recover_2_parts_share() {
let share1 = "2-1-CgmKQZHMO+5n5pU".to_string();
let share2 = "2-2".to_string();
let shares = vec![share1, share2];
recover_secret(shares, false).unwrap();
recover_secret(&shares, false).unwrap();
}
#[test]
#[should_panic(expected = "Integer parsing error")]
#[should_panic(expected = "IntegerParsingError")]
fn test_recover_incorrect_share_num() {
let share1 = "2-1-CgnlCxRNtnkzENE".to_string();
let share2 = "2-DEFINITLY_NAN-CgkAnUgP3lfwjyM".to_string();
let shares = vec![share1, share2];
recover_secret(shares, false).unwrap();
recover_secret(&shares, false).unwrap();
}
#[test]
#[should_panic(expected = "This share is incorrectly formatted.")]
#[should_panic(expected = "ShareParsingError")]
fn test_recover_0_share_num() {
let share1 = "2-0-1YAYwmOHqZ69jA".to_string();
let share2 = "2-1-YJZQDGm22Y77Gw".to_string();
let shares = vec![share1, share2];
recover_secret(shares, false).unwrap();
recover_secret(&shares, false).unwrap();
}
#[test]
#[should_panic(expected = "This share is incorrectly formatted.")]
#[should_panic(expected = "ShareParsingError")]
fn test_recover_invalid_b64() {
let share1 = "2-1-CgnlCxRNtnkzENE".to_string();
let share2 = "2-1-YJZQDG((((m22Y)))77Gw".to_string();
let share2 = "2-2-YJZQDG((((m22Y)))77Gw".to_string();
let shares = vec![share1, share2];
recover_secret(shares, false).unwrap();
recover_secret(&shares, false).unwrap();
}
#[test]
#[should_panic(expected = "This share number has already been used by a previous share.")]
#[should_panic(expected = "DuplicateShareId")]
fn test_recover_duplicate_shares_number() {
let share1 = "2-1-CgnlCxRNtnkzENE".to_string();
let share2 = "2-1-CgkAnUgP3lfwjyM".to_string();
let shares = vec![share1, share2];
recover_secret(shares, false).unwrap();
recover_secret(&shares, false).unwrap();
}
#[test]
#[should_panic(expected = "The data encoded in this share is the same as the one found in a previous share.")]
#[should_panic(expected = "DuplicateShareData")]
fn test_recover_duplicate_shares_data() {
let share1 = "2-1-CgnlCxRNtnkzENE".to_string();
let share2 = "2-2-CgnlCxRNtnkzENE".to_string();
let shares = vec![share1, share2];
recover_secret(shares, false).unwrap();
recover_secret(&shares, false).unwrap();
}
#[test]
#[should_panic(expected = "The number of shares provided is insufficient to recover the secret.")]
#[should_panic(expected = "MissingShares")]
fn test_recover_too_few_shares() {
let share1 = "3-1-ChbcCdSZOaMn6DM1jFca2P6/0WRlP7AK".to_string();
let share2 = "3-2-ChbG46L1zRszs0PPn63XnnupmZTcgYJ3".to_string();
let shares = vec![share1, share2];
recover_secret(shares, false).unwrap();
recover_secret(&shares, false).unwrap();
}

View File

@ -0,0 +1,188 @@
#![cfg(feature = "dss")]
extern crate rusty_secrets;
use rusty_secrets::dss::ss1::{recover_secret, split_secret, Reproducibility, Share};
const TEST_THRESHOLD: u8 = 2;
const TEST_SHARES_COUNT: u8 = 2;
const TEST_REPRODUCIBILITY: Reproducibility = Reproducibility::Reproducible;
const TEST_SECRET: &[u8] =
b"These programs were never about terrorism: they're about economic spying, \
social control, and diplomatic manipulation. They're about power.";
fn get_test_hash() -> Vec<u8> {
let good_shares = split_secret(
TEST_THRESHOLD,
TEST_SHARES_COUNT,
TEST_SECRET,
TEST_REPRODUCIBILITY,
&None,
).unwrap();
good_shares[0].hash.clone()
}
#[test]
#[should_panic(expected = "EmptyShares")]
fn test_recover_no_shares() {
let shares = vec![];
recover_secret(&shares).unwrap();
}
#[test]
#[should_panic(expected = "ShareParsingErrorEmptyShare")]
fn test_recover_2_parts_share() {
let hash = get_test_hash();
let share1 = Share {
id: 1,
threshold: TEST_THRESHOLD,
shares_count: TEST_SHARES_COUNT,
data: "CgmKQZHMO+5n5pU".to_string().into_bytes(),
hash: hash.clone(),
metadata: None,
};
let share2 = Share {
id: 2,
threshold: TEST_THRESHOLD,
shares_count: TEST_SHARES_COUNT,
data: "".to_string().into_bytes(),
hash: hash.clone(),
metadata: None,
};
let shares = vec![share1, share2];
recover_secret(&shares).unwrap();
}
#[test]
#[should_panic(expected = "ShareParsingInvalidShareId")]
fn test_recover_0_share_num() {
let hash = get_test_hash();
let share1 = Share {
id: 0,
threshold: TEST_THRESHOLD,
shares_count: TEST_SHARES_COUNT,
data: "1YAYwmOHqZ69jA".to_string().into_bytes(),
hash: hash.clone(),
metadata: None,
};
let share2 = Share {
id: 1,
threshold: TEST_THRESHOLD,
shares_count: TEST_SHARES_COUNT,
data: "YJZQDGm22Y77Gw".to_string().into_bytes(),
hash: hash.clone(),
metadata: None,
};
let shares = vec![share1, share2];
recover_secret(&shares).unwrap();
}
// ---
// TODO: will be implemented when serialization is done for ss1 shares
// ---
// #[test]
// #[should_panic(expected = "ShareParsingError")]
// fn test_recover_invalid_b64() {
// let share1 = Share {
// id: 1,
// threshold: 2,
// shares_count: 2,
// data: "1YAYwmOHqZ69jA".to_string().into_bytes(),
// metadata: None
// };
// let share2 = Share {
// id: 2,
// threshold: 2,
// shares_count: 2,
// data: "YJZQDG((((m22Y)))77Gw".to_string().into_bytes(),
// metadata: None
// };
//
// let shares = vec![share1, share2];
//
// recover_secret(&shares).unwrap();
// }
#[test]
#[should_panic(expected = "DuplicateShareId")]
fn test_recover_duplicate_shares_number() {
let hash = get_test_hash();
let share1 = Share {
id: 1,
threshold: TEST_THRESHOLD,
shares_count: TEST_SHARES_COUNT,
data: "1YAYwmOHqZ69jA".to_string().into_bytes(),
hash: hash.clone(),
metadata: None,
};
let share2 = Share {
id: 1,
threshold: TEST_THRESHOLD,
shares_count: TEST_SHARES_COUNT,
data: "YJZQDGm22Y77Gw".to_string().into_bytes(),
hash: hash.clone(),
metadata: None,
};
let shares = vec![share1, share2];
recover_secret(&shares).unwrap();
}
#[test]
#[should_panic(expected = "DuplicateShareData")]
fn test_recover_duplicate_shares_data() {
let hash = get_test_hash();
let share1 = Share {
id: 1,
threshold: TEST_THRESHOLD,
shares_count: TEST_SHARES_COUNT,
data: "1YAYwmOHqZ69jA".to_string().into_bytes(),
hash: hash.clone(),
metadata: None,
};
let share2 = Share {
id: 2,
threshold: TEST_THRESHOLD,
shares_count: TEST_SHARES_COUNT,
data: "1YAYwmOHqZ69jA".to_string().into_bytes(),
hash: hash.clone(),
metadata: None,
};
let shares = vec![share1, share2];
recover_secret(&shares).unwrap();
}
#[test]
#[should_panic(expected = "MissingShares")]
fn test_recover_too_few_shares() {
let hash = get_test_hash();
let share1 = Share {
id: 1,
threshold: TEST_THRESHOLD + 1,
shares_count: TEST_SHARES_COUNT + 1,
data: "1YAYwmOHqZ69jA".to_string().into_bytes(),
hash: hash.clone(),
metadata: None,
};
let share2 = Share {
id: 2,
threshold: TEST_THRESHOLD + 1,
shares_count: TEST_SHARES_COUNT + 1,
data: "YJZQDGm22Y77Gw".to_string().into_bytes(),
hash: hash.clone(),
metadata: None,
};
let shares = vec![share1, share2];
recover_secret(&shares).unwrap();
}

View File

@ -1,21 +1,22 @@
extern crate base64;
extern crate protobuf;
extern crate rustc_serialize as serialize;
extern crate rusty_secrets;
use protobuf::Message;
use share_data;
use sss::recover_secret;
use serialize::base64::{self, FromBase64, ToBase64};
use rusty_secrets::proto::wrapped::ShareProto;
use rusty_secrets::sss::recover_secret;
const BASE64_CONFIG: base64::Config = base64::STANDARD_NO_PAD;
pub fn wrap_from_sellibitze(share: &str) -> String {
let parts: Vec<_> = share.trim().split('-').collect();
let share_data = parts[2].from_base64().unwrap();
let share_data = base64::decode_config(parts[2], BASE64_CONFIG).unwrap();
let config = base64::Config { pad: false, ..base64::STANDARD };
let mut share_protobuf = share_data::ShareData::new();
let mut share_protobuf = ShareProto::new();
share_protobuf.set_shamir_data(share_data);
let b64_share = share_protobuf.write_to_bytes().unwrap().to_base64(config);
let b64_share = base64::encode_config(&share_protobuf.write_to_bytes().unwrap(), BASE64_CONFIG);
format!("{}-{}-{}", parts[0], parts[1], b64_share)
}
@ -25,48 +26,47 @@ fn test_recover_sellibitze() {
let share1 = "2-1-1YAYwmOHqZ69jA";
let share2 = "2-4-F7rAjX3UOa53KA";
let shares = vec![share1, share2].iter().map(|x| wrap_from_sellibitze(x)).collect::<Vec<_>>();
let shares = vec![share1, share2]
.iter()
.map(|x| wrap_from_sellibitze(x))
.collect::<Vec<_>>();
let mut secret = "My secret".to_string().into_bytes();
secret.push(10);
assert_eq!(recover_secret(shares, false).unwrap(), secret);
assert_eq!(recover_secret(&shares, false).unwrap(), secret);
}
// Generated with code on master branch on the 6th of April.
#[test]
fn test_recover_es_test_vectors() {
let share1 =
"5-1-DbuicpLQiCf7bVWiAz8eCpQGpdZmYQ7z2j2+g351tWFLOQPTZkXY8BYfwGGGjkOoz1g9x0ScmLFcWk+2tign"
.to_string();
"5-1-DbuicpLQiCf7bVWiAz8eCpQGpdZmYQ7z2j2+g351tWFLOQPTZkXY8BYfwGGGjkOoz1g9x0ScmLFcWk+2tign";
let share2 =
"5-2-nShdfkY5+SlfybMyqjHXCZ01bq5N/0Lkf0nQZw5x3bnHIEVfa0RA4YcJ4SjG/UdpgO/gOcyLRkSp2Dwf8bvw"
.to_string();
"5-2-nShdfkY5+SlfybMyqjHXCZ01bq5N/0Lkf0nQZw5x3bnHIEVfa0RA4YcJ4SjG/UdpgO/gOcyLRkSp2Dwf8bvw";
let share3 =
"5-3-qEhJ3IVEdbDkiRoy+jOJ/KuGE9jWyGeOYEcDwPfEV8E9rfD1Bc17BQAbJ51Xd8oexS2M1qMvNgJHZUQZbUgQ"
.to_string();
"5-3-qEhJ3IVEdbDkiRoy+jOJ/KuGE9jWyGeOYEcDwPfEV8E9rfD1Bc17BQAbJ51Xd8oexS2M1qMvNgJHZUQZbUgQ";
let share4 =
"5-6-yyVPUeaYPPiWK0wIV5OQ/t61V0lSEO+7X++EWeHRlIq3sRBNwUpKNfx/C+Vc9xTzUftrqBKvkWDZQal7nyi2"
.to_string();
"5-6-yyVPUeaYPPiWK0wIV5OQ/t61V0lSEO+7X++EWeHRlIq3sRBNwUpKNfx/C+Vc9xTzUftrqBKvkWDZQal7nyi2";
let share5 =
"5-7-i8iL6bVf272B3qIjp0QqSny6AIm+DkP7oQjkVVLvx9EMhlvd4HJOxPpmtNF/RjA/zz21d7DY/B//saOPpBQa"
.to_string();
"5-7-i8iL6bVf272B3qIjp0QqSny6AIm+DkP7oQjkVVLvx9EMhlvd4HJOxPpmtNF/RjA/zz21d7DY/B//saOPpBQa";
let shares = vec![share1, share2, share3, share4, share5]
.iter()
.map(|x| wrap_from_sellibitze(x))
.collect::<Vec<_>>();
let secret =
"The immoral cannot be made moral through the use of secret law.".to_string().into_bytes();
assert_eq!(recover_secret(shares, false).unwrap(), secret);
let secret = "The immoral cannot be made moral through the use of secret law."
.to_string()
.into_bytes();
assert_eq!(recover_secret(&shares, false).unwrap(), secret);
}
#[test]
fn test_recover_sellibitze_more_than_threshold_shars() {
let share1 = "2-1-1YAYwmOHqZ69jA".to_string();
let share2 = "2-4-F7rAjX3UOa53KA".to_string();
let share3 = "2-2-YJZQDGm22Y77Gw".to_string();
let share4 = "2-5-j0P4PHsw4lW+rg".to_string();
let share1 = "2-1-1YAYwmOHqZ69jA";
let share2 = "2-4-F7rAjX3UOa53KA";
let share3 = "2-2-YJZQDGm22Y77Gw";
let share4 = "2-5-j0P4PHsw4lW+rg";
let shares = vec![share1, share2, share3, share4]
.iter()
@ -75,5 +75,5 @@ fn test_recover_sellibitze_more_than_threshold_shars() {
let mut secret = "My secret".to_string().into_bytes();
secret.push(10);
assert_eq!(recover_secret(shares, false).unwrap(), secret);
assert_eq!(recover_secret(&shares, false).unwrap(), secret);
}

View File

@ -0,0 +1,14 @@
#![cfg(feature = "dss")]
extern crate rusty_secrets;
use rusty_secrets::dss::thss;
#[test]
#[should_panic(expected = "ThresholdTooBig")]
fn test_generate_invalid_k() {
let secret = b"These programs were never about terrorism: they're about economic spying, \
social control, and diplomatic manipulation. They're about power.";
thss::split_secret(10, 7, secret, &None).unwrap();
}

View File

@ -0,0 +1,153 @@
#![cfg(feature = "dss")]
extern crate rusty_secrets;
use rusty_secrets::dss::thss::{recover_secret, Share};
#[test]
#[should_panic(expected = "EmptyShares")]
fn test_recover_no_shares() {
let shares = vec![];
recover_secret(&shares).unwrap();
}
#[test]
#[should_panic(expected = "ShareParsingErrorEmptyShare")]
fn test_recover_2_parts_share() {
let share1 = Share {
id: 1,
threshold: 2,
shares_count: 2,
data: "CgmKQZHMO+5n5pU".to_string().into_bytes(),
metadata: None,
};
let share2 = Share {
id: 2,
threshold: 2,
shares_count: 2,
data: "".to_string().into_bytes(),
metadata: None,
};
let shares = vec![share1, share2];
recover_secret(&shares).unwrap();
}
#[test]
#[should_panic(expected = "ShareParsingInvalidShareId")]
fn test_recover_0_share_num() {
let share1 = Share {
id: 0,
threshold: 2,
shares_count: 2,
data: "1YAYwmOHqZ69jA".to_string().into_bytes(),
metadata: None,
};
let share2 = Share {
id: 1,
threshold: 2,
shares_count: 2,
data: "YJZQDGm22Y77Gw".to_string().into_bytes(),
metadata: None,
};
let shares = vec![share1, share2];
recover_secret(&shares).unwrap();
}
// ---
// TODO: will be implemented when serialization is done for thss shares
// ---
// #[test]
// #[should_panic(expected = "ShareParsingError")]
// fn test_recover_invalid_b64() {
// let share1 = Share {
// id: 1,
// threshold: 2,
// shares_count: 2,
// data: "1YAYwmOHqZ69jA".to_string().into_bytes(),
// metadata: None
// };
// let share2 = Share {
// id: 2,
// threshold: 2,
// shares_count: 2,
// data: "YJZQDG((((m22Y)))77Gw".to_string().into_bytes(),
// metadata: None
// };
//
// let shares = vec![share1, share2];
//
// recover_secret(&shares).unwrap();
// }
#[test]
#[should_panic(expected = "DuplicateShareId")]
fn test_recover_duplicate_shares_number() {
let share1 = Share {
id: 1,
threshold: 2,
shares_count: 2,
data: "1YAYwmOHqZ69jA".to_string().into_bytes(),
metadata: None,
};
let share2 = Share {
id: 1,
threshold: 2,
shares_count: 2,
data: "YJZQDGm22Y77Gw".to_string().into_bytes(),
metadata: None,
};
let shares = vec![share1, share2];
recover_secret(&shares).unwrap();
}
#[test]
#[should_panic(expected = "DuplicateShareData")]
fn test_recover_duplicate_shares_data() {
let share1 = Share {
id: 1,
threshold: 2,
shares_count: 2,
data: "1YAYwmOHqZ69jA".to_string().into_bytes(),
metadata: None,
};
let share2 = Share {
id: 2,
threshold: 2,
shares_count: 2,
data: "1YAYwmOHqZ69jA".to_string().into_bytes(),
metadata: None,
};
let shares = vec![share1, share2];
recover_secret(&shares).unwrap();
}
#[test]
#[should_panic(expected = "MissingShares")]
fn test_recover_too_few_shares() {
let share1 = Share {
id: 1,
threshold: 3,
shares_count: 3,
data: "1YAYwmOHqZ69jA".to_string().into_bytes(),
metadata: None,
};
let share2 = Share {
id: 2,
threshold: 3,
shares_count: 3,
data: "YJZQDGm22Y77Gw".to_string().into_bytes(),
metadata: None,
};
let shares = vec![share1, share2];
recover_secret(&shares).unwrap();
}