From 24da2df81265ddfbbeb7dd10fd59eb828afa41b8 Mon Sep 17 00:00:00 2001 From: Katharina Fey Date: Mon, 6 Aug 2018 15:46:57 +0200 Subject: Doing some file management, moving stuff around --- lockchain-core/src/crypto/encoding.rs | 24 --------- lockchain-core/src/crypto/hashing.rs | 25 --------- lockchain-core/src/crypto/keystore.rs | 8 ++- lockchain-core/src/crypto/mod.rs | 9 ++-- lockchain-core/src/crypto/passwords/mod.rs | 7 --- lockchain-core/src/crypto/random.rs | 46 ----------------- lockchain-core/src/crypto/secrets.rs | 25 +++++++++ lockchain-core/src/crypto/store.rs | 15 ++++++ lockchain-core/src/crypto/utils/encoding.rs | 24 +++++++++ lockchain-core/src/crypto/utils/hashing.rs | 25 +++++++++ lockchain-core/src/crypto/utils/mod.rs | 5 ++ lockchain-core/src/crypto/utils/random.rs | 46 +++++++++++++++++ lockchain-core/src/lib.rs | 78 ++++++++++++++++++++++++----- lockchain-core/src/users/auth.rs | 65 +++--------------------- lockchain-core/src/users/mod.rs | 6 +++ lockchain-crypto/Cargo.toml | 2 +- lockchain-server/Cargo.toml | 2 +- 17 files changed, 231 insertions(+), 181 deletions(-) delete mode 100644 lockchain-core/src/crypto/encoding.rs delete mode 100644 lockchain-core/src/crypto/hashing.rs delete mode 100644 lockchain-core/src/crypto/passwords/mod.rs delete mode 100644 lockchain-core/src/crypto/random.rs create mode 100644 lockchain-core/src/crypto/secrets.rs create mode 100644 lockchain-core/src/crypto/store.rs create mode 100644 lockchain-core/src/crypto/utils/encoding.rs create mode 100644 lockchain-core/src/crypto/utils/hashing.rs create mode 100644 lockchain-core/src/crypto/utils/mod.rs create mode 100644 lockchain-core/src/crypto/utils/random.rs diff --git a/lockchain-core/src/crypto/encoding.rs b/lockchain-core/src/crypto/encoding.rs deleted file mode 100644 index 0c49490..0000000 --- a/lockchain-core/src/crypto/encoding.rs +++ /dev/null @@ -1,24 +0,0 @@ -//! Easy to use encoding utility functions - -use base64; -use std::fmt::Write; - -/// Encode a piece of arbitary data into a bse64 string -pub fn base64_encode(data: &Vec) -> String { - return base64::encode(data); -} - -/// Decode a base64 string into arbitrary data -pub fn base64_decode(data: &String) -> Vec { - return base64::decode(data).unwrap(); -} - -/// Simply encode a byte-string as hexadecimal symbols -pub fn encode_hex(data: &str) -> String { - let mut s = String::new(); - for &byte in data.as_bytes() { - write!(&mut s, "{:X}", byte).expect("Unable to HEX encode!"); - } - - return s; -} \ No newline at end of file diff --git a/lockchain-core/src/crypto/hashing.rs b/lockchain-core/src/crypto/hashing.rs deleted file mode 100644 index 4a24a17..0000000 --- a/lockchain-core/src/crypto/hashing.rs +++ /dev/null @@ -1,25 +0,0 @@ -//! Hashing utility functions for various applications - -use blake2::digest::{Input, VariableOutput}; -use blake2::Blake2s; - -const BLAKE_16_LENGTH: usize = 16; - -/// Hash a value with blake2 -pub fn blake2(data: &str, salt: &str) -> [u8; BLAKE_16_LENGTH] { - let mut hasher = match Blake2s::new(BLAKE_16_LENGTH) { - Ok(res) => res, - Err(some) => panic!(some), - }; - - let to_hash = format!("{}{}", data, salt); - hasher.process(to_hash.as_bytes()); - - let mut buffer = [0u8; BLAKE_16_LENGTH]; - match hasher.variable_result(&mut buffer) { - Ok(res) => res, - Err(e) => panic!(e), - }; - - return buffer; -} diff --git a/lockchain-core/src/crypto/keystore.rs b/lockchain-core/src/crypto/keystore.rs index 0f19e30..71d7be2 100644 --- a/lockchain-core/src/crypto/keystore.rs +++ b/lockchain-core/src/crypto/keystore.rs @@ -1,4 +1,10 @@ -//! A utility keystore module for the lockchain ecosystem +//! A keystore is a specific implementation of a metadata store +//! +//! At it's core it provides three simple functions +//! +//! - Adding keys for a user +//! - Removing keys +//! - Retrieving keys use traits::{AutoEncoder, Base64AutoEncoder}; use {crypto::Key, meta::MetaDomain}; diff --git a/lockchain-core/src/crypto/mod.rs b/lockchain-core/src/crypto/mod.rs index 671cff0..ad9c0e1 100644 --- a/lockchain-core/src/crypto/mod.rs +++ b/lockchain-core/src/crypto/mod.rs @@ -2,7 +2,6 @@ //! //! -mod data; /// We re-export keybob's API here mod keys { @@ -13,11 +12,11 @@ mod keys { impl AutoEncoder for KeyType {} } -// pub mod passwords; -pub mod encoding; +mod data; +mod utils; +pub use utils::*; pub mod keystore; -pub mod hashing; -pub mod random; +pub mod store; pub use self::data::PackedData; pub use self::keystore::KeyStore; diff --git a/lockchain-core/src/crypto/passwords/mod.rs b/lockchain-core/src/crypto/passwords/mod.rs deleted file mode 100644 index 331ec9d..0000000 --- a/lockchain-core/src/crypto/passwords/mod.rs +++ /dev/null @@ -1,7 +0,0 @@ -//! A series of password generators for user-facing applications - - - -pub enum PwType { - -} diff --git a/lockchain-core/src/crypto/random.rs b/lockchain-core/src/crypto/random.rs deleted file mode 100644 index 7d31992..0000000 --- a/lockchain-core/src/crypto/random.rs +++ /dev/null @@ -1,46 +0,0 @@ -//! A small convenience wrapper around `rand` - -use rand::{thread_rng, Rng}; - -/// Generate a random number with an upper bound -pub fn number(bound: u64) -> u64 { - return thread_rng().next_u64() % bound; -} - -/// Generate a sequence of random bytes that are returned -/// as a vector. -/// -/// Can at most allocate 2048 bytes at a time -/// FIXME: That shouldn't have a limit! -pub fn bytes(length: usize) -> Vec { - let mut vec: Vec = Vec::new(); - - if length > 2048 { - return vec; - } - - let mut random_data = [0u8; 2048]; - thread_rng().fill_bytes(&mut random_data); - - for i in 0..length { - vec.push(random_data[i]); - } - - return vec; -} - -/// A small utility wraper around bcrypt to allow -/// easy password checking. -pub mod passwd { - use bcrypt::{self, DEFAULT_COST}; - - /// Create a new password, returning a hash - pub fn create(pw: &str) -> Option { - Some(bcrypt::hash(pw, DEFAULT_COST).ok()?) - } - - /// Verify a password against it's stored hash - pub fn verify(pw: &str, hash: &str) -> Option { - bcrypt::verify(pw, hash).ok() - } -} diff --git a/lockchain-core/src/crypto/secrets.rs b/lockchain-core/src/crypto/secrets.rs new file mode 100644 index 0000000..87e2c13 --- /dev/null +++ b/lockchain-core/src/crypto/secrets.rs @@ -0,0 +1,25 @@ + +/// Specifies the type of secret that's used to derive a vault user secret +pub enum SecretType { + /// A simple password + Plain, + /// A keyfile that allows asymetric trust operations + Keyfile, + /// Signing a user password with the id of a yubikey + Combine, +} + +/// The backing secret for user authentication +/// +/// This is _always_ in a non-recoverable form, i.e. a hash +/// and salted password. **However** it does reveal something +/// about the user setup, i.e. the type of secret used. +/// +/// Depending on what secret is used, there are other operations that +/// might be supported to verify operations. For example, a `Keyfile` +/// secret can deposit the entire public key in the `content` field, +/// then use asymmetric operations to verify operations more thoroughly. +pub struct UserSecret { + type: SecretType, + content: String, +} diff --git a/lockchain-core/src/crypto/store.rs b/lockchain-core/src/crypto/store.rs new file mode 100644 index 0000000..f57359d --- /dev/null +++ b/lockchain-core/src/crypto/store.rs @@ -0,0 +1,15 @@ + +use std::collections::HashMap; + +/// A thin user keystore +/// +/// It's implementation can manage multiple keys per user, of various +/// types and constrained for limited access rights. +pub struct KeyStore { + +} + +struct StoreUser { + name: String, + HashMap< +} \ No newline at end of file diff --git a/lockchain-core/src/crypto/utils/encoding.rs b/lockchain-core/src/crypto/utils/encoding.rs new file mode 100644 index 0000000..0c49490 --- /dev/null +++ b/lockchain-core/src/crypto/utils/encoding.rs @@ -0,0 +1,24 @@ +//! Easy to use encoding utility functions + +use base64; +use std::fmt::Write; + +/// Encode a piece of arbitary data into a bse64 string +pub fn base64_encode(data: &Vec) -> String { + return base64::encode(data); +} + +/// Decode a base64 string into arbitrary data +pub fn base64_decode(data: &String) -> Vec { + return base64::decode(data).unwrap(); +} + +/// Simply encode a byte-string as hexadecimal symbols +pub fn encode_hex(data: &str) -> String { + let mut s = String::new(); + for &byte in data.as_bytes() { + write!(&mut s, "{:X}", byte).expect("Unable to HEX encode!"); + } + + return s; +} \ No newline at end of file diff --git a/lockchain-core/src/crypto/utils/hashing.rs b/lockchain-core/src/crypto/utils/hashing.rs new file mode 100644 index 0000000..4a24a17 --- /dev/null +++ b/lockchain-core/src/crypto/utils/hashing.rs @@ -0,0 +1,25 @@ +//! Hashing utility functions for various applications + +use blake2::digest::{Input, VariableOutput}; +use blake2::Blake2s; + +const BLAKE_16_LENGTH: usize = 16; + +/// Hash a value with blake2 +pub fn blake2(data: &str, salt: &str) -> [u8; BLAKE_16_LENGTH] { + let mut hasher = match Blake2s::new(BLAKE_16_LENGTH) { + Ok(res) => res, + Err(some) => panic!(some), + }; + + let to_hash = format!("{}{}", data, salt); + hasher.process(to_hash.as_bytes()); + + let mut buffer = [0u8; BLAKE_16_LENGTH]; + match hasher.variable_result(&mut buffer) { + Ok(res) => res, + Err(e) => panic!(e), + }; + + return buffer; +} diff --git a/lockchain-core/src/crypto/utils/mod.rs b/lockchain-core/src/crypto/utils/mod.rs new file mode 100644 index 0000000..d57689c --- /dev/null +++ b/lockchain-core/src/crypto/utils/mod.rs @@ -0,0 +1,5 @@ +//! A collection of common cryptography utilities. + +pub mod encoding; +pub mod random; +pub mod hashing; \ No newline at end of file diff --git a/lockchain-core/src/crypto/utils/random.rs b/lockchain-core/src/crypto/utils/random.rs new file mode 100644 index 0000000..7d31992 --- /dev/null +++ b/lockchain-core/src/crypto/utils/random.rs @@ -0,0 +1,46 @@ +//! A small convenience wrapper around `rand` + +use rand::{thread_rng, Rng}; + +/// Generate a random number with an upper bound +pub fn number(bound: u64) -> u64 { + return thread_rng().next_u64() % bound; +} + +/// Generate a sequence of random bytes that are returned +/// as a vector. +/// +/// Can at most allocate 2048 bytes at a time +/// FIXME: That shouldn't have a limit! +pub fn bytes(length: usize) -> Vec { + let mut vec: Vec = Vec::new(); + + if length > 2048 { + return vec; + } + + let mut random_data = [0u8; 2048]; + thread_rng().fill_bytes(&mut random_data); + + for i in 0..length { + vec.push(random_data[i]); + } + + return vec; +} + +/// A small utility wraper around bcrypt to allow +/// easy password checking. +pub mod passwd { + use bcrypt::{self, DEFAULT_COST}; + + /// Create a new password, returning a hash + pub fn create(pw: &str) -> Option { + Some(bcrypt::hash(pw, DEFAULT_COST).ok()?) + } + + /// Verify a password against it's stored hash + pub fn verify(pw: &str, hash: &str) -> Option { + bcrypt::verify(pw, hash).ok() + } +} diff --git a/lockchain-core/src/lib.rs b/lockchain-core/src/lib.rs index cb02caf..a7b5b0c 100644 --- a/lockchain-core/src/lib.rs +++ b/lockchain-core/src/lib.rs @@ -1,27 +1,81 @@ -//! Common library types used in lockchain crates -#![feature(external_doc)] -#![doc(include = "../README.md")] +//! A common set of functions & types for the `lockchain` ecosystem. +//! +//! This crate by itself doesn't do much. It is meant to be used as the central +//! adapter between a variety of other crates from the `lockchain` ecosystem, +//! that all plug and interact with types and functions defined in this library. +//! +//! This documentation is meant as an outline of what the core crate does and how +//! you can use it, in combination with other libraries, in your application. +//! +//! ## Overview +//! +//! At it's centre, `lockchain-core` defines storage traits. These come in a few +//! forms, from `Vault`, being a very generic interface over what is meant as a +//! secure storage collection, to `Record`, being an individual record in such a +//! system. This means that both the nature of `Vault` and `Record` are generic +//! implementation details, left to you to pick for your application, depending on +//! what fits your needs. +//! +//! Additionally there are of course crypto primitives. `lockchain-core` exposes the +//! `keybob` API for generation and verification of clear text secrets that can be +//! padded to generate AES encryption keys. It adds a user management layer that provides +//! login, permissions as well as second-factor authentication (such as a yubikey). And it +//! provides an easy to use keystore, which binds encrypted keys to user identities, so that +//! encryption never has to be done outside of the users scope. +//! +//! --- +//! +//! ## Usage +//! +//! This means that there's no one way of using `lockchain-core`, instead there are other crates +//! that plug into it. Following is a list of crates, maintained by the `lockchain` team that +//! were designed to work seemlessly with `lockchain-core`. +//! +//! - `lockchain-crypto` is an adapter layer that adds the ability to stream-decrypt records from +//! any kind of vault +//! - `lockchain-files` is a storage adapter which implements a file-storage layer for a vault +//! - `lockchain-memory` is a storage adapter which implements a vault only in memory +//! - `lockchain-client` provides a shim layer between a common client interface and several server-facing +//! communication interfaces, such as `http` or `unix-sockets` +//! - `lockchain-http` provides an http shim on top of the core lockchain API's +//! - `lockchain-unix` provides a unix socket API shim, similar to the http layer +//! +//! The core principle behind lockchain's design was that the server can store encrypted files, without +//! having the capability of being made to decrypt them. That means that the code required +//! is physically not contained in the binary. +//! +//! Primarily this means that crypto is always done on the "client side", however this is up to _you_ to define. +//! Your application might have different needs than were envisioned for lockchain, and as such you can pick +//! and choose from features across the entire `lockchain` ecosystem to which fit your usecase best. +//! +//! ## Something missing? +//! +//! This crate ecosystem is still in active development. There are several projects that aim to use +//! the `lockchain` ecosystem for secure storage needs. As such, we hope to have covered most use cases +//! already. +//! +//! If we missed something, please let us know! #[macro_use] extern crate serde_derive; -extern crate serde_json; -extern crate serde; -extern crate chrono; -extern crate bcrypt; extern crate base64; +extern crate bcrypt; extern crate blake2; -extern crate rand; +extern crate chrono; extern crate keybob; extern crate nix; extern crate pam_auth; +extern crate rand; +extern crate serde; +extern crate serde_json; -pub mod errors; -pub mod traits; pub mod crypto; -pub mod users; +pub mod errors; mod meta; mod record; +pub mod traits; +pub mod users; pub use self::crypto::PackedData; -pub use self::record::{Header, Payload, Record, EncryptedBody}; pub use self::meta::{MetaDomain, VaultMetadata}; +pub use self::record::{EncryptedBody, Header, Payload, Record}; diff --git a/lockchain-core/src/users/auth.rs b/lockchain-core/src/users/auth.rs index aee3be1..1a8758c 100644 --- a/lockchain-core/src/users/auth.rs +++ b/lockchain-core/src/users/auth.rs @@ -3,9 +3,6 @@ //! The way a user is authenticated is via the `lockchain` group //! and a simple writing/ deleting of a lock file. -// use nix::sys::wait::*; -// use nix::unistd::{fork, ForkResult}; - use pam_auth::Authenticator; use errors::AuthError; @@ -23,60 +20,10 @@ use errors::AuthError; /// yet due to issues in the `pam-auth` dependency. #[allow(unused_variables)] pub fn pam_authenticate(username: &str, password: &str) -> Result<(), AuthError> { - // Err(AuthError::FailedPAM) - - // match fork().map_err(|_| AuthError::FailedFork)? { - // ForkResult::Parent { child } => { - // waitpid(child, None).unwrap(); - // // kill(child, SIGKILL).expect("kill failed"); - // } - // ForkResult::Child => { - // let mut auth = Authenticator::new("lockchain").ok_or(AuthError::FailedPAM)?; - - use std::error::Error; - let service = "lockchain-core"; - - println!("Username: {}", username); - println!("Password: {}", password); - println!("Service: {}", service); - - let mut auth = Authenticator::new(service).unwrap(); - auth.set_credentials(username, password); - - match auth.authenticate() { - Ok(()) => println!("authenticate() OK!"), - Err(e) => { - println!("authenticate() FAILED!"); - println!("{}", e.description()); - println!("{:#?}", e.cause()); - } - } - - match auth.open_session() { - Ok(()) => println!("open_session() OK!"), - Err(e) => { - println!("open_session() FAILED!"); - println!("{}", e.description()); - println!("{:#?}", e.cause()); - } - } - - Ok(()) - - // auth.set_credentials(username, password); - // auth.authenticate().map_err(|_| AuthError::InvalidUser)?; - // auth.open_session().map_err(|_| AuthError::FailedPAM)?; - - // use std::process::Command; - // let output = Command::new("su") - // .arg(username) - // .output() - // .expect("failed to execute process"); - // println!("whoami: {:#?}", String::from_utf8(output.stdout).unwrap()); - - // ::std::process::exit(255); - // } - // } - - // Ok(()) + unimplemented!() } + +/// Tbd... +pub fn yubikey_authenticate(username: &str, yubi_id: &str) -> Result<(), AuthError> { + unimplemented!() +} \ No newline at end of file diff --git a/lockchain-core/src/users/mod.rs b/lockchain-core/src/users/mod.rs index 03cbcb4..338cc5e 100644 --- a/lockchain-core/src/users/mod.rs +++ b/lockchain-core/src/users/mod.rs @@ -82,6 +82,12 @@ impl User { pub fn verify(&self, pw: &str) -> bool { self.pw_hash == encoding::base64_encode(&hashing::blake2(pw, &self.name).to_vec()) } + /// Provides a hook to use second-factor authentication to authorise + /// + /// This is meant to be used with an external Yubikey + pub fn second_auth_verify(&mut self) -> bool { + unimplemented!() + } /// Generate a token unique to this user (or return the existing one) pub fn token(&mut self) -> String { if self.token.is_none() { diff --git a/lockchain-crypto/Cargo.toml b/lockchain-crypto/Cargo.toml index acf31b5..656f60f 100644 --- a/lockchain-crypto/Cargo.toml +++ b/lockchain-crypto/Cargo.toml @@ -9,7 +9,7 @@ version = "0.8.1-alpha.0" authors = ["Katharina Fey "] [dependencies] -lockchain-core = { version = "0.9.0" } #, path = "../lockchain-core" } +lockchain-core = { version = "0.9.0", path = "../lockchain-core" } serde_derive = "1.0" serde = "1.0" diff --git a/lockchain-server/Cargo.toml b/lockchain-server/Cargo.toml index 7398ea2..1fa3a32 100644 --- a/lockchain-server/Cargo.toml +++ b/lockchain-server/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Katharina Fey "] [dependencies] lockchain-core = { path = "../lockchain-core" } -lockchain-files ={ path = "../lockchain-files" } +lockchain-files = { path = "../lockchain-files" } lockchain-http = { path = "../lockchain-http" } clap = "2.0" -- cgit v1.2.3