feat: v0.1.0 dev
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,3 +1,4 @@
|
|||||||
|
.idea/
|
||||||
# ---> Rust
|
# ---> Rust
|
||||||
# Generated by Cargo
|
# Generated by Cargo
|
||||||
# will have compiled files and executables
|
# will have compiled files and executables
|
||||||
|
|||||||
14
Cargo.toml
Normal file
14
Cargo.toml
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
[package]
|
||||||
|
name = "swift-secure-enclave-tool-rs"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2024"
|
||||||
|
authors = ["Hatter Jiang"]
|
||||||
|
repository = "https://git.hatter.ink/hatter/swift-secure-enclave-tool-rs"
|
||||||
|
description = "Swift secure enclave tool in Rust"
|
||||||
|
license = "MIT OR Apache-2.0"
|
||||||
|
keywords = ["crypto", "ecdsa", "ecdh", "secure-enclave"]
|
||||||
|
categories = ["cryptography"]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
base64 = "0.22.1"
|
||||||
|
rust_util = "0.6.47"
|
||||||
133
src/lib.rs
Normal file
133
src/lib.rs
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
use base64::engine::general_purpose::STANDARD;
|
||||||
|
use base64::Engine;
|
||||||
|
use rust_util::{debugging, opt_result, simple_error, XResult};
|
||||||
|
use std::process::{Command, Output};
|
||||||
|
|
||||||
|
const SWIFT_SECURE_ENCLAVE_TOOL_CMD: &str = "swift-secure-enclave-tool";
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub enum KeyPurpose {
|
||||||
|
Signing,
|
||||||
|
KeyAgreement,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct KeyMaterial {
|
||||||
|
pub public_key_point: Vec<u8>,
|
||||||
|
pub public_key_der: Vec<u8>,
|
||||||
|
pub private_key_representation: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn is_secure_enclave_supported() -> XResult<bool> {
|
||||||
|
let mut cmd = Command::new(SWIFT_SECURE_ENCLAVE_TOOL_CMD);
|
||||||
|
cmd.arg("is_support_secure_enclave");
|
||||||
|
|
||||||
|
let cmd_stdout = run_command_stdout(cmd)?;
|
||||||
|
if cmd_stdout.starts_with("ok:") {
|
||||||
|
let result = cmd_stdout.chars().skip(3).collect::<String>();
|
||||||
|
Ok(result == "true")
|
||||||
|
} else {
|
||||||
|
simple_error!("Invalid is_secure_enclave_supported result: {}", cmd_stdout)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn generate_ecdsa_keypair(key_purpose: KeyPurpose, require_bio: bool) -> XResult<KeyMaterial> {
|
||||||
|
let mut cmd = Command::new(SWIFT_SECURE_ENCLAVE_TOOL_CMD);
|
||||||
|
cmd.arg(match key_purpose {
|
||||||
|
KeyPurpose::Signing => "generate_p256_ecsign_keypair",
|
||||||
|
KeyPurpose::KeyAgreement => "generate_p256_ecdh_keypair",
|
||||||
|
});
|
||||||
|
cmd.arg(&format!("{}", require_bio));
|
||||||
|
|
||||||
|
let cmd_stdout = run_command_stdout(cmd)?;
|
||||||
|
parse_keypair_result(&cmd_stdout)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn recover_ecdsa_keypair(
|
||||||
|
key_purpose: KeyPurpose,
|
||||||
|
private_key_representation: &[u8],
|
||||||
|
) -> XResult<KeyMaterial> {
|
||||||
|
let mut cmd = Command::new(SWIFT_SECURE_ENCLAVE_TOOL_CMD);
|
||||||
|
cmd.arg(match key_purpose {
|
||||||
|
KeyPurpose::Signing => "recover_p256_ecsign_public_key",
|
||||||
|
KeyPurpose::KeyAgreement => "recover_p256_ecdh_public_key",
|
||||||
|
});
|
||||||
|
cmd.arg(&STANDARD.encode(private_key_representation));
|
||||||
|
|
||||||
|
let cmd_stdout = run_command_stdout(cmd)?;
|
||||||
|
parse_keypair_result(&cmd_stdout)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn private_key_ecdsa_sign(
|
||||||
|
private_key_representation: &[u8],
|
||||||
|
content: &[u8],
|
||||||
|
) -> XResult<Vec<u8>> {
|
||||||
|
let mut cmd = Command::new(SWIFT_SECURE_ENCLAVE_TOOL_CMD);
|
||||||
|
cmd.arg("compute_p256_ecsign");
|
||||||
|
cmd.arg(&STANDARD.encode(private_key_representation));
|
||||||
|
cmd.arg(&STANDARD.encode(content));
|
||||||
|
|
||||||
|
let cmd_stdout = run_command_stdout(cmd)?;
|
||||||
|
if cmd_stdout.starts_with("ok:") {
|
||||||
|
let result = cmd_stdout.chars().skip(3).collect::<String>();
|
||||||
|
Ok(STANDARD.decode(result)?)
|
||||||
|
} else {
|
||||||
|
simple_error!("Invalid private_key_ecdsa_sign result: {}", cmd_stdout)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn private_key_ecdh(
|
||||||
|
private_key_representation: &[u8],
|
||||||
|
ephemera_public_key: &[u8],
|
||||||
|
) -> XResult<Vec<u8>> {
|
||||||
|
let mut cmd = Command::new(SWIFT_SECURE_ENCLAVE_TOOL_CMD);
|
||||||
|
cmd.arg("compute_p256_ecdh");
|
||||||
|
cmd.arg(&STANDARD.encode(private_key_representation));
|
||||||
|
cmd.arg(&STANDARD.encode(ephemera_public_key));
|
||||||
|
|
||||||
|
let cmd_stdout = run_command_stdout(cmd)?;
|
||||||
|
if cmd_stdout.starts_with("ok:") {
|
||||||
|
let result = cmd_stdout.chars().skip(3).collect::<String>();
|
||||||
|
Ok(STANDARD.decode(result)?)
|
||||||
|
} else {
|
||||||
|
simple_error!("Invalid compute_p256_ecdh result: {}", cmd_stdout)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run_command_stdout(cmd: Command) -> XResult<String> {
|
||||||
|
let output = run_command(cmd)?;
|
||||||
|
let stdout_text = opt_result!(String::from_utf8(output.stdout), "Parse stdout failed:{}");
|
||||||
|
Ok(stdout_text)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn run_command(mut cmd: Command) -> XResult<Output> {
|
||||||
|
debugging!("Run command: {:?}", cmd);
|
||||||
|
let output = cmd.output();
|
||||||
|
match output {
|
||||||
|
Err(e) => simple_error!("Run command failed: {:?}", e),
|
||||||
|
Ok(output) => {
|
||||||
|
if !output.status.success() {
|
||||||
|
simple_error!("Run command not success: {:?}", output.status.code())
|
||||||
|
} else {
|
||||||
|
Ok(output)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_keypair_result(cmd_stdout: &str) -> XResult<KeyMaterial> {
|
||||||
|
if cmd_stdout.starts_with("ok:") {
|
||||||
|
let result = cmd_stdout.chars().skip(3).collect::<String>();
|
||||||
|
let parts = result.split(",").collect::<Vec<_>>();
|
||||||
|
let public_key_point = STANDARD.decode(&parts[0])?;
|
||||||
|
let public_key_der = STANDARD.decode(&parts[1])?;
|
||||||
|
let private_key_representation = STANDARD.decode(&parts[2])?;
|
||||||
|
Ok(KeyMaterial {
|
||||||
|
public_key_point,
|
||||||
|
public_key_der,
|
||||||
|
private_key_representation,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
simple_error!("Invalid result: {}", cmd_stdout)
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user