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
|
||||
* [added] Derive key pairs from passwords
|
||||
* [modified] Added root repository to exclude list
|
||||
* [modified] Initializing data in index before use
|
||||
|
||||
|
|
|
@ -14,6 +14,7 @@ dependencies = [
|
|||
"index 0.1.0",
|
||||
"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)",
|
||||
"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)",
|
||||
"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)",
|
||||
|
|
|
@ -20,6 +20,7 @@ log = "0.3"
|
|||
byteorder = "1.0"
|
||||
ansi_term = "0.9"
|
||||
sodiumoxide = "0.0.14"
|
||||
libsodium-sys = "0.0.14"
|
||||
filetime = "0.1"
|
||||
regex = "0.2"
|
||||
fuse = "0.3"
|
||||
|
|
|
@ -32,6 +32,11 @@ key will be set as default encryption key.
|
|||
Set the key pair as default
|
||||
|
||||
|
||||
* `-p`, `--password <PASSWORD>`:
|
||||
|
||||
Derive the key pair from the given password instead of randomly creating it.
|
||||
|
||||
|
||||
* `-h`, `--help`:
|
||||
|
||||
Prints help information
|
||||
|
|
|
@ -14,6 +14,10 @@ writes it to the given file `FILE`.
|
|||
|
||||
## OPTIONS
|
||||
|
||||
* `-p`, `--password <PASSWORD>`:
|
||||
|
||||
Derive the key pair from the given password instead of randomly creating it.
|
||||
|
||||
* `-h`, `--help`:
|
||||
|
||||
Prints help information
|
||||
|
|
|
@ -116,11 +116,13 @@ pub enum Arguments {
|
|||
hash: Option<HashMethod>
|
||||
},
|
||||
GenKey {
|
||||
file: Option<String>
|
||||
file: Option<String>,
|
||||
password: Option<String>
|
||||
},
|
||||
AddKey {
|
||||
repo_path: String,
|
||||
file: Option<String>,
|
||||
password: Option<String>,
|
||||
set_default: bool
|
||||
},
|
||||
AlgoTest {
|
||||
|
@ -399,11 +401,14 @@ pub fn parse() -> Result<(LogLevel, Arguments), ErrorCode> {
|
|||
.arg(Arg::from_usage("<REPO> 'Path of the repository'")
|
||||
.validator(|val| validate_repo_path(val, true, Some(false), Some(false)))))
|
||||
.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'")))
|
||||
.subcommand(SubCommand::with_name("addkey").about("Add a key pair to the repository")
|
||||
.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("-p --password [PASSWORD] 'Derive the key pair from the given password'")
|
||||
.conflicts_with("FILE"))
|
||||
.arg(Arg::from_usage("<REPO> 'Path of the repository'")
|
||||
.validator(|val| validate_repo_path(val, true, Some(false), Some(false))))
|
||||
.arg(Arg::from_usage("[FILE] 'File containing the keypair'")
|
||||
|
@ -592,7 +597,8 @@ pub fn parse() -> Result<(LogLevel, Arguments), ErrorCode> {
|
|||
},
|
||||
("genkey", Some(args)) => {
|
||||
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)) => {
|
||||
|
@ -600,6 +606,7 @@ pub fn parse() -> Result<(LogLevel, Arguments), ErrorCode> {
|
|||
Arguments::AddKey {
|
||||
repo_path: repository.to_string(),
|
||||
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())
|
||||
}
|
||||
},
|
||||
|
|
|
@ -625,8 +625,11 @@ pub fn run() -> Result<(), ErrorCode> {
|
|||
print_config(&repo.config);
|
||||
}
|
||||
},
|
||||
Arguments::GenKey{file} => {
|
||||
let (public, secret) = Crypto::gen_keypair();
|
||||
Arguments::GenKey{file, password} => {
|
||||
let (public, secret) = match password {
|
||||
None => Crypto::gen_keypair(),
|
||||
Some(ref password) => Crypto::keypair_from_password(password)
|
||||
};
|
||||
info!("Created the following key pair");
|
||||
println!("public: {}", to_hex(&public[..]));
|
||||
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);
|
||||
}
|
||||
},
|
||||
Arguments::AddKey{repo_path, set_default, file} => {
|
||||
Arguments::AddKey{repo_path, set_default, password, file} => {
|
||||
let mut repo = try!(open_repository(&repo_path));
|
||||
let (public, secret) = if let Some(file) = file {
|
||||
checked!(Crypto::load_keypair_from_file(file), "load key pair", ErrorCode::LoadKey)
|
||||
} else {
|
||||
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!("secret: {}", to_hex(&secret[..]));
|
||||
(public, secret)
|
||||
|
|
|
@ -14,6 +14,7 @@ extern crate chrono;
|
|||
#[macro_use] extern crate log;
|
||||
extern crate byteorder;
|
||||
extern crate sodiumoxide;
|
||||
extern crate libsodium_sys;
|
||||
extern crate ansi_term;
|
||||
extern crate filetime;
|
||||
extern crate regex;
|
||||
|
|
|
@ -7,9 +7,11 @@ use std::sync::{Once, ONCE_INIT};
|
|||
use serde_yaml;
|
||||
use serde_bytes::ByteBuf;
|
||||
|
||||
use libsodium_sys;
|
||||
use sodiumoxide;
|
||||
use sodiumoxide::crypto::sealedbox;
|
||||
use sodiumoxide::crypto::box_;
|
||||
use sodiumoxide::crypto::pwhash;
|
||||
pub use sodiumoxide::crypto::box_::{SecretKey, PublicKey};
|
||||
|
||||
use ::util::*;
|
||||
|
@ -211,4 +213,21 @@ impl Crypto {
|
|||
sodium_init();
|
||||
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