Skip to content

Commit

Permalink
g3bench: allow to verify all keyless result
Browse files Browse the repository at this point in the history
  • Loading branch information
zh-jq-b committed Feb 21, 2025
1 parent 3392a7c commit ebee1bc
Show file tree
Hide file tree
Showing 3 changed files with 167 additions and 18 deletions.
164 changes: 146 additions & 18 deletions g3bench/src/target/keyless/opts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ const ARG_RSA_PADDING: &str = "rsa-padding";
const ARG_PAYLOAD: &str = "payload";
const ARG_DUMP_RESULT: &str = "dump-result";
const ARG_VERIFY: &str = "verify";
const ARG_VERIFY_DATA: &str = "verify-data";

const DIGEST_TYPES: [&str; 6] = ["md5sha1", "sha1", "sha224", "sha256", "sha384", "sha512"];
const RSA_PADDING_VALUES: [&str; 5] = ["PKCS1", "OAEP", "PSS", "X931", "NONE"];
Expand Down Expand Up @@ -172,7 +173,8 @@ pub(super) struct KeylessGlobalArgs {
pub(super) action: KeylessAction,
pub(super) payload: Vec<u8>,
dump_result: bool,
verify_result: Vec<u8>,
verify: bool,
verify_data: Vec<u8>,
}

impl KeylessGlobalArgs {
Expand Down Expand Up @@ -295,8 +297,9 @@ impl KeylessGlobalArgs {
};

let dump_result = args.get_flag(ARG_DUMP_RESULT);
let verify_result = if let Some(s) = args.get_one::<String>(ARG_VERIFY) {
hex::decode(s.as_bytes()).map_err(|e| anyhow!("invalid verify value: {e}"))?
let verify = args.get_flag(ARG_VERIFY);
let verify_data = if let Some(s) = args.get_one::<String>(ARG_VERIFY_DATA) {
hex::decode(s.as_bytes()).map_err(|e| anyhow!("invalid verify data: {e}"))?
} else {
vec![]
};
Expand All @@ -308,7 +311,8 @@ impl KeylessGlobalArgs {
action,
payload,
dump_result,
verify_result,
verify,
verify_data,
})
}

Expand All @@ -317,11 +321,56 @@ impl KeylessGlobalArgs {
let hex_str = hex::encode(&data);
println!("== Output of task {task_id}:\n{hex_str}");
}
if !self.verify_result.is_empty() && self.verify_result != data {
return Err(anyhow!("result verify failed"));

if !self.verify {
return Ok(());
}

Ok(())
match self.action {
KeylessAction::RsaSign(digest, padding) => self.verify_rsa(digest, padding, &data),
KeylessAction::EcdsaSign(digest) => self.verify(digest, &data),
KeylessAction::Ed25519Sign => self.verify_ed(&data),
KeylessAction::Encrypt => {
let decrypted = self.decrypt_data(&data)?;
if decrypted != self.payload {
println!(" original: {data:?}\ndecrypted: {decrypted:?}");
Err(anyhow!("result data can't be decrypted to original"))
} else {
Ok(())
}
}
KeylessAction::RsaEncrypt(padding) => {
let decrypted = self.decrypt_rsa_data(padding, &data)?;
if decrypted != self.payload {
println!(" original: {data:?}\ndecrypted: {decrypted:?}");
Err(anyhow!("result data can't be decrypted to original"))
} else {
Ok(())
}
}
KeylessAction::RsaPrivateEncrypt(padding) => {
let decrypted = self.rsa_public_decrypt_data(padding, &data)?;
if decrypted != self.payload {
Err(anyhow!("result data can't be decrypted to original"))
} else {
Ok(())
}
}
_ => {
if self.verify_data.is_empty() {
return Err(anyhow!("expected data is needed to verify the result"));
}
if self.verify_data != data {
Err(anyhow!(
"result data not match:\nexpected: {:?}\n found: {:?}",
self.verify_data,
data
))
} else {
Ok(())
}
}
}
}

#[inline]
Expand All @@ -336,9 +385,8 @@ impl KeylessGlobalArgs {
}

pub(super) fn encrypt(&self) -> anyhow::Result<Vec<u8>> {
let pkey = self.get_private_key()?;
let mut ctx =
PkeyCtx::new(pkey).map_err(|e| anyhow!("failed to create EVP_PKEY_CTX: {e}"))?;
let mut ctx = PkeyCtx::new(&self.public_key)
.map_err(|e| anyhow!("failed to create EVP_PKEY_CTX: {e}"))?;
ctx.encrypt_init()
.map_err(|e| anyhow!("encrypt init failed: {e}"))?;

Expand All @@ -349,9 +397,8 @@ impl KeylessGlobalArgs {
}

pub(super) fn encrypt_rsa(&self, padding: KeylessRsaPadding) -> anyhow::Result<Vec<u8>> {
let pkey = self.get_private_key()?;
let mut ctx =
PkeyCtx::new(pkey).map_err(|e| anyhow!("failed to create EVP_PKEY_CTX: {e}"))?;
let mut ctx = PkeyCtx::new(&self.public_key)
.map_err(|e| anyhow!("failed to create EVP_PKEY_CTX: {e}"))?;
ctx.encrypt_init()
.map_err(|e| anyhow!("encrypt init failed: {e}"))?;
ctx.set_rsa_padding(padding.into())
Expand All @@ -364,19 +411,27 @@ impl KeylessGlobalArgs {
}

pub(super) fn decrypt(&self) -> anyhow::Result<Vec<u8>> {
self.decrypt_data(&self.payload)
}

fn decrypt_data(&self, from: &[u8]) -> anyhow::Result<Vec<u8>> {
let pkey = self.get_private_key()?;
let mut ctx =
PkeyCtx::new(pkey).map_err(|e| anyhow!("failed to create EVP_PKEY_CTX: {e}"))?;
ctx.decrypt_init()
.map_err(|e| anyhow!("decrypt init failed: {e}"))?;

let mut buf = Vec::new();
ctx.decrypt_to_vec(&self.payload, &mut buf)
ctx.decrypt_to_vec(from, &mut buf)
.map_err(|e| anyhow!("decrypt failed: {e}"))?;
Ok(buf)
}

pub(super) fn decrypt_rsa(&self, padding: KeylessRsaPadding) -> anyhow::Result<Vec<u8>> {
self.decrypt_rsa_data(padding, &self.payload)
}

fn decrypt_rsa_data(&self, padding: KeylessRsaPadding, from: &[u8]) -> anyhow::Result<Vec<u8>> {
let pkey = self.get_private_key()?;
let mut ctx =
PkeyCtx::new(pkey).map_err(|e| anyhow!("failed to create EVP_PKEY_CTX: {e}"))?;
Expand All @@ -386,7 +441,7 @@ impl KeylessGlobalArgs {
.map_err(|e| anyhow!("failed to set rsa padding: {e}"))?;

let mut buf = Vec::new();
ctx.decrypt_to_vec(&self.payload, &mut buf)
ctx.decrypt_to_vec(from, &mut buf)
.map_err(|e| anyhow!("decrypt failed: {e}"))?;
Ok(buf)
}
Expand All @@ -406,6 +461,24 @@ impl KeylessGlobalArgs {
Ok(buf)
}

fn verify(&self, digest: KeylessSignDigest, sig: &[u8]) -> anyhow::Result<()> {
let mut ctx = PkeyCtx::new(&self.public_key)
.map_err(|e| anyhow!("failed to create EVP_PKEY_CTX: {e}"))?;
ctx.verify_init()
.map_err(|e| anyhow!("verify init failed: {e}"))?;
ctx.set_signature_md(digest.md())
.map_err(|e| anyhow!("failed to set signature digest type: {e}"))?;

let verified = ctx
.verify(&self.payload, sig)
.map_err(|e| anyhow!("verify failed: {e}"))?;
if verified {
Ok(())
} else {
Err(anyhow!("sign verify data failed"))
}
}

pub(super) fn sign_rsa(
&self,
digest: KeylessSignDigest,
Expand All @@ -427,6 +500,31 @@ impl KeylessGlobalArgs {
Ok(buf)
}

fn verify_rsa(
&self,
digest: KeylessSignDigest,
padding: KeylessRsaPadding,
sig: &[u8],
) -> anyhow::Result<()> {
let mut ctx = PkeyCtx::new(&self.public_key)
.map_err(|e| anyhow!("failed to create EVP_PKEY_CTX: {e}"))?;
ctx.verify_init()
.map_err(|e| anyhow!("verify init failed: {e}"))?;
ctx.set_signature_md(digest.md())
.map_err(|e| anyhow!("failed to set signature digest type: {e}"))?;
ctx.set_rsa_padding(padding.into())
.map_err(|e| anyhow!("failed to set rsa padding type: {e}"))?;

let verified = ctx
.verify(&self.payload, sig)
.map_err(|e| anyhow!("verify failed: {e}"))?;
if verified {
Ok(())
} else {
Err(anyhow!("sign verify data failed"))
}
}

pub(super) fn sign_ed(&self) -> anyhow::Result<Vec<u8>> {
let pkey = self.get_private_key()?;
let mut ctx =
Expand All @@ -440,6 +538,22 @@ impl KeylessGlobalArgs {
Ok(buf)
}

fn verify_ed(&self, sig: &[u8]) -> anyhow::Result<()> {
let mut ctx = PkeyCtx::new(&self.public_key)
.map_err(|e| anyhow!("failed to create EVP_PKEY_CTX: {e}"))?;
ctx.verify_init()
.map_err(|e| anyhow!("verify init failed: {e}"))?;

let verified = ctx
.verify(&self.payload, sig)
.map_err(|e| anyhow!("verify failed: {e}"))?;
if verified {
Ok(())
} else {
Err(anyhow!("sign verify data failed"))
}
}

pub(super) fn rsa_private_encrypt(
&self,
padding: KeylessRsaPadding,
Expand Down Expand Up @@ -467,6 +581,14 @@ impl KeylessGlobalArgs {
}

pub(super) fn rsa_public_decrypt(&self, padding: KeylessRsaPadding) -> anyhow::Result<Vec<u8>> {
self.rsa_public_decrypt_data(padding, &self.payload)
}

fn rsa_public_decrypt_data(
&self,
padding: KeylessRsaPadding,
from: &[u8],
) -> anyhow::Result<Vec<u8>> {
let rsa = self
.public_key
.rsa()
Expand All @@ -475,15 +597,15 @@ impl KeylessGlobalArgs {
let rsa_size = rsa.size() as usize;
let mut output_buf = vec![0u8; rsa_size];

let payload_len = self.payload.len();
let payload_len = from.len();
if payload_len != rsa_size {
return Err(anyhow!(
"payload length {payload_len} is not equal to RSA size {rsa_size}"
));
}

let len = rsa
.public_decrypt(&self.payload, &mut output_buf, padding.into())
.public_decrypt(from, &mut output_buf, padding.into())
.map_err(|e| anyhow!("rsa public decrypt failed: {e}"))?;
output_buf.truncate(len);
Ok(output_buf)
Expand Down Expand Up @@ -589,9 +711,15 @@ fn add_keyless_args(cmd: Command) -> Command {
.arg(
Arg::new(ARG_VERIFY)
.help("Verify the result")
.num_args(1)
.action(ArgAction::SetTrue)
.long(ARG_VERIFY),
)
.arg(
Arg::new(ARG_VERIFY_DATA)
.help("Verify the result with the same data")
.num_args(1)
.long(ARG_VERIFY_DATA),
)
}

impl AppendKeylessArgs for Command {
Expand Down
7 changes: 7 additions & 0 deletions scripts/coverage/g3bench/mkcert.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,14 @@ cd "${SCRIPT_DIR}"

MKCERT="../../../target/debug/g3mkcert"

# for TLS

$MKCERT --root --common-name "g3 root" --output-cert rootCA.pem --output-key rootCA-key.pem

$MKCERT --tls-server --ca-cert rootCA.pem --ca-key rootCA-key.pem --host g3proxy.local --output-cert g3proxy.local.pem --output-key g3proxy.local-key.pem
$MKCERT --tls-server --ca-cert rootCA.pem --ca-key rootCA-key.pem --host httpbin.local --output-cert httpbin.local.pem --output-key httpbin.local-key.pem

# for Keyless

$MKCERT --root --common-name "g3 root" --output-cert rootCA-RSA.pem --output-key rootCA-RSA-key.pem --rsa 2048
$MKCERT --root --common-name "g3 root" --output-cert rootCA-EC.pem --output-key rootCA-EC-key.pem --ec256
14 changes: 14 additions & 0 deletions scripts/coverage/g3bench/target_keyless_openssl.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@

# RSA

g3bench keyless openssl --key ./rootCA-RSA-key.pem --sign --digest-type sha256 --verify "4d4dfb668f8c6ddd0227c03907515c58779914098a1bf8c169faafdea4d1b91d"

g3bench keyless openssl --key ./rootCA-RSA-key.pem --encrypt --verify "abcdef"
g3bench keyless openssl --key ./rootCA-RSA-key.pem --decrypt --verify --verify-data "abcdef" "540c543665ec51c75b2311f507a01336f2f527831f2294d354ae04642c5f26cf97dd91a9213384c1b991f04e8ce98053394e3d835c5892c42b0494637948d585830fa774e65566385ed91fa6da3277004469d9b3ed54e7ba19738e6e73ed286399d583cde6f2e73d21144b166c345f7f12355b58d5259d2ea4206f9fced27192d287285f0d988a1d400be4c27cc0a563fb6d82b1bfd77bcd2a916cd7f4473f4c13377aa8259e5994fe40f72689fb6e717eb6dbb48e08a5fefb8e09f57bcab29c83c8392cd641d66f73ccd6254f5286b3e61611d97a40209f79cbb6479a613b17e746a3559a33f756a13a9467f3eddba3f7939bd719085df04bed64ba9b59ef75"

g3bench keyless openssl --key ./rootCA-RSA-key.pem --rsa-padding PKCS1 --rsa-private-encrypt --verify "abcdef"
g3bench keyless openssl --key ./rootCA-RSA-key.pem --rsa-padding PKCS1 --rsa-public-decrypt --verify --verify-data "abcdef" "742e92ef67e6f1f0e37e2415172ec2e177e6ac688a7290bcf8c12a92f87f7ac82060e47a2d2d03c08cc82b369b495ddee2d37626424dcacef970632e1ef6ca2315c71910d0dc28feb9831dc7b13d7ee93fad650917bfeb674ff23720c8889aebe95b818d121837c1d4ef101837e88d02cb5599f3858162d0283701683102b5b5c9daf27d25820be740091704e038689855dea9e3fd75b1dcc8942d0f708d1a175584c9304b8e8e720b8c4d78b356f37a4bd908713d3bf3d74bf8c6b8f657d2158239eee621ec6f45c7bdd1f92bb2f9fcd71a39481d7bf7f4d0b439434bb2c9e3d9213400a36edf12222849e023393bccdb20113b0c800b71ce0f8e3a6f81720d"

# EC

g3bench keyless openssl --key ./rootCA-EC-key.pem --sign --digest-type sha256 --verify "4d4dfb668f8c6ddd0227c03907515c58779914098a1bf8c169faafdea4d1b91d"

0 comments on commit ebee1bc

Please sign in to comment.