From 800d94e5fb0aa1020443b7d3838aa357acc72a4e Mon Sep 17 00:00:00 2001 From: Hatter Jiang Date: Wed, 14 May 2025 23:01:55 +0800 Subject: [PATCH] feat: v1.1.0, add external sign/ecdh support --- Cargo.toml | 2 +- examples/external_ecdh.rs | 13 +++++++++ examples/external_sign.rs | 10 +++++++ src/lib.rs | 58 +++++++++++++++++++++++++++++++-------- 4 files changed, 70 insertions(+), 13 deletions(-) create mode 100644 examples/external_ecdh.rs create mode 100644 examples/external_sign.rs diff --git a/Cargo.toml b/Cargo.toml index ff8e09a..ded0826 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "swift-secure-enclave-tool-rs" -version = "1.0.0" +version = "1.1.0" edition = "2024" authors = ["Hatter Jiang"] repository = "https://git.hatter.ink/hatter/swift-secure-enclave-tool-rs" diff --git a/examples/external_ecdh.rs b/examples/external_ecdh.rs new file mode 100644 index 0000000..a92901d --- /dev/null +++ b/examples/external_ecdh.rs @@ -0,0 +1,13 @@ +use base64::engine::general_purpose::STANDARD; +use base64::Engine; +use swift_secure_enclave_tool_rs::external_ecdh; + +fn main() { + let args = std::env::args().collect::>(); + let parameter = &args[1]; + let epk = STANDARD.decode(&args[2]).unwrap(); + + let shared_secret = external_ecdh("card-cli", parameter, &epk).unwrap(); + + println!("{}", hex::encode(&shared_secret)); +} diff --git a/examples/external_sign.rs b/examples/external_sign.rs new file mode 100644 index 0000000..8a6b86e --- /dev/null +++ b/examples/external_sign.rs @@ -0,0 +1,10 @@ +use swift_secure_enclave_tool_rs::external_sign; + +fn main() { + let args = std::env::args().collect::>(); + let parameter = &args[1]; + + let signature = external_sign("card-cli", parameter, "ES256", b"hello world").unwrap(); + + println!("{}", hex::encode(&signature)); +} diff --git a/src/lib.rs b/src/lib.rs index ba336fd..f4fbbc4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -133,14 +133,7 @@ pub fn private_key_sign(private_key_representation: &[u8], content: &[u8]) -> XR cmd.arg(STANDARD.encode(content)); let cmd_stdout = run_command_stdout(cmd)?; - - if is_success(&cmd_stdout)? { - let sign_result: SignResult = from_str(&cmd_stdout)?; - Ok(STANDARD.decode(&sign_result.signature_base64)?) - } else { - let error_result: ErrorResult = from_str(&cmd_stdout)?; - simple_error!("{}", error_result.error) - } + parse_sign_result(&cmd_stdout) } // ephemera_public_key MUST be DER format public key @@ -156,12 +149,51 @@ pub fn private_key_ecdh( cmd.arg(STANDARD.encode(ephemera_public_key)); let cmd_stdout = run_command_stdout(cmd)?; + parse_dh_result(&cmd_stdout) +} - if is_success(&cmd_stdout)? { - let dh_result: DhResult = from_str(&cmd_stdout)?; +pub fn external_sign(external_command: &str, parameter: &str, alg: &str, content: &[u8]) -> XResult> { + let mut cmd = Command::new(external_command); + cmd.arg("external_sign"); + cmd.arg("--parameter"); + cmd.arg(parameter); + cmd.arg("--alg"); + cmd.arg(alg); + cmd.arg("--message-base64"); + cmd.arg(STANDARD.encode(content)); + + let cmd_stdout = run_command_stdout(cmd)?; + parse_sign_result(&cmd_stdout) +} + +pub fn external_ecdh(external_command: &str, parameter: &str, ephemera_public_key: &[u8]) -> XResult> { + let mut cmd = Command::new(external_command); + cmd.arg("external_ecdh"); + cmd.arg("--parameter"); + cmd.arg(parameter); + cmd.arg("--epk"); + cmd.arg(STANDARD.encode(ephemera_public_key)); + + let cmd_stdout = run_command_stdout(cmd)?; + parse_dh_result(&cmd_stdout) +} + +fn parse_sign_result(stdout: &str) -> XResult> { + if is_success(stdout)? { + let sign_result: SignResult = from_str(stdout)?; + Ok(STANDARD.decode(&sign_result.signature_base64)?) + } else { + let error_result: ErrorResult = from_str(stdout)?; + simple_error!("{}", error_result.error) + } +} + +fn parse_dh_result(stdout: &str) -> XResult> { + if is_success(stdout)? { + let dh_result: DhResult = from_str(stdout)?; Ok(hex::decode(&dh_result.shared_secret_hex)?) } else { - let error_result: ErrorResult = from_str(&cmd_stdout)?; + let error_result: ErrorResult = from_str(stdout)?; simple_error!("{}", error_result.error) } } @@ -180,7 +212,9 @@ fn run_command(mut cmd: Command) -> XResult { Ok(output) => { debugging!("Output: {:?}", output); if !output.status.success() { - simple_error!("Run command not success: {:?}", output.status.code()) + let stderr = String::from_utf8_lossy(&output.stderr); + let stdout = String::from_utf8_lossy(&output.stdout); + simple_error!("Run command not success: {:?}\n - stdout: {}\n - stderr: {}", output.status.code(), stdout, stderr) } else { Ok(output) }