commit afc02e2253d88857f6b73c24b6d931aa6ad86219 Author: Romain Ruetschi Date: Wed Feb 14 16:12:53 2018 +0100 Initial implementation for RustySecrets v0.1.0 diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f2e972d --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +# Generated by Cargo +# will have compiled files and executables +/target/ + +# These are backup files generated by rustfmt +**/*.rs.bk diff --git a/.rustfmt.toml b/.rustfmt.toml new file mode 100644 index 0000000..0173980 --- /dev/null +++ b/.rustfmt.toml @@ -0,0 +1,2 @@ +error_on_line_overflow = false +max_width = 120 diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..29911d4 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,21 @@ +language: rust + +os: + - linux + - osx + +rust: + - stable + - beta + - nightly + +cache: cargo + +before_cache: + # Travis can't cache files that are not readable by "others" + - chmod -R a+r $HOME/.cargo + +matrix: + allow_failures: + - rust: nightly + diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..981a12c --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,10 @@ +# Changelog + +## [Unreleased](https://github.com/SpinResearch/rustysecrets-cli/compare/0.1.0...master) + +> Nothing yet. + +## [0.1.0](https://github.com/SpinResearch/rustysecrets-cli/releases/tag/0.1.0) - 2017-08-02 **(alpha release)** + +> First alpha release + diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..6961beb --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,666 @@ +[[package]] +name = "ansi_term" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "atty" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "backtrace" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)", + "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "backtrace-sys" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (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]] +name = "bitflags" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "bitflags" +version = "1.0.1" +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.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cfg-if" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "clap" +version = "2.30.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", + "textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "cmake" +version = "0.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.4 (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.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 = "colored" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "either" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "error-chain" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "fuchsia-zircon" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", + "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "fuchsia-zircon-sys" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "gcc" +version = "0.3.54" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "gdi32-sys" +version = "0.2.0" +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 = "git-build-version" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "git2 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)", + "quick-error 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "git2" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "libgit2-sys 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "idna" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-normalization 0.1.5 (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.22 (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.36" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "libgit2-sys" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)", + "gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)", + "openssl-sys 0.7.17 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libressl-pnacl-sys" +version = "2.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "pnacl-build-helper 1.4.11 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "libz-sys" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "log" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "matches" +version = "0.1.6" +source = "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.3 (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.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "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 = "mime" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicase 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num_cpus" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "openssl-sys" +version = "0.7.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "libressl-pnacl-sys 2.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", + "user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "percent-encoding" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "pkg-config" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "pnacl-build-helper" +version = "1.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "tempdir 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", + "walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "protobuf" +version = "1.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "quick-error" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rand" +version = "0.3.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rand" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rayon" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rayon-core 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rayon-core" +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)", + "lazy_static 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "redox_syscall" +version = "0.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "redox_termios" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "remove_dir_all" +version = "0.3.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)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "ring" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "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.36 (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-demangle" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "rusty_secrets" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +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)", + "merkle_sigs 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "protobuf 1.4.3 (registry+https://github.com/rust-lang/crates.io-index)", + "rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)", + "ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "rustysecrets-cli" +version = "0.1.0-pre" +dependencies = [ + "clap 2.30.0 (registry+https://github.com/rust-lang/crates.io-index)", + "colored 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "git-build-version 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)", + "mime 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "rusty_secrets 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "tempdir 0.3.6 (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 = "same-file" +version = "0.1.3" +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)", + "winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "scopeguard" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "strsim" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "tempdir" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "remove_dir_all 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "termion" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "textwrap" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicase" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-bidi" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-normalization" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-width" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "untrusted" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "url" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", + "matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", + "percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "user32-sys" +version = "0.2.0" +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 = "vcpkg" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "vec_map" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "version_check" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "walkdir" +version = "1.0.7" +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)", + "same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.2.8 (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" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi-x86_64-pc-windows-gnu 0.4.0 (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" + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[metadata] +"checksum ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6b3568b48b7cefa6b8ce125f9bb4989e52fbcc29ebea88df04cc7c5f12f70455" +"checksum atty 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8352656fd42c30a0c3c89d26dea01e3b77c0ab2af18230835c15e2e13cd51859" +"checksum backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "ebbbf59b1c43eefa8c3ede390fcc36820b4999f7914104015be25025e0d62af2" +"checksum backtrace-sys 0.1.16 (registry+https://github.com/rust-lang/crates.io-index)" = "44585761d6161b0f57afc49482ab6bd067e4edef48c12a152c237eb0203f7661" +"checksum base64 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "229d032f1a99302697f10b27167ae6d03d49d032e6a8e2550e8d3fc13356d2b4" +"checksum bitflags 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2a6577517ecd0ee0934f48a7295a89aaef3e6dfafeac404f94c0b3448518ddfe" +"checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf" +"checksum byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "652805b7e73fada9d85e9a6682a4abd490cb52d96aeecc12e33a0de34dfd0d23" +"checksum cc 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "deaf9ec656256bb25b404c51ef50097207b9cbb29c933d31f92cae5a8a0ffee0" +"checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de" +"checksum clap 2.30.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1c07b9257a00f3fc93b7f3c417fc15607ec7a56823bc2c37ec744e266387de5b" +"checksum cmake 0.1.29 (registry+https://github.com/rust-lang/crates.io-index)" = "56d741ea7a69e577f6d06b36b7dff4738f680593dc27a701ffa8506b73ce28bb" +"checksum coco 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "c06169f5beb7e31c7c67ebf5540b8b472d23e3eade3b2ec7d1f5b504a85f91bd" +"checksum colored 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b0aa3473e85a3161b59845d6096b289bb577874cafeaf75ea1b1beaa6572c7fc" +"checksum either 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "740178ddf48b1a9e878e6d6509a1442a2d42fd2928aae8e7a6f8a36fb01981b3" +"checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" +"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" +"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" +"checksum gcc 0.3.54 (registry+https://github.com/rust-lang/crates.io-index)" = "5e33ec290da0d127825013597dbdfc28bee4964690c7ce1166cbc2a7bd08b1bb" +"checksum gdi32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0912515a8ff24ba900422ecda800b52f4016a56251922d397c576bf92c690518" +"checksum git-build-version 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "c6b55fb1209e98deef256214972a0bff1341eaf6773390a9ebebb9276c3aef1e" +"checksum git2 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "33a96eeef227403006cdb59ea6e05baad8cddde6b79abed753d96ccee136bad2" +"checksum idna 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "014b298351066f1512874135335d62a789ffe78a9974f94b43ed5621951eaf7d" +"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.36 (registry+https://github.com/rust-lang/crates.io-index)" = "1e5d97d6708edaa407429faa671b942dc0f2727222fb6b6539bf1db936e4b121" +"checksum libgit2-sys 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)" = "8f8d1217daf6e0812f78c3b81b987b94edc000e8f700aee456c6e7940f818b3e" +"checksum libressl-pnacl-sys 2.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "cbc058951ab6a3ef35ca16462d7642c4867e6403520811f28537a4e2f2db3e71" +"checksum libz-sys 1.0.18 (registry+https://github.com/rust-lang/crates.io-index)" = "87f737ad6cc6fd6eefe3d9dc5412f1573865bded441300904d2f42269e140f16" +"checksum log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "89f010e843f2b1a31dbd316b3b8d443758bc634bed37aabade59c686d644e0a2" +"checksum matches 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "100aabe6b8ff4e4a7e32c1c13523379802df0772b82466207ac25b013f193376" +"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 mime 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e2e00e17be181010a91dbfefb01660b17311059dc8c7f48b9017677721e732bd" +"checksum num_cpus 1.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c51a3322e4bca9d212ad9a158a02abc6934d005490c054a2778df73a70aa0a30" +"checksum openssl-sys 0.7.17 (registry+https://github.com/rust-lang/crates.io-index)" = "89c47ee94c352eea9ddaf8e364be7f978a3bb6d66d73176572484238dd5a5c3f" +"checksum percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "31010dd2e1ac33d5b46a5b413495239882813e0369f8ed8a5e266f173602f831" +"checksum pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "3a8b4c6b8165cd1a1cd4b9b120978131389f64bdaf456435caa41e630edba903" +"checksum pnacl-build-helper 1.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "dfbe13ee77c06fb633d71c72438bd983286bb3521863a753ade8e951c7efb090" +"checksum protobuf 1.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bec26e67194b7d991908145fdf21b7cae8b08423d96dcb9e860cd31f854b9506" +"checksum quick-error 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "5fb6ccf8db7bbcb9c2eae558db5ab4f3da1c2a87e4e597ed394726bc8ea6ca1d" +"checksum rand 0.3.22 (registry+https://github.com/rust-lang/crates.io-index)" = "15a732abf9d20f0ad8eeb6f909bf6868722d9a06e1e50802b6a70351f40b4eb1" +"checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5" +"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 redox_syscall 0.1.37 (registry+https://github.com/rust-lang/crates.io-index)" = "0d92eecebad22b767915e4d529f89f28ee96dbbf5a4810d2b844373f136417fd" +"checksum redox_termios 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7e891cfe48e9100a70a3b6eb652fef28920c117d366339687bd5576160db0f76" +"checksum remove_dir_all 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b5d2f806b0fcdabd98acd380dc8daef485e22bcb7cddc811d1337967f2528cf5" +"checksum ring 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6f7d28b30a72c01b458428e0ae988d4149c20d902346902be881e3edc4bb325c" +"checksum rustc-demangle 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "aee45432acc62f7b9a108cc054142dac51f979e69e71ddce7d6fc7adf29e817e" +"checksum rusty_secrets 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d6bf3e7412367e6c177a5dcdcafc448e7b8d3c6d56d4d45aaa93a20fe192b3fb" +"checksum safemem 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e27a8b19b835f7aea908818e871f5cc3a5a186550c30773be987e155e8163d8f" +"checksum same-file 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d931a44fdaa43b8637009e7632a02adc4f2b2e0733c08caa4cf00e8da4a117a7" +"checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27" +"checksum strsim 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb4f380125926a99e52bc279241539c018323fab05ad6368b56f93d9369ff550" +"checksum tempdir 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f73eebdb68c14bcb24aef74ea96079830e7fa7b31a6106e42ea7ee887c1e134e" +"checksum termion 1.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "689a3bdfaab439fd92bc87df5c4c78417d3cbe537487274e9b0b2dce76e92096" +"checksum textwrap 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "c0b59b6b4b44d867f1370ef1bd91bfb262bf07bf0ae65c202ea2fbc16153b693" +"checksum unicase 2.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "284b6d3db520d67fbe88fd778c21510d1b0ba4a551e5d0fbb023d33405f6de8a" +"checksum unicode-bidi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "49f2bd0c6468a8230e1db229cff8029217cf623c767ea5d60bfbd42729ea54d5" +"checksum unicode-normalization 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "51ccda9ef9efa3f7ef5d91e8f9b83bbe6955f9bf86aec89d5cce2c874625920f" +"checksum unicode-width 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)" = "bf3a113775714a22dcb774d8ea3655c53a32debae63a063acc00a91cc586245f" +"checksum untrusted 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f392d7819dbe58833e26872f5f6f0d68b7bbbe90fc3667e98731c4a15ad9a7ae" +"checksum url 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fa35e768d4daf1d85733418a49fb42e10d7f633e394fccab4ab7aba897053fe2" +"checksum user32-sys 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "4ef4711d107b21b410a3a974b1204d9accc8b10dad75d8324b5d755de1617d47" +"checksum vcpkg 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9e0a7d8bed3178a8fb112199d466eeca9ed09a14ba8ad67718179b4fd5487d0b" +"checksum vec_map 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "887b5b631c2ad01628bbbaa7dd4c869f80d3186688f8d0b6f58774fbe324988c" +"checksum version_check 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "6b772017e347561807c1aa192438c5fd74242a670a6cffacc40f2defd1dc069d" +"checksum walkdir 1.0.7 (registry+https://github.com/rust-lang/crates.io-index)" = "bb08f9e670fab86099470b97cd2b252d6527f0b3cc1401acdb595ffc9dd288ff" +"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a" +"checksum winapi 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "04e3bd221fcbe8a271359c04f21a76db7d0c6028862d1bb5512d85e1e2eb5bb3" +"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc" +"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..4204099 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,47 @@ +[package] +name = "rustysecrets-cli" +version = "0.1.0-pre" +authors = ["Romain Ruetschi "] + +description = "rustysecrets-cli is a command-line wrapper around RustySecrets, a Rust implementation of threshold Shamir's secret sharing" +license = "BSD-3-Clause" +readme = "README.md" +homepage = "https://github.com/SpinResearch/rustysecrets-cli" +documentation = "https://github.com/SpinResearch/rustysecrets-cli#readme" +repository = "https://github.com/SpinResearch/rustysecrets-cli" + +build = "build.rs" + +[[bin]] +name = "rustysecrets" +path = "src/main.rs" + +[dependencies] +rusty_secrets = "^0.1.0" +clap = "^2.26" +colored = "^1.5" +error-chain = "^0.11.0" +mime = "^0.3" +log = { version = "^0.4", features = ["std"] } + +[dev-dependencies] +tempdir = "^0.3" +colored = "^1.5" + +[build-dependencies] +clap = "^2.26" +mime = "^0.3" +git-build-version = "*" + +[profile.release] +lto = true + +[package.metadata.release] +sign-commit = true +upload-doc = false +pre-release-commit-message = "Release version {{version}}" +pro-release-commit-message = "Bump version to {{version}}" +tag-message = "Release version {{version}}" +tag-prefix = "v" +dev-version-ext = "pre" + diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..887b1fa --- /dev/null +++ b/LICENSE @@ -0,0 +1,29 @@ +BSD 3-Clause License + +Copyright (c) 2018, Spin Research +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +* Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..6be4ffb --- /dev/null +++ b/README.md @@ -0,0 +1,108 @@ + +# RustySecrets CLI + +[![Build Status](https://travis-ci.org/SpinResearch/rustysecrets-cli.svg?branch=master&style=flat)](https://travis-ci.org/SpinResearch/rustysecrets-cli) +[![Crates.io](https://img.shields.io/crates/v/rustysecrets-cli.svg)](https://crates.io/crates/rustysecrets-cli) +[![license](https://img.shields.io/github/license/SpinResearch/rustysecrets-cli.svg)](License) + +> *rustysecrets-cli* is a command-line wrapper around [RustySecrets](https://github.com/SpinResearch/RustySecrets), a Rust implementation of threshold [Shamir's secret sharing](https://en.wikipedia.org/wiki/Shamir%27s_Secret_Sharing). + +## Installation + + $ cargo install rustysecrets-cli + +## Usage + +```bash +$ mkdir shares +$ cat > secret.txt +These programs were never about terrorism: they’re about economic spying, +social control, and diplomatic manipulation. They’re about power. +^D + +$ rustysecrets split secret.txt -o shares -k 7 -n 10 -m text/plain +$ ls shares/ +share_0 share_1 share_2 share_3 share_4 share_5 share_6 share_7 share_8 share_9 + +$ rustysecrets recover shares/share_{0-6} + info: Version: INITIAL_RELEASE + info: MIME-Type: text/plain +These programs were never about terrorism: they’re about economic spying, +social control, and diplomatic manipulation. They’re about power. + +$ rustysecrets recover shares/share_{0-2} + error: Could not recover secret +caused by: Not enough shares provided! +``` + +## Documentation + +### `rustysecrets` + +``` +USAGE: + rustysecrets + +OPTIONS: + -h, --help Prints help information + -V, --version Prints version information + +SUBCOMMANDS: + help Prints this message or the help of the given subcommand(s) + recover Recover the secret from the shares [aliases: r] + split Split a secret into shares [aliases: s] +``` + +### `rustysecrets split` + +> Split a secret into shares + +``` +USAGE: + rustysecrets split [OPTIONS] --output -k -n + +OPTIONS: + -o, --output Path to the directory to output the shares to + -m, --mime The MIME type of the secret + -h, --help Prints help information + -k Number of shares necessary to recover the secret + -n Total number of generated shares + -r, --raw Include this flag to generate raw shares (ie. without a MIME type) + -t, --share-tmpl Template for the share names. Defaults to 'share_{{num}}' + -s, --sign Sign the shares + -v, --verbose Enable verbose mode + +ARGS: + Path to the file containing the secret to split, or - to read from stdin +``` + +### `rustysecrets recover` + +> Recover the secret from the shares + +``` +USAGE: + rustysecrets recover [OPTIONS] ... + +OPTIONS: + -o, --output Path to file to output the secret to, prints to stdout if omitted + -h, --help Prints help information + -r, --raw Include this flag if the shares are raw (ie. do not contain a MIME type) + -v, --verbose Enable verbose mode + --verify Verify the shares signatures + +ARGS: + ... Paths to shares to recover the secret from +``` + +## Bug Reporting + +Please report bugs either as pull requests or as issues in [the issue +tracker](https://github.com/SpinResearch/rustysecrets-cli). *rustysecrets-cli* has a +**full disclosure** vulnerability policy. **Please do NOT attempt to report +any security vulnerability in this code privately to anybody.** + +## License + +RustySecrets CLI is released under the BSD3 license. See [LICENSE](LICENSE) for more informations. + diff --git a/build.rs b/build.rs new file mode 100644 index 0000000..b74debe --- /dev/null +++ b/build.rs @@ -0,0 +1,40 @@ + +extern crate git_build_version; +extern crate mime; +extern crate clap; + +use clap::Shell; + +use std::env; +use std::path::Path; +use std::fs; + +include!("src/cli.rs"); + +fn main() { + gen_completions(); + expose_git_describe(); +} + +fn gen_completions() { + let out_dir = env::var_os("OUT_DIR").unwrap(); + let mut path_buf = Path::new(&out_dir).to_path_buf(); + path_buf.pop(); + path_buf.pop(); + path_buf.push("rustysecrets-completions"); + let path = path_buf.as_path(); + + if !path.exists() { + fs::create_dir(path).unwrap(); + } + + let mut app = build_cli(); + app.gen_completions("rustysecrets", Shell::Bash, &path); + app.gen_completions("rustysecrets", Shell::Zsh, &path); + app.gen_completions("rustysecrets", Shell::Fish, &path); + // app.gen_completions("rustysecrets", Shell::PowerShell, &outdir); +} + +fn expose_git_describe() { + git_build_version::write_version(".").expect("Saving git version"); +} diff --git a/src/cli.rs b/src/cli.rs new file mode 100644 index 0000000..d333fcb --- /dev/null +++ b/src/cli.rs @@ -0,0 +1,178 @@ +use clap::{App, AppSettings, Arg, SubCommand}; + +pub fn build_cli() -> App<'static, 'static> { + App::new("RustySecrets CLI") + .version("0.2-pre") + .author("SpinResearch") + .about("Split a secret of an arbitrary length in n different shares and k-out-of-n shares are required to recover it.") + .setting(AppSettings::SubcommandRequiredElseHelp) + .setting(AppSettings::VersionlessSubcommands) + .setting(AppSettings::ColoredHelp) + .setting(AppSettings::UnifiedHelpMessage) + .subcommand(SubCommand::with_name("split") + .about("Split a secret into shares") + .visible_alias("s") + .setting(AppSettings::ColoredHelp) + .setting(AppSettings::UnifiedHelpMessage) + .arg(Arg::with_name("verbose") + .short("v") + .long("verbose") + .help("Enable verbose mode")) + .arg(Arg::with_name("k") + .short("k") + .required(true) + .takes_value(true) + .validator(validators::num::strictly_positive) + .help("Number of shares necessary to recover the secret")) + .arg(Arg::with_name("n") + .short("n") + .required(true) + .takes_value(true) + .validator(validators::num::strictly_positive) + .help("Total number of generated shares")) + .arg(Arg::with_name("share-tmpl") + .short("t") + .long("share-tmpl") + .takes_value(true) + .validator(validators::rusty_secrets::share_tmpl) + .help("Template for the share names. Defaults to 'share_{{num}}'")) + .arg(Arg::with_name("DIR") + .short("o") + .long("output") + .required(true) + .takes_value(true) + .validator(validators::fs::directory) + .help("Path to the directory to output the shares to")) + .arg(Arg::with_name("MIME") + .short("m") + .long("mime") + .takes_value(true) + .validator(validators::mime_type) + .help("The MIME type of the secret")) + .arg(Arg::with_name("raw") + .short("r") + .long("raw") + .conflicts_with("MIME") + .help("Include this flag to generate raw shares (ie. without a MIME type)")) + .arg(Arg::with_name("sign") + .short("s") + .long("sign") + .help("Sign the shares")) + .arg(Arg::with_name("INPUT") + .required(true) + .validator(validators::fs::file_or_stdin) + .help("Path to the file containing the secret to split, or - to read from stdin"))) + .subcommand(SubCommand::with_name("recover") + .about("Recover the secret from the shares") + .visible_alias("r") + .setting(AppSettings::ColoredHelp) + .setting(AppSettings::UnifiedHelpMessage) + .arg(Arg::with_name("verbose") + .short("v") + .long("verbose") + .help("Enable verbose mode")) + .arg(Arg::with_name("SHARES") + .required(true) + .takes_value(true) + .multiple(true) + .validator(validators::fs::file) + .help("Paths to shares to recover the secret from")) + .arg(Arg::with_name("raw") + .short("r") + .long("raw") + .help("Include this flag if the shares are raw (ie. do not contain a MIME type)")) + .arg(Arg::with_name("verify") + .long("verify") + .help("Verify the shares signatures")) + .arg(Arg::with_name("FILE") + .short("o") + .long("output") + .takes_value(true) + .help("Path to file to output the secret to, prints to stdout if omitted"))) +} + +#[cfg_attr(feature = "cargo-clippy", allow(needless_pass_by_value))] +pub mod validators { + + pub mod rusty_secrets { + + pub fn share_tmpl(value: String) -> Result<(), String> { + if !value.contains("{{num}}") { + return Err("Invalid share template, must contain '{[num]}'".to_string()); + } + + Ok(()) + } + + } + + pub mod num { + + pub fn strictly_positive(value: String) -> Result<(), String> { + let n = value.parse::(); + + if n.is_err() { + return Err(format!("{} is not a positive number", value)); + } + + if n.unwrap() < 1 { + return Err(format!("{} is not strictly positive", value)); + } + + Ok(()) + } + + } + + pub fn mime_type(value: String) -> Result<(), String> { + use mime::Mime; + + if value.parse::().is_err() { + return Err(format!("{} is not a valid MIME type", value)); + } + + Ok(()) + } + + pub mod fs { + + use std::path::Path; + + pub fn file(value: String) -> Result<(), String> { + let path = Path::new(&value); + + if !path.exists() { + return Err(format!("'{}' does not exists", value)); + } + + if !path.is_file() { + return Err(format!("'{}' is not a file", value)); + } + + Ok(()) + } + + pub fn file_or_stdin(value: String) -> Result<(), String> { + if value == "-" { + return Ok(()); + } + + file(value) + } + + pub fn directory(value: String) -> Result<(), String> { + let path = Path::new(&value); + + if !path.exists() { + return Err(format!("'{}' does not exists", value)); + } + + if !path.is_dir() { + return Err(format!("'{}' is not a directory", value)); + } + + Ok(()) + } + + } +} diff --git a/src/cmds/mod.rs b/src/cmds/mod.rs new file mode 100644 index 0000000..4f85538 --- /dev/null +++ b/src/cmds/mod.rs @@ -0,0 +1,5 @@ +mod split; +mod recover; + +pub use self::split::split; +pub use self::recover::recover; diff --git a/src/cmds/recover.rs b/src/cmds/recover.rs new file mode 100644 index 0000000..110f9f8 --- /dev/null +++ b/src/cmds/recover.rs @@ -0,0 +1,78 @@ +use rusty_secrets::{sss, wrapped_secrets}; + +use errors::*; + +use std::path::Path; +use std::fs::File; +use std::io::{self, Read, Write}; + +pub fn recover(shares_paths: Vec<&Path>, output_path: Option<&Path>, verify_signatures: bool, raw: bool) -> Result<()> { + let mut shares = Vec::with_capacity(shares_paths.len()); + + for share_path in shares_paths { + if !share_path.exists() { + bail!(ErrorKind::ShareDoesNotExists(format!( + "{}", + share_path.display() + ),)) + } + if !share_path.is_file() { + bail!(ErrorKind::ShareIsNotAFile(format!( + "{}", + share_path.display() + ),)) + } + + debug!("Reading share {:?}... ", share_path); + + let mut share_file = + File::open(share_path).chain_err(|| ErrorKind::CannotOpenShare(format!("{}", share_path.display())))?; + + let mut share = String::new(); + let size = share_file + .read_to_string(&mut share) + .chain_err(|| ErrorKind::CannotReadShare(format!("{}", share_path.display())))?; + + debug!("Read {} bytes.", size); + + shares.push(share); + } + + debug!("Recovering secret... "); + + let secret = if raw { + sss::recover_secret(&shares, verify_signatures).chain_err(|| ErrorKind::CannotRecoverSecret)? + } else { + let mut res = + wrapped_secrets::recover_secret(&shares, verify_signatures).chain_err(|| ErrorKind::CannotRecoverSecret)?; + + debug!("Version: {:?}", res.get_version()); + + if res.get_mime_type() != "" { + debug!("MIME-Type: {}", res.get_mime_type()); + } + + res.take_secret() + }; + + match output_path { + Some(output_path) => { + let mut output_file = File::create(output_path) + .chain_err(|| ErrorKind::CannotCreateSecretFile(format!("{}", output_path.display())))?; + output_file + .write_all(&secret) + .chain_err(|| ErrorKind::CannotWriteSecretToFile(format!("{}", output_path.display())))?; + } + None => { + // See https://github.com/romac/rustysecrets-cli/issues/9 + // let secret_str = String::from_utf8(secret) + // .chain_err(|| "Could not parse secret as UTF-8, consider outputting it to a file instead")?; + + io::stdout() + .write_all(&secret) + .chain_err(|| ErrorKind::CannotWriteSecretToStdout)?; + } + } + + Ok(()) +} diff --git a/src/cmds/split.rs b/src/cmds/split.rs new file mode 100644 index 0000000..b8ba168 --- /dev/null +++ b/src/cmds/split.rs @@ -0,0 +1,66 @@ +use mime::Mime; +use rusty_secrets::{sss, wrapped_secrets}; + +use errors::*; +use input::Input; + +use std::path::Path; +use std::fs::File; +use std::io::{Read, Write}; + +#[cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))] +pub fn split( + mut secret_input: Input, + output_path: &Path, + k: u8, + n: u8, + mime_type: Option, + sign_shares: bool, + raw: bool, + share_tmpl: &str, +) -> Result<()> { + if k > n { + bail!(ErrorKind::KMustBeSmallerThanN(k, n)) + } + + if raw && mime_type.is_some() { + bail!(ErrorKind::RawMimeConflict); + } + + debug!("Reading secret..."); + + let mut secret = Vec::new(); + let size = secret_input + .read_to_end(&mut secret) + .chain_err(|| ErrorKind::CannotReadSecret(secret_input))?; + + debug!("Read {} bytes.", size); + + debug!("Generating shares..."); + + let shares = if raw { + sss::split_secret(k, n, &secret, sign_shares) + } else { + let mime_type = mime_type.map(|m| m.as_ref().to_string()); + wrapped_secrets::split_secret(k, n, &secret, mime_type, sign_shares) + }.chain_err(|| "Could not generate shares")?; + + for (num, share) in shares.iter().enumerate() { + let mut path_buf = output_path.to_path_buf(); + path_buf.push(share_tmpl.replace("{{num}}", &format!("{}", num))); + let share_path = path_buf.as_path(); + + debug!("Writing share #{} to '{}'...", num, share_path.display()); + + let mut share_file = File::create(share_path) + .chain_err(|| ErrorKind::CannotCreateShareFile(format!("{}", share_path.display())))?; + + share_file + .write_all(share.as_bytes()) + .chain_err(|| ErrorKind::CannotWriteShareDataToFile(format!("{}", share_path.display())))?; + } + + info!("Wrote {} shares to '{}'", n, output_path.display()); + + Ok(()) +} diff --git a/src/errors.rs b/src/errors.rs new file mode 100644 index 0000000..a748153 --- /dev/null +++ b/src/errors.rs @@ -0,0 +1,68 @@ +#![cfg_attr(feature = "cargo-clippy", allow(unused_doc_comment))] +#![allow(unknown_lints)] + +use input::Input; + +// Create the Error, ErrorKind, ResultExt, and Result types +error_chain! { + + errors { + KMustBeSmallerThanN(k: u8, n: u8) { + description("k must be smaller than or equal to n") + display("k must be smaller than or equal to n, got: k = {}, n = {}", k, n) + } + CannotReadSecret(input: Input) { + description("Cannot read secret") + display("Cannot read secret from '{}'", input) + } + CannotOpenSecretFile(path: String) { + description("cannot open secret file") + display("cannot open secret file '{}'", path) + } + CannotCreateShareFile(path: String) { + description("Cannot create share file") + display("Cannot create share file '{}'", path) + } + CannotWriteShareDataToFile(path: String) { + description("Cannot write share data to file") + display("Cannot write share data to '{}'", path) + } + ShareDoesNotExists(path: String) { + description("Share does not exists") + display("Share does not exists: '{}'", path) + } + ShareIsNotAFile(path: String) { + description("Given share is not a file") + display("Share is not a file: '{}'", path) + } + CannotOpenShare(path: String) { + description("Cannot open share") + display("Cannot open share at '{}'", path) + } + CannotReadShare(path: String) { + description("Cannot read share") + display("Cannot read share at '{}'", path) + } + CannotRecoverSecret { + description("Cannot recover secret") + display("Cannot recover secret") + } + CannotCreateSecretFile(path: String) { + description("Cannot write share data to file") + display("Cannot create secret file '{}'", path) + } + CannotWriteSecretToFile(path: String) { + description("Cannot write secret to file") + display("Cannot write secret to '{}'", path) + } + CannotWriteSecretToStdout { + description("Cannot write secret to stdout") + display("Cannot write secret to stdout") + } + RawMimeConflict { + description("Cannot set a MIME type with raw shares") + display("Cannot set a MIME type with raw shares") + } + } + +} diff --git a/src/input.rs b/src/input.rs new file mode 100644 index 0000000..b6a35dd --- /dev/null +++ b/src/input.rs @@ -0,0 +1,38 @@ +// Adapted from +// https://gist.github.com/ayosec/2ee0993247e003b42c5c + +use std::{fmt, fs, io}; + +#[derive(Debug)] +pub enum Input { + Standard(io::Stdin), + File(fs::File, String), +} + +impl Input { + pub fn stdin() -> Input { + Input::Standard(io::stdin()) + } + + pub fn file(path: String) -> io::Result { + Ok(Input::File(try!(fs::File::open(path.clone())), path)) + } +} + +impl io::Read for Input { + fn read(&mut self, buf: &mut [u8]) -> io::Result { + match *self { + Input::Standard(ref mut s) => s.read(buf), + Input::File(ref mut f, _) => f.read(buf), + } + } +} + +impl fmt::Display for Input { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match *self { + Input::Standard(_) => write!(f, ""), + Input::File(_, ref path) => write!(f, "{}", path), + } + } +} diff --git a/src/logger.rs b/src/logger.rs new file mode 100644 index 0000000..a6aad2c --- /dev/null +++ b/src/logger.rs @@ -0,0 +1,45 @@ +use log::{Level, Log, Metadata, Record}; +use colored::*; + +pub struct ColoredTermLogger { + level: Level, + #[allow(dead_code)] + colored: bool, +} + +impl ColoredTermLogger { + pub fn new(level: Level, colored: bool) -> Self { + ColoredTermLogger { level, colored } + } + + pub fn with_level(level: Level) -> Self { + Self::new(level, !cfg!(windows)) + } +} + +impl Default for ColoredTermLogger { + fn default() -> Self { + Self::with_level(Level::Warn) + } +} + +impl Log for ColoredTermLogger { + fn enabled(&self, metadata: &Metadata) -> bool { + metadata.level() <= self.level + } + + // TODO: Disable colors if colored == false + fn log(&self, record: &Record) { + if self.enabled(record.metadata()) { + match record.level() { + Level::Trace => eprintln!("{} {}", "debug:".white().bold(), record.args()), + Level::Debug => eprintln!("{} {}", "info:".blue().bold(), record.args()), + Level::Info => eprintln!("{} {}", "success:".green().bold(), record.args()), + Level::Warn => eprintln!("{} {}", "warn:".yellow().bold(), record.args()), + Level::Error => eprintln!("{} {}", "error:".red().bold(), record.args()), + } + } + } + + fn flush(&self) {} +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..46e2d69 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,107 @@ +// `error_chain` recursion adjustment +#![recursion_limit = "1024"] +// Make rustc's built-in lints more strict +#![warn(warnings)] + +extern crate colored; +use colored::*; + +extern crate clap; + +#[macro_use] +extern crate error_chain; + +#[macro_use] +extern crate log; +extern crate mime; +extern crate rusty_secrets; + +mod errors; +use errors::*; + +mod input; +use input::Input; + +mod cli; +mod cmds; +mod version; +mod logger; +use logger::ColoredTermLogger; + +use log::{Level, LevelFilter}; +use std::path::Path; + +fn main() { + if let Err(ref e) = run() { + error!("{}", e); + + for e in e.iter().skip(1) { + error!("{} {}", "reason:".yellow().bold(), e); + } + + if let Some(backtrace) = e.backtrace() { + error!("{} {:?}", "backtrace:".blue().bold(), backtrace); + } + + ::std::process::exit(1); + } +} + +fn run() -> Result<()> { + let app = cli::build_cli().version(version::get()); + let matches = app.get_matches(); + + let verbose = matches + .subcommand_matches("split") + .or_else(|| matches.subcommand_matches("recover")) + .map(|matches| matches.is_present("verbose")) + .unwrap_or(false); + + let level = if verbose { Level::Debug } else { Level::Info }; + let logger = ColoredTermLogger::with_level(level); + + log::set_max_level(LevelFilter::Debug); + log::set_boxed_logger(Box::new(logger)).unwrap(); + + if let Some(matches) = matches.subcommand_matches("split") { + let secret_arg = matches.value_of("INPUT").unwrap(); + let secret_input = if secret_arg == "-" { + Input::stdin() + } else { + Input::file(secret_arg.to_string()).chain_err(|| ErrorKind::CannotOpenSecretFile(secret_arg.to_string()))? + }; + + let output_path = Path::new(matches.value_of("DIR").unwrap()); + let k = matches.value_of("k").unwrap().parse::().unwrap(); + let n = matches.value_of("n").unwrap().parse::().unwrap(); + let mime_type = matches.value_of("MIME").map(|v| v.parse().unwrap()); + let sign_shares = matches.is_present("sign"); + let raw = matches.is_present("raw"); + let share_tmpl = matches.value_of("share-tmpl").unwrap_or("share_{{num}}"); + + cmds::split( + secret_input, + output_path, + k, + n, + mime_type, + sign_shares, + raw, + share_tmpl, + )? + } else if let Some(matches) = matches.subcommand_matches("recover") { + let shares = matches + .values_of("SHARES") + .unwrap() + .map(Path::new) + .collect(); + + let output_path = matches.value_of("FILE").map(Path::new); + let verify_signatures = matches.is_present("verify"); + let raw = matches.is_present("raw"); + + cmds::recover(shares, output_path, verify_signatures, raw)? + } + + Ok(()) +} diff --git a/src/version.rs b/src/version.rs new file mode 100644 index 0000000..ecf0b7f --- /dev/null +++ b/src/version.rs @@ -0,0 +1,5 @@ +include!(concat!(env!("OUT_DIR"), "/version.rs")); + +pub(crate) fn get() -> &'static str { + VERSION +} diff --git a/tests/resources/secret.txt b/tests/resources/secret.txt new file mode 100644 index 0000000..c17b2ef --- /dev/null +++ b/tests/resources/secret.txt @@ -0,0 +1,2 @@ +These programs were never about terrorism: they’re about economic spying, +social control, and diplomatic manipulation. They’re about power. diff --git a/tests/tests.rs b/tests/tests.rs new file mode 100644 index 0000000..15a50e1 --- /dev/null +++ b/tests/tests.rs @@ -0,0 +1,65 @@ +extern crate colored; +use colored::*; + +extern crate tempdir; +use tempdir::TempDir; + +use std::str; +use std::process::Command; + +#[test] +fn raw() { + run(&["--raw"]); +} + +#[test] +fn wrapped() { + run(&[]); +} + +fn run(raw: &[&str]) { + let secret_path = "tests/resources/secret.txt"; + let secret = include_str!("resources/secret.txt"); + let n = 10; + let k = 7; + + let tmp = TempDir::new("rustysecrets").unwrap(); + + let output_path = tmp.path().to_string_lossy().as_ref().to_string(); + + let split_out = Command::new("target/debug/rustysecrets") + .arg("split") + .arg(secret_path) + .args(raw) + .args(&["-o", &output_path]) + .args(&["-k", &k.to_string()]) + .args(&["-n", &n.to_string()]) + .output() + .unwrap(); + + assert_eq!(str::from_utf8(&split_out.stdout).unwrap(), ""); + + assert_eq!( + str::from_utf8(&split_out.stderr).unwrap(), + &format!( + "{} Wrote {} shares to '{}'\n", + "success:".green().bold(), + n, + output_path + ) + ); + + let shares = (0..7) + .map(|i| format!("{}/share_{}", output_path, i)) + .collect::>(); + + let recover_out = Command::new("target/debug/rustysecrets") + .arg("recover") + .args(raw) + .args(&shares) + .output() + .unwrap(); + + assert_eq!(str::from_utf8(&recover_out.stdout).unwrap(), secret); + assert_eq!(str::from_utf8(&recover_out.stderr).unwrap(), ""); +}