mirror of https://github.com/dswd/zvault
Derive key pairs from passwords
This commit is contained in:
parent
cac4f81876
commit
4ac42d14ef
|
@ -4,6 +4,7 @@ This project follows [semantic versioning](http://semver.org).
|
||||||
|
|
||||||
|
|
||||||
### UNRELEASED
|
### UNRELEASED
|
||||||
|
* [added] Derive key pairs from passwords
|
||||||
* [modified] Added root repository to exclude list
|
* [modified] Added root repository to exclude list
|
||||||
* [modified] Initializing data in index before use
|
* [modified] Initializing data in index before use
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ dependencies = [
|
||||||
"index 0.1.0",
|
"index 0.1.0",
|
||||||
"lazy_static 0.2.8 (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.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.22 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"libsodium-sys 0.0.14 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"murmurhash3 0.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"murmurhash3 0.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"pbr 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"pbr 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
|
|
@ -20,6 +20,7 @@ log = "0.3"
|
||||||
byteorder = "1.0"
|
byteorder = "1.0"
|
||||||
ansi_term = "0.9"
|
ansi_term = "0.9"
|
||||||
sodiumoxide = "0.0.14"
|
sodiumoxide = "0.0.14"
|
||||||
|
libsodium-sys = "0.0.14"
|
||||||
filetime = "0.1"
|
filetime = "0.1"
|
||||||
regex = "0.2"
|
regex = "0.2"
|
||||||
fuse = "0.3"
|
fuse = "0.3"
|
||||||
|
|
|
@ -32,6 +32,11 @@ key will be set as default encryption key.
|
||||||
Set the key pair as default
|
Set the key pair as default
|
||||||
|
|
||||||
|
|
||||||
|
* `-p`, `--password <PASSWORD>`:
|
||||||
|
|
||||||
|
Derive the key pair from the given password instead of randomly creating it.
|
||||||
|
|
||||||
|
|
||||||
* `-h`, `--help`:
|
* `-h`, `--help`:
|
||||||
|
|
||||||
Prints help information
|
Prints help information
|
||||||
|
|
|
@ -14,6 +14,10 @@ writes it to the given file `FILE`.
|
||||||
|
|
||||||
## OPTIONS
|
## OPTIONS
|
||||||
|
|
||||||
|
* `-p`, `--password <PASSWORD>`:
|
||||||
|
|
||||||
|
Derive the key pair from the given password instead of randomly creating it.
|
||||||
|
|
||||||
* `-h`, `--help`:
|
* `-h`, `--help`:
|
||||||
|
|
||||||
Prints help information
|
Prints help information
|
||||||
|
|
|
@ -116,11 +116,13 @@ pub enum Arguments {
|
||||||
hash: Option<HashMethod>
|
hash: Option<HashMethod>
|
||||||
},
|
},
|
||||||
GenKey {
|
GenKey {
|
||||||
file: Option<String>
|
file: Option<String>,
|
||||||
|
password: Option<String>
|
||||||
},
|
},
|
||||||
AddKey {
|
AddKey {
|
||||||
repo_path: String,
|
repo_path: String,
|
||||||
file: Option<String>,
|
file: Option<String>,
|
||||||
|
password: Option<String>,
|
||||||
set_default: bool
|
set_default: bool
|
||||||
},
|
},
|
||||||
AlgoTest {
|
AlgoTest {
|
||||||
|
@ -399,11 +401,14 @@ pub fn parse() -> Result<(LogLevel, Arguments), ErrorCode> {
|
||||||
.arg(Arg::from_usage("<REPO> 'Path of the repository'")
|
.arg(Arg::from_usage("<REPO> 'Path of the repository'")
|
||||||
.validator(|val| validate_repo_path(val, true, Some(false), Some(false)))))
|
.validator(|val| validate_repo_path(val, true, Some(false), Some(false)))))
|
||||||
.subcommand(SubCommand::with_name("genkey").about("Generate a new key pair")
|
.subcommand(SubCommand::with_name("genkey").about("Generate a new key pair")
|
||||||
|
.arg(Arg::from_usage("-p --password [PASSWORD] 'Derive the key pair from the given password'"))
|
||||||
.arg(Arg::from_usage("[FILE] 'Destination file for the keypair'")))
|
.arg(Arg::from_usage("[FILE] 'Destination file for the keypair'")))
|
||||||
.subcommand(SubCommand::with_name("addkey").about("Add a key pair to the repository")
|
.subcommand(SubCommand::with_name("addkey").about("Add a key pair to the repository")
|
||||||
.arg(Arg::from_usage("-g --generate 'Generate a new key pair'")
|
.arg(Arg::from_usage("-g --generate 'Generate a new key pair'")
|
||||||
.conflicts_with("FILE"))
|
.conflicts_with_all(&["FILE", "PASSWORD"]))
|
||||||
.arg(Arg::from_usage("[set_default] --default -d 'Set the key pair as default'"))
|
.arg(Arg::from_usage("[set_default] --default -d 'Set the key pair as default'"))
|
||||||
|
.arg(Arg::from_usage("-p --password [PASSWORD] 'Derive the key pair from the given password'")
|
||||||
|
.conflicts_with("FILE"))
|
||||||
.arg(Arg::from_usage("<REPO> 'Path of the repository'")
|
.arg(Arg::from_usage("<REPO> 'Path of the repository'")
|
||||||
.validator(|val| validate_repo_path(val, true, Some(false), Some(false))))
|
.validator(|val| validate_repo_path(val, true, Some(false), Some(false))))
|
||||||
.arg(Arg::from_usage("[FILE] 'File containing the keypair'")
|
.arg(Arg::from_usage("[FILE] 'File containing the keypair'")
|
||||||
|
@ -592,7 +597,8 @@ pub fn parse() -> Result<(LogLevel, Arguments), ErrorCode> {
|
||||||
},
|
},
|
||||||
("genkey", Some(args)) => {
|
("genkey", Some(args)) => {
|
||||||
Arguments::GenKey {
|
Arguments::GenKey {
|
||||||
file: args.value_of("FILE").map(|v| v.to_string())
|
file: args.value_of("FILE").map(|v| v.to_string()),
|
||||||
|
password: args.value_of("password").map(|v| v.to_string())
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
("addkey", Some(args)) => {
|
("addkey", Some(args)) => {
|
||||||
|
@ -600,6 +606,7 @@ pub fn parse() -> Result<(LogLevel, Arguments), ErrorCode> {
|
||||||
Arguments::AddKey {
|
Arguments::AddKey {
|
||||||
repo_path: repository.to_string(),
|
repo_path: repository.to_string(),
|
||||||
set_default: args.is_present("set_default"),
|
set_default: args.is_present("set_default"),
|
||||||
|
password: args.value_of("password").map(|v| v.to_string()),
|
||||||
file: args.value_of("FILE").map(|v| v.to_string())
|
file: args.value_of("FILE").map(|v| v.to_string())
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -625,8 +625,11 @@ pub fn run() -> Result<(), ErrorCode> {
|
||||||
print_config(&repo.config);
|
print_config(&repo.config);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Arguments::GenKey{file} => {
|
Arguments::GenKey{file, password} => {
|
||||||
let (public, secret) = Crypto::gen_keypair();
|
let (public, secret) = match password {
|
||||||
|
None => Crypto::gen_keypair(),
|
||||||
|
Some(ref password) => Crypto::keypair_from_password(password)
|
||||||
|
};
|
||||||
info!("Created the following key pair");
|
info!("Created the following key pair");
|
||||||
println!("public: {}", to_hex(&public[..]));
|
println!("public: {}", to_hex(&public[..]));
|
||||||
println!("secret: {}", to_hex(&secret[..]));
|
println!("secret: {}", to_hex(&secret[..]));
|
||||||
|
@ -634,13 +637,16 @@ pub fn run() -> Result<(), ErrorCode> {
|
||||||
checked!(Crypto::save_keypair_to_file(&public, &secret, file), "save key pair", ErrorCode::SaveKey);
|
checked!(Crypto::save_keypair_to_file(&public, &secret, file), "save key pair", ErrorCode::SaveKey);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Arguments::AddKey{repo_path, set_default, file} => {
|
Arguments::AddKey{repo_path, set_default, password, file} => {
|
||||||
let mut repo = try!(open_repository(&repo_path));
|
let mut repo = try!(open_repository(&repo_path));
|
||||||
let (public, secret) = if let Some(file) = file {
|
let (public, secret) = if let Some(file) = file {
|
||||||
checked!(Crypto::load_keypair_from_file(file), "load key pair", ErrorCode::LoadKey)
|
checked!(Crypto::load_keypair_from_file(file), "load key pair", ErrorCode::LoadKey)
|
||||||
} else {
|
} else {
|
||||||
info!("Created the following key pair");
|
info!("Created the following key pair");
|
||||||
let (public, secret) = Crypto::gen_keypair();
|
let (public, secret) = match password {
|
||||||
|
None => Crypto::gen_keypair(),
|
||||||
|
Some(ref password) => Crypto::keypair_from_password(password)
|
||||||
|
};
|
||||||
println!("public: {}", to_hex(&public[..]));
|
println!("public: {}", to_hex(&public[..]));
|
||||||
println!("secret: {}", to_hex(&secret[..]));
|
println!("secret: {}", to_hex(&secret[..]));
|
||||||
(public, secret)
|
(public, secret)
|
||||||
|
|
|
@ -14,6 +14,7 @@ extern crate chrono;
|
||||||
#[macro_use] extern crate log;
|
#[macro_use] extern crate log;
|
||||||
extern crate byteorder;
|
extern crate byteorder;
|
||||||
extern crate sodiumoxide;
|
extern crate sodiumoxide;
|
||||||
|
extern crate libsodium_sys;
|
||||||
extern crate ansi_term;
|
extern crate ansi_term;
|
||||||
extern crate filetime;
|
extern crate filetime;
|
||||||
extern crate regex;
|
extern crate regex;
|
||||||
|
|
|
@ -7,9 +7,11 @@ use std::sync::{Once, ONCE_INIT};
|
||||||
use serde_yaml;
|
use serde_yaml;
|
||||||
use serde_bytes::ByteBuf;
|
use serde_bytes::ByteBuf;
|
||||||
|
|
||||||
|
use libsodium_sys;
|
||||||
use sodiumoxide;
|
use sodiumoxide;
|
||||||
use sodiumoxide::crypto::sealedbox;
|
use sodiumoxide::crypto::sealedbox;
|
||||||
use sodiumoxide::crypto::box_;
|
use sodiumoxide::crypto::box_;
|
||||||
|
use sodiumoxide::crypto::pwhash;
|
||||||
pub use sodiumoxide::crypto::box_::{SecretKey, PublicKey};
|
pub use sodiumoxide::crypto::box_::{SecretKey, PublicKey};
|
||||||
|
|
||||||
use ::util::*;
|
use ::util::*;
|
||||||
|
@ -211,4 +213,21 @@ impl Crypto {
|
||||||
sodium_init();
|
sodium_init();
|
||||||
box_::gen_keypair()
|
box_::gen_keypair()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn keypair_from_password(password: &str) -> (PublicKey, SecretKey) {
|
||||||
|
let salt = pwhash::Salt::from_slice(b"the_great_zvault_password_salt_1").unwrap();
|
||||||
|
let mut key = [0u8; pwhash::HASHEDPASSWORDBYTES];
|
||||||
|
let key = pwhash::derive_key(&mut key, password.as_bytes(), &salt, pwhash::OPSLIMIT_INTERACTIVE, pwhash::MEMLIMIT_INTERACTIVE).unwrap();
|
||||||
|
let mut seed = [0u8; 32];
|
||||||
|
let offset = key.len()-seed.len();
|
||||||
|
for (i, b) in seed.iter_mut().enumerate() {
|
||||||
|
*b = key[i+offset];
|
||||||
|
}
|
||||||
|
let mut pk = [0u8; 32];
|
||||||
|
let mut sk = [0u8; 32];
|
||||||
|
if unsafe { libsodium_sys::crypto_box_seed_keypair(&mut pk, &mut sk, &seed) } != 0 {
|
||||||
|
panic!("Libsodium failed");
|
||||||
|
}
|
||||||
|
(PublicKey::from_slice(&pk).unwrap(), SecretKey::from_slice(&sk).unwrap())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue