Skip to content

Commit

Permalink
Merge pull request #15 from int08h/1.1.3
Browse files Browse the repository at this point in the history
Add decryption to 'roughenough-kms'
  • Loading branch information
int08h authored Feb 2, 2019
2 parents 9515a56 + 9d7d18b commit fc463f8
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 39 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## Version 1.1.3

* Add decrypt option to `roughenough-kms`

## Version 1.1.2

* Add client request statistics tracking.
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "roughenough"
version = "1.1.2"
version = "1.1.3"
repository = "https://github.com/int08h/roughenough"
authors = ["Stuart Stock <[email protected]>", "Aaron Hill <[email protected]>"]
license = "Apache-2.0"
Expand Down
108 changes: 71 additions & 37 deletions src/bin/roughenough-kms.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,36 @@
// limitations under the License.

//!
//! CLI used to encrypt the Roughenough long-term key using one of the KMS implementations
//! CLI used to encrypt and decrypt the Roughenough long-term key
//! using one of the KMS implementations
//!
#[macro_use]
extern crate log;

use clap::{App, Arg};

#[allow(unused_imports)]
use roughenough::kms::{EnvelopeEncryption, KmsProvider};
use roughenough::roughenough_version;

#[cfg(feature = "awskms")]
fn aws_kms(kms_key: &str, plaintext_seed: &[u8]) {
use roughenough::kms::{AwsKms, EnvelopeEncryption};
#[cfg(not(any(feature = "awskms", feature = "gcpkms")))]
fn encrypt_seed(_: &str, _: &str) {
// main() will exit if kms support is not enabled, making this unreachable
unreachable!()
}

#[cfg(any(feature = "awskms", feature = "gcpkms"))]
fn encrypt_seed(kms_key: &str, hex_seed: &str) {
let kms_client = get_kms(kms_key);

let client = AwsKms::from_arn(kms_key).unwrap();
let plaintext_seed = hex::decode(hex_seed).expect("Error decoding hex seed value");

if plaintext_seed.len() != 32 {
panic!("Seed must be 32 bytes long; provided seed is {}", plaintext_seed.len());
}

match EnvelopeEncryption::encrypt_seed(&client, &plaintext_seed) {
match EnvelopeEncryption::encrypt_seed(&kms_client, &plaintext_seed) {
Ok(encrypted_blob) => {
println!("kms_protection: \"{}\"", kms_key);
println!("seed: {}", hex::encode(&encrypted_blob));
Expand All @@ -39,23 +53,39 @@ fn aws_kms(kms_key: &str, plaintext_seed: &[u8]) {
}
}

#[cfg(feature = "gcpkms")]
fn gcp_kms(kms_key: &str, plaintext_seed: &[u8]) {
use roughenough::kms::{EnvelopeEncryption, GcpKms};
#[cfg(not(any(feature = "awskms", feature = "gcpkms")))]
fn decrypt_blob(_: &str, _: &str) {
// main() will exit if kms support is not enabled, making this unreachable
unreachable!()
}

let client = GcpKms::from_resource_id(kms_key).unwrap();
#[cfg(any(feature = "awskms", feature = "gcpkms"))]
fn decrypt_blob(kms_key: &str, hex_blob: &str) {
let kms_client = get_kms(kms_key);
let ciphertext = hex::decode(hex_blob).expect("Error decoding hex blob value");

match EnvelopeEncryption::encrypt_seed(&client, &plaintext_seed) {
Ok(encrypted_blob) => {
println!("kms_protection: \"{}\"", kms_key);
println!("seed: {}", hex::encode(&encrypted_blob));
match EnvelopeEncryption::decrypt_seed(&kms_client, ciphertext.as_ref()) {
Ok(plaintext) => {
println!("{}", hex::encode(plaintext));
}
Err(e) => {
error!("Error: {:?}", e);
}
}
}

#[cfg(feature = "awskms")]
fn get_kms(kms_key: &str) -> impl KmsProvider {
use roughenough::kms::AwsKms;
AwsKms::from_arn(kms_key).unwrap()
}

#[cfg(feature = "gcpkms")]
fn get_kms(kms_key: &str) -> impl KmsProvider {
use roughenough::kms::GcpKms;
GcpKms::from_resource_id(kms_key).unwrap()
}

#[allow(unused_variables)]
pub fn main() {
use log::Level;
Expand All @@ -64,45 +94,49 @@ pub fn main() {

let matches = App::new("roughenough-kms")
.version(roughenough_version().as_ref())
.long_about("Encrypt a Roughenough server's long-term seed using a KMS")
.long_about("Encrypt and decrypt Roughenough long-term server seeds using a KMS")
.arg(
Arg::with_name("KEY_ID")
.short("k")
.long("kms-key")
.takes_value(true)
.required(true)
.help("Identity of the KMS key to be used"),
.help("Identity of the KMS key to be used")
).arg(
Arg::with_name("DECRYPT")
.short("d")
.long("decrypt")
.takes_value(true)
.required(false)
.help("Previously encrypted blob to decrypt to plaintext"),
).arg(
Arg::with_name("SEED")
.short("s")
.long("seed")
.takes_value(true)
.required(true)
.required(false)
.help("32 byte hex seed for the server's long-term identity"),
).get_matches();

let kms_key = matches.value_of("KEY_ID").unwrap();
let plaintext_seed = matches
.value_of("SEED")
.map(|seed| hex::decode(seed).expect("Error parsing seed value"))
.unwrap();

if plaintext_seed.len() != 32 {
error!(
"Seed must be 32 bytes long; provided seed is {}",
plaintext_seed.len()
);
return;
if !(cfg!(feature = "gcpkms") || cfg!(feature = "awskms")) {
warn!("KMS support was not compiled into this build; nothing to do.");
warn!("See the Roughenough documentation for information on KMS support.");
warn!(" https://github.com/int08h/roughenough/blob/master/doc/OPTIONAL-FEATURES.md");
return
}

if cfg!(feature = "awskms") {
#[cfg(feature = "awskms")]
aws_kms(kms_key, &plaintext_seed);
} else if cfg!(feature = "gcpkms") {
#[cfg(feature = "gcpkms")]
gcp_kms(kms_key, &plaintext_seed);
let kms_key = matches.value_of("KEY_ID").expect("Invalid KMS key id");

if matches.is_present("SEED") {
let hex_seed = matches.value_of("SEED").expect("Invalid seed value");
encrypt_seed(kms_key, hex_seed);

} else if matches.is_present("DECRYPT") {
let hex_blob = matches.value_of("DECRYPT").expect("Invalid blob value");
decrypt_blob(kms_key, hex_blob);

} else {
warn!("KMS support was not compiled, nothing to do.");
warn!("For information on KMS support see the Roughenough documentation.");
error!("Neither seed encryption (-s) or blob decryption (-d) was specified.");
error!("One of them is required.");
}
}
2 changes: 1 addition & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ pub use crate::message::RtMessage;
pub use crate::tag::Tag;

/// Version of Roughenough
pub const VERSION: &str = "1.1.2";
pub const VERSION: &str = "1.1.3";

/// Roughenough version string enriched with any compile-time optional features
pub fn roughenough_version() -> String {
Expand Down

0 comments on commit fc463f8

Please sign in to comment.