Skip to content

Commit

Permalink
g3keymess: allow to check key existence
Browse files Browse the repository at this point in the history
  • Loading branch information
zh-jq-b committed Oct 16, 2023
1 parent a9da70c commit 9856786
Show file tree
Hide file tree
Showing 13 changed files with 113 additions and 31 deletions.
4 changes: 3 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ g3-stdlog = { version = "0.1", path = "lib/g3-stdlog" }
g3-syslog = { version = "0.6", path = "lib/g3-syslog" }
g3-slog-types = { version = "0.1", path = "lib/g3-slog-types" }
g3-geoip = { version = "0.1", path = "lib/g3-geoip" }
g3-tls-cert = { version = "0.3", path = "lib/g3-tls-cert" }
g3-tls-cert = { version = "0.4", path = "lib/g3-tls-cert" }
g3-types = { version = "0.3", path = "lib/g3-types" }
g3-xcrypt = { version = "0.1", path = "lib/g3-xcrypt" }
g3-yaml = { version = "0.4.1", path = "lib/g3-yaml" }
Expand Down
18 changes: 5 additions & 13 deletions g3bench/src/target/keyless/opts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use openssl::pkey::{Id, PKey, Private, Public};
use openssl::pkey_ctx::PkeyCtx;
use openssl::rsa::Padding;

use g3_tls_cert::ext::{X509Ext, X509Pubkey};
use g3_tls_cert::ext::{PublicKeyExt, X509Ext};

