Skip to content
This repository has been archived by the owner on Feb 3, 2023. It is now read-only.

Signing 2 - hc keygen #974

Merged
merged 19 commits into from
Feb 11, 2019
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]
### Changed
- Added command `hc keygen` which creates a new key pair, asks for a passphrase and writes an encrypted key bundle file to `~/.holochain/keys`.
- `hash` properties for `UiBundleConfiguration` and `DnaConfiguration` in Conductor config files is now optional
- core now depends on `pretty_assertions` crate
- `ChainHeader::sources()` is now `ChainHeader::provenances()`
Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

members = [
"cli",
"common",
"conductor",
"conductor_api",
"core_api_c_binding",
Expand Down
5 changes: 5 additions & 0 deletions cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@ authors = ["Holochain Core Dev Team <devcore@holochain.org>"]

[dependencies]
holochain_net = { path = "../net" }
holochain_common = { path = "../common" }
holochain_core_types = { path = "../core_types" }
holochain_core = { path = "../core" }
holochain_cas_implementations = { path = "../cas_implementations" }
holochain_conductor_api = { path = "../conductor_api" }
holochain_dpki = { path = "../hc_dpki" }
holochain_sodium = { path = "../sodium" }
holochain_wasm_utils = { path = "../wasm_utils" }
structopt = "0.2"
failure = "^0.1"
Expand All @@ -25,3 +28,5 @@ dir-diff = "0.3.1"
colored = "1.6"
ignore = "0.4.3"
rustyline = "^2.1"
rpassword = "2.1.0"
directories = "1.0"
46 changes: 46 additions & 0 deletions cli/src/cli/keygen.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
use error::DefaultResult;
use holochain_common::paths::keys_directory;
use holochain_dpki::{
bundle::KeyBundle,
keypair::{Keypair, SEEDSIZE},
util::PwHashConfig,
};
use holochain_sodium::{pwhash, random::random_secbuf, secbuf::SecBuf};
use rpassword;
use std::{
fs::{create_dir_all, File},
io::prelude::*,
};

pub fn keygen() -> DefaultResult<()> {
let passphrase = rpassword::read_password_from_tty(Some("Passphrase: ")).unwrap();

let mut seed = SecBuf::with_secure(SEEDSIZE);
random_secbuf(&mut seed);
let mut keypair = Keypair::new_from_seed(&mut seed).unwrap();
let passphrase_bytes = passphrase.as_bytes();
let mut passphrase_buf = SecBuf::with_insecure(passphrase_bytes.len());
passphrase_buf
.write(0, passphrase_bytes)
.expect("SecBuf must be writeable");

let bundle: KeyBundle = keypair
.get_bundle(
&mut passphrase_buf,
"hint".to_string(),
Some(PwHashConfig(
pwhash::OPSLIMIT_INTERACTIVE,
pwhash::MEMLIMIT_INTERACTIVE,
pwhash::ALG_ARGON2ID13,
)),
)
.unwrap();

let path = keys_directory();
create_dir_all(path.clone())?;
let path = path.join(keypair.pub_keys);
let mut file = File::create(path.clone())?;
file.write_all(serde_json::to_string(&bundle).unwrap().as_bytes())?;
println!("Wrote {}.", path.to_str().unwrap());
Ok(())
}
2 changes: 2 additions & 0 deletions cli/src/cli/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
mod agent;
mod generate;
mod init;
mod keygen;
pub mod package;
mod run;
mod scaffold;
Expand All @@ -11,6 +12,7 @@ pub use self::{
agent::agent,
generate::generate,
init::init,
keygen::keygen,
package::{package, unpack},
run::run,
test::{test, TEST_DIR_NAME},
Expand Down
11 changes: 11 additions & 0 deletions cli/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
extern crate holochain_cas_implementations;
extern crate holochain_common;
extern crate holochain_conductor_api;
extern crate holochain_core;
extern crate holochain_core_types;
extern crate holochain_dpki;
extern crate holochain_net;
extern crate holochain_sodium;
extern crate holochain_wasm_utils;
extern crate structopt;
#[macro_use]
Expand All @@ -19,6 +22,7 @@ extern crate toml;
#[macro_use]
extern crate serde_json;
extern crate ignore;
extern crate rpassword;
extern crate rustyline;
extern crate tempfile;
extern crate uuid;
Expand Down Expand Up @@ -142,6 +146,12 @@ enum Cli {
#[structopt(long = "skip-package", short = "s", help = "Skip packaging DNA")]
skip_build: bool,
},
#[structopt(
name = "keygen",
alias = "k",
about = "Creates a new agent key pair, asks for a passphrase and writes an encrypted key bundle to ~/.holochain/keys"
lucksus marked this conversation as resolved.
Show resolved Hide resolved
)]
KeyGen,
}

fn main() {
Expand Down Expand Up @@ -183,6 +193,7 @@ fn run() -> HolochainResult<()> {
cli::test(&current_path, &dir, &testfile, skip_build)
}
.map_err(HolochainError::Default)?,
Cli::KeyGen => cli::keygen().map_err(|e| HolochainError::Default(format_err!("{}", e)))?,
}

Ok(())
Expand Down
8 changes: 8 additions & 0 deletions common/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[package]
name = "holochain_common"
version = "0.0.3"
authors = ["Holochain Core Dev Team <devcore@holochain.org>"]
edition = "2018"

[dependencies]
directories = "1.0"
1 change: 1 addition & 0 deletions common/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod paths;
23 changes: 23 additions & 0 deletions common/src/paths.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
use std::path::PathBuf;

pub const QUALIFIER: &'static str = "org";
pub const ORGANIZATION: &'static str = "holochain";
pub const APPLICATION: &'static str = "holochain";
pub const KEYS_DIRECTORY: &'static str = "keys";

/// Returns the path to the root config directory for all of Holochain.
/// If we can get a user directory it will be an XDG compliant path
/// like "/home/peter/.config/holochain".
/// If it can't get a user directory it will default to "/etc/holochain".
pub fn config_root() -> PathBuf {
directories::ProjectDirs::from(QUALIFIER, ORGANIZATION, APPLICATION)
.and_then(|dirs| Some(dirs.config_dir().to_owned()))
lucksus marked this conversation as resolved.
Show resolved Hide resolved
.or(Some(PathBuf::new().join("/etc").join(APPLICATION)))
.unwrap()
lucksus marked this conversation as resolved.
Show resolved Hide resolved
}

/// Returns the path to where agent keys are stored and looked for by default.
/// Something like "~/.config/holochain/keys".
pub fn keys_directory() -> PathBuf {
config_root().join(KEYS_DIRECTORY)
}
1 change: 1 addition & 0 deletions hc_dpki/src/bundle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
/// The bundle_type tells if the bundle is a RootSeed bundle | DeviceSeed bundle | DevicePINSeed Bundle | ApplicationKeys Bundle
///
/// the data includes a base64 encoded string of the ReturnBundleData Struct that was created by combining all the keys in one SecBuf
#[derive(Serialize, Deserialize)]
pub struct KeyBundle {
pub bundle_type: String,
pub hint: String,
Expand Down
5 changes: 3 additions & 2 deletions hc_dpki/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ extern crate holochain_sodium;
#[macro_use]
extern crate arrayref;
extern crate base64;
extern crate rustc_serialize;

extern crate bip39;
extern crate boolinator;
extern crate rustc_serialize;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this needed again?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know. I've just moved this by two lines for alphanumeric sorting.

#[macro_use]
extern crate serde;

pub mod bundle;
pub mod error;
Expand Down