const ARG_CERT: &str = "cert";
const ARG_PKEY: &str = "key";
Expand Down Expand Up @@ -203,18 +203,10 @@ impl KeylessGlobalArgs {
let key = crate::target::openssl::load_key(file)?;

// verify SKI match
let x509_pubkey = X509Pubkey::from_pubkey(&key).map_err(|e| {
anyhow!(
"failed to create x509 pubkey from key in file {}: {e}",
file.display()
)
})?;
let encoded_bytes = x509_pubkey
.encoded_bytes()
.map_err(|e| anyhow!("failed to get encoded pubkey data: {e}"))?;
let digest = openssl::hash::hash(MessageDigest::sha1(), encoded_bytes)
.map_err(|e| anyhow!("failed to get sha1 hash of pubkey: {e}"))?;
let ski = digest.to_vec();
let ski = key
.ski()
.map_err(|e| anyhow!("failed to get SKI from key file {}: {e}", file.display()))?;
let ski = ski.to_vec();

if let Some(ski_cert) = &public_key_ski {
if ski.ne(ski_cert) {
Expand Down
1 change: 1 addition & 0 deletions g3keymess/proto/schema/proc.capnp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ interface ProcControl {

publishKey @4 (pem: Text) -> (result :Types.OperationResult);
listKeys @5 () -> (result :List(Data));
checkKey @7 (ski: Data) -> (result: Types.OperationResult);

addMetricsTag @6 (name :Text, value :Text) -> (result :Types.OperationResult);
}
9 changes: 9 additions & 0 deletions g3keymess/src/control/bridge/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,15 @@ pub(crate) async fn list_keys() -> anyhow::Result<Vec<Vec<u8>>> {
run_in_main_thread(async move { Ok(crate::store::get_all_ski()) }).await
}

pub(crate) async fn check_key(ski: Vec<u8>) -> anyhow::Result<()> {
run_in_main_thread(async move {
crate::store::get_by_ski(&ski)
.map(|_| ())
.ok_or_else(|| anyhow!("key not found"))
})
.await
}

async fn run_in_main_thread<T, F>(future: F) -> anyhow::Result<T>
where
T: Send + 'static,
Expand Down
13 changes: 13 additions & 0 deletions g3keymess/src/control/capnp/proc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,19 @@ impl proc_control::Server for ProcControlImpl {
})
}

fn check_key(
&mut self,
params: proc_control::CheckKeyParams,
mut results: proc_control::CheckKeyResults,
) -> Promise<(), capnp::Error> {
let ski = pry!(pry!(params.get()).get_ski()).to_vec();
Promise::from_future(async move {
let r = crate::control::bridge::check_key(ski).await;
set_operation_result(results.get().init_result(), r);
Ok(())
})
}

fn add_metrics_tag(
&mut self,
params: proc_control::AddMetricsTagParams,
Expand Down
17 changes: 3 additions & 14 deletions g3keymess/src/store/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,9 @@ use std::cell::RefCell;

use ahash::AHashMap;
use anyhow::anyhow;
use openssl::hash::{DigestBytes, MessageDigest};
use openssl::pkey::{HasPublic, PKey, Private};
use openssl::pkey::{PKey, Private};

use g3_tls_cert::ext::X509Pubkey;
use g3_tls_cert::ext::PublicKeyExt;

mod ops;
pub use ops::{load_all, reload_all};
Expand All @@ -33,7 +32,7 @@ thread_local! {
}

pub(crate) fn add_global(key: PKey<Private>) -> anyhow::Result<()> {
let ski = public_key_ski(&key)?;
let ski = key.ski().map_err(|e| anyhow!("failed to get SKI: {e}"))?;
GLOBAL_SKI_MAP.with_borrow_mut(|map| {
map.insert(ski.to_vec(), key);
});
Expand All @@ -48,13 +47,3 @@ pub(crate) fn get_all_ski() -> Vec<Vec<u8>> {
pub(crate) fn get_by_ski(ski: &[u8]) -> Option<PKey<Private>> {
GLOBAL_SKI_MAP.with_borrow(|map| map.get(ski).cloned())
}

fn public_key_ski<T: HasPublic>(key: &PKey<T>) -> anyhow::Result<DigestBytes> {
let x =
X509Pubkey::from_pubkey(key).map_err(|e| anyhow!("failed to build X509 PUBKEY: {e}"))?;
let encoded = x
.encoded_bytes()
.map_err(|e| anyhow!("failed to get encoded X509 PUBKEY bytes: {e}"))?;
openssl::hash::hash(MessageDigest::sha1(), encoded)
.map_err(|e| anyhow!("failed to calculate SKI value: {e}"))
}
2 changes: 2 additions & 0 deletions g3keymess/utils/ctl/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,5 +17,7 @@ futures-util.workspace = true
capnp-rpc.workspace = true
capnp.workspace = true
hex.workspace = true
openssl.workspace = true
g3-ctl.workspace = true
g3-tls-cert.workspace = true
g3keymess-proto = { path = "../../proto" }
2 changes: 2 additions & 0 deletions g3keymess/utils/ctl/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ fn build_cli_args() -> Command {
.subcommand(proc::commands::offline())
.subcommand(proc::commands::list())
.subcommand(proc::commands::publish_key())
.subcommand(proc::commands::check_key())
.subcommand(server::command())
}

Expand Down Expand Up @@ -172,6 +173,7 @@ async fn main() -> anyhow::Result<()> {
proc::COMMAND_OFFLINE => proc::offline(&proc_control).await,
proc::COMMAND_LIST => proc::list(&proc_control, args).await,
proc::COMMAND_PUBLISH_KEY => proc::publish_key(&proc_control, args).await,
proc::COMMAND_CHECK_KEY => proc::check_key(&proc_control, args).await,
server::COMMAND => server::run(&proc_control, args).await,
_ => unreachable!(),
}
Expand Down
36 changes: 36 additions & 0 deletions g3keymess/utils/ctl/src/proc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,11 @@ use std::path::PathBuf;

use anyhow::anyhow;
use clap::ArgMatches;
use openssl::pkey::PKey;

use g3_ctl::{CommandError, CommandResult};

use g3_tls_cert::ext::PublicKeyExt;
use g3keymess_proto::proc_capnp::proc_control;
use g3keymess_proto::server_capnp::server_control;

Expand All @@ -30,6 +32,7 @@ pub const COMMAND_VERSION: &str = "version";
pub const COMMAND_OFFLINE: &str = "offline";
pub const COMMAND_LIST: &str = "list";
pub const COMMAND_PUBLISH_KEY: &str = "publish-key";
pub const COMMAND_CHECK_KEY: &str = "check-key";

const COMMAND_LIST_ARG_RESOURCE: &str = "resource";
const RESOURCE_VALUE_SERVER: &str = "server";
Expand Down Expand Up @@ -69,6 +72,17 @@ pub mod commands {
.value_hint(ValueHint::FilePath),
)
}

pub fn check_key() -> Command {
Command::new(COMMAND_CHECK_KEY).arg(
Arg::new(COMMAND_ARG_FILE)
.help("Private key file in pem format")
.required(true)
.num_args(1)
.value_parser(value_parser!(PathBuf))
.value_hint(ValueHint::FilePath),
)
}
}

pub async fn version(client: &proc_control::Client) -> CommandResult<()> {
Expand Down Expand Up @@ -130,3 +144,25 @@ pub async fn publish_key(client: &proc_control::Client, args: &ArgMatches) -> Co
let rsp = req.send().promise.await?;
parse_operation_result(rsp.get()?.get_result()?)
}

pub async fn check_key(client: &proc_control::Client, args: &ArgMatches) -> CommandResult<()> {
let file = args.get_one::<PathBuf>(COMMAND_ARG_FILE).unwrap();
let content = std::fs::read_to_string(file).map_err(|e| {
CommandError::Cli(anyhow!(
"failed to read content of file {}: {e}",
file.display()
))
})?;

let key = PKey::private_key_from_pem(content.as_bytes()).map_err(|e| {
CommandError::Cli(anyhow!("failed to load key from {}: {e}", file.display()))
})?;
let ski = key.ski().map_err(|e| {
CommandError::Cli(anyhow!("failed to get SKI for key {}: {e}", file.display()))
})?;

let mut req = client.check_key_request();
req.get().set_ski(&ski);
let rsp = req.send().promise.await?;
parse_operation_result(rsp.get()?.get_result()?)
}
2 changes: 1 addition & 1 deletion lib/g3-tls-cert/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "g3-tls-cert"
version = "0.3.0"
version = "0.4.0"
license.workspace = true
edition.workspace = true

Expand Down
5 changes: 4 additions & 1 deletion lib/g3-tls-cert/src/ext/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,10 @@ mod x509_builder;
pub use x509_builder::X509BuilderExt;

mod x509_pubkey;
pub use x509_pubkey::{X509Pubkey, X509PubkeyRef};
use x509_pubkey::{X509Pubkey, X509PubkeyRef};

mod rsa;
pub use rsa::RsaExt;

mod pkey;
pub use pkey::PublicKeyExt;
33 changes: 33 additions & 0 deletions lib/g3-tls-cert/src/ext/pkey.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/*
* Copyright 2023 ByteDance and/or its affiliates.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

use openssl::error::ErrorStack;
use openssl::hash::{DigestBytes, MessageDigest};
use openssl::pkey::{HasPublic, PKey};

use super::X509Pubkey;

pub trait PublicKeyExt {
fn ski(&self) -> Result<DigestBytes, ErrorStack>;
}

impl<T: HasPublic> PublicKeyExt for PKey<T> {
fn ski(&self) -> Result<DigestBytes, ErrorStack> {
let x = X509Pubkey::from_pubkey(self)?;
let encoded = x.encoded_bytes()?;
openssl::hash::hash(MessageDigest::sha1(), encoded)
}
}

0 comments on commit 9856786

Please sign in to comment.