feat: v1.11.0, remove swiftc dependency

This commit is contained in:
2025-03-24 00:05:30 +08:00
parent ea0b091414
commit 8b6056db34
35 changed files with 63 additions and 2715 deletions

View File

@@ -1,11 +1,7 @@
use crate::ecdsautil;
use crate::keyutil::{parse_key_uri, KeyUri};
use clap::{App, Arg, ArgMatches, SubCommand};
use p256::elliptic_curve::sec1::FromEncodedPoint;
use p256::{EncodedPoint, PublicKey};
use rust_util::util_clap::{Command, CommandError};
use rust_util::util_msg;
use spki::EncodePublicKey;
use std::collections::BTreeMap;
pub struct CommandImpl;

View File

@@ -31,7 +31,7 @@ impl Command for CommandImpl {
}
let ciphertext = sub_arg_matches.value_of("ciphertext").unwrap();
let plaintext = hmacutil::hmac_decrypt_to_string(&ciphertext)?;
let plaintext = hmacutil::hmac_decrypt_to_string(ciphertext)?;
if json_output {
let mut json = BTreeMap::<&'_ str, String>::new();

View File

@@ -8,8 +8,6 @@ use rust_util::util_msg;
use crate::ecdsautil::parse_ecdsa_r_and_s;
use crate::util::try_decode;
const SEPARATOR: &str = ".";
pub struct CommandImpl;
impl Command for CommandImpl {

View File

@@ -50,8 +50,7 @@ impl Command for CommandImpl {
let KeyUri::SecureEnclaveKey(se_key_uri) = parse_key_uri(key)?;
debugging!("Secure enclave key URI: {:?}", se_key_uri);
let ephemeral_public_key_der_bytes;
if epk.starts_with("04") {
let ephemeral_public_key_der_bytes = if epk.starts_with("04") {
let ephemeral_public_key_point_bytes = opt_result!(
hex::decode(epk),
"Decode public key point from hex failed: {}"
@@ -65,11 +64,10 @@ impl Command for CommandImpl {
return simple_error!("Parse public key failed.");
}
let public_key = public_key_opt.unwrap();
ephemeral_public_key_der_bytes = public_key.to_public_key_der()?.as_bytes().to_vec();
public_key.to_public_key_der()?.as_bytes().to_vec()
} else {
ephemeral_public_key_der_bytes =
opt_result!(hex::decode(epk), "Decode public key from hex failed: {}");
}
opt_result!(hex::decode(epk), "Decode public key from hex failed: {}")
};
let dh = seutil::secure_enclave_p256_dh(
&se_key_uri.private_key,

View File

@@ -7,11 +7,8 @@ use jwt::{AlgorithmType, Header, ToBase64};
use rust_util::util_clap::{Command, CommandError};
use rust_util::{util_msg, util_time, XResult};
use serde_json::{Map, Number, Value};
use yubikey::piv::{sign_data, AlgorithmId, SlotId};
use yubikey::{Certificate, YubiKey};
use crate::ecdsautil::parse_ecdsa_to_rs;
use crate::{cmd_signjwt, digest, ecdsautil, hmacutil, pivutil, rsautil, util};
use crate::{cmd_signjwt, digest, ecdsautil, hmacutil, rsautil, util};
const SEPARATOR: &str = ".";

View File

@@ -22,8 +22,8 @@ pub fn parse_ecdsa_to_rs(signature_der: &[u8]) -> XResult<Vec<u8>> {
}
pub fn parse_ecdsa_r_and_s(signature_der: &[u8]) -> XResult<(Vec<u8>, Vec<u8>)> {
let mut vec_r: Vec<u8> = Vec::new();
let mut vec_s: Vec<u8> = Vec::new();
let vec_r: Vec<u8>;
let vec_s: Vec<u8>;
let (_, parsed_signature) = opt_result!(der_parser::parse_der(signature_der), "Parse signature failed: {}");
match parsed_signature.content {
BerObjectContent::Sequence(seq) => {
@@ -73,7 +73,6 @@ pub fn generate_p384_keypair() -> XResult<(String, String, String)> {
macro_rules! parse_ecdsa_private_key {
($algo: tt, $parse_ecdsa_private_key: tt) => ({
use $algo::ecdsa::{SigningKey};
use $algo::pkcs8::DecodePrivateKey;
use $algo::SecretKey;
@@ -103,7 +102,7 @@ pub fn sign_p256_rs(private_key_d: &[u8], pre_hash: &[u8]) -> XResult<Vec<u8>> {
use p256::ecdsa::{SigningKey, Signature};
use p256::ecdsa::signature::hazmat::PrehashSigner;
let signing_key = SigningKey::from_slice(&private_key_d)?;
let signing_key = SigningKey::from_slice(private_key_d)?;
let signature: Signature = signing_key.sign_prehash(pre_hash)?;
Ok(signature.to_bytes().to_vec())
@@ -113,7 +112,7 @@ pub fn sign_p384_rs(private_key_d: &[u8], pre_hash: &[u8]) -> XResult<Vec<u8>> {
use p384::ecdsa::{SigningKey, Signature};
use p384::ecdsa::signature::hazmat::PrehashSigner;
let signing_key = SigningKey::from_slice(&private_key_d)?;
let signing_key = SigningKey::from_slice(private_key_d)?;
let signature: Signature = signing_key.sign_prehash(pre_hash)?;
Ok(signature.to_bytes().to_vec())

View File

@@ -8,7 +8,7 @@ use yubico_manager::config::{Config, Mode, Slot};
use yubico_manager::hmacmode::HmacKey;
use yubico_manager::sec::hmac_sha1;
use yubico_manager::Yubico;
use crate::digest::{copy_sha256, sha256, sha256_bytes};
use crate::digest::{copy_sha256, sha256_bytes};
use crate::util::{base64_decode, base64_encode};
const HMAC_ENC_PREFIX: &str = "hmac_enc:";
@@ -33,8 +33,8 @@ pub fn hmac_encrypt(plaintext: &[u8]) -> XResult<String> {
Ok(format!("{}{}:{}:{}",
HMAC_ENC_PREFIX,
hex::encode(&hmac_nonce),
hex::encode(&aes_gcm_nonce),
hex::encode(hmac_nonce),
hex::encode(aes_gcm_nonce),
base64_encode(&ciphertext)
))
}
@@ -92,7 +92,7 @@ pub fn compute_yubikey_hmac(challenge_bytes: &[u8]) -> XResult<Vec<u8>> {
.set_mode(Mode::Sha1)
.set_slot(Slot::Slot2);
let hmac_result = opt_result!(yubi.challenge_response_hmac(&challenge_bytes, config), "Challenge HMAC failed: {}");
let hmac_result = opt_result!(yubi.challenge_response_hmac(challenge_bytes, config), "Challenge HMAC failed: {}");
Ok(hmac_result.deref().to_vec())
}

View File

@@ -33,15 +33,10 @@ mod cmd_pivverify;
mod cmd_rsadecrypt;
mod cmd_rsaencrypt;
mod cmd_rsaverify;
#[cfg(feature = "with-secure-enclave")]
mod cmd_se;
#[cfg(feature = "with-secure-enclave")]
mod cmd_se_ecdh;
#[cfg(feature = "with-secure-enclave")]
mod cmd_se_ecsign;
#[cfg(feature = "with-secure-enclave")]
mod cmd_se_generate;
#[cfg(feature = "with-secure-enclave")]
mod cmd_se_recover;
mod cmd_signfile;
mod cmd_signjwt;
@@ -68,7 +63,6 @@ mod pinutil;
mod pivutil;
mod pkiutil;
mod rsautil;
#[cfg(feature = "with-secure-enclave")]
mod seutil;
mod signfile;
mod sshutil;
@@ -139,15 +133,10 @@ fn inner_main() -> CommandError {
Box::new(cmd_signjwtsoft::CommandImpl),
Box::new(cmd_signfile::CommandImpl),
Box::new(cmd_verifyfile::CommandImpl),
#[cfg(feature = "with-secure-enclave")]
Box::new(cmd_se::CommandImpl),
#[cfg(feature = "with-secure-enclave")]
Box::new(cmd_se_generate::CommandImpl),
#[cfg(feature = "with-secure-enclave")]
Box::new(cmd_se_recover::CommandImpl),
#[cfg(feature = "with-secure-enclave")]
Box::new(cmd_se_ecsign::CommandImpl),
#[cfg(feature = "with-secure-enclave")]
Box::new(cmd_se_ecdh::CommandImpl),
Box::new(cmd_ecverify::CommandImpl),
Box::new(cmd_parseecdsasignature::CommandImpl),
@@ -159,8 +148,6 @@ fn inner_main() -> CommandError {
let mut features: Vec<&str> = vec![];
#[cfg(feature = "with-sequoia-openpgp")]
features.push("sequoia-openpgp");
#[cfg(feature = "with-secure-enclave")]
features.push("secure-enclave");
features
};
let about = format!(

View File

@@ -1,113 +1,63 @@
use crate::util::{base64_decode, base64_encode};
use base64::engine::general_purpose::STANDARD;
use base64::Engine;
use rust_util::XResult;
use swift_rs::swift;
use swift_rs::{Bool, SRString};
swift!(fn is_support_secure_enclave() -> Bool);
swift!(fn generate_secure_enclave_p256_ecdh_keypair() -> SRString);
swift!(fn generate_secure_enclave_p256_ecsign_keypair() -> SRString);
swift!(fn compute_secure_enclave_p256_ecdh(private_key_base64: SRString, ephemera_public_key_base64: SRString) -> SRString);
swift!(fn compute_secure_enclave_p256_ecsign(private_key_base64: SRString, content: SRString) -> SRString);
swift!(fn recover_secure_enclave_p256_ecsign_public_key(private_key_base64: SRString) -> SRString);
swift!(fn recover_secure_enclave_p256_ecdh_public_key(private_key_base64: SRString) -> SRString);
use swift_secure_enclave_tool_rs::KeyPurpose;
pub fn is_support_se() -> bool {
unsafe { is_support_secure_enclave() }
swift_secure_enclave_tool_rs::is_secure_enclave_supported().unwrap_or(false)
}
pub fn generate_secure_enclave_p256_keypair(sign: bool) -> XResult<(Vec<u8>, Vec<u8>, String)> {
let p256_keypair_result = if sign {
unsafe { generate_secure_enclave_p256_ecsign_keypair() }
let key_material = if sign {
swift_secure_enclave_tool_rs::generate_ecdsa_keypair(KeyPurpose::Signing, true)?
} else {
unsafe { generate_secure_enclave_p256_ecdh_keypair() }
swift_secure_enclave_tool_rs::generate_ecdsa_keypair(KeyPurpose::KeyAgreement, true)?
};
parse_p256_keypair_result(p256_keypair_result.as_str())
Ok((
key_material.public_key_point,
key_material.public_key_der,
STANDARD.encode(&key_material.private_key_representation),
))
}
pub fn recover_secure_enclave_p256_public_key(
private_key: &str,
sign: bool,
) -> XResult<(Vec<u8>, Vec<u8>, String)> {
let p256_keypair_result = if sign {
unsafe { recover_secure_enclave_p256_ecsign_public_key(SRString::from(private_key)) }
let private_key_representation = STANDARD.decode(private_key)?;
let key_material = if sign {
swift_secure_enclave_tool_rs::recover_ecdsa_keypair(
KeyPurpose::Signing,
&private_key_representation,
)
} else {
unsafe { recover_secure_enclave_p256_ecdh_public_key(SRString::from(private_key)) }
};
parse_p256_keypair_result(p256_keypair_result.as_str())
swift_secure_enclave_tool_rs::recover_ecdsa_keypair(
KeyPurpose::KeyAgreement,
&private_key_representation,
)
}?;
Ok((
key_material.public_key_point,
key_material.public_key_der,
STANDARD.encode(&key_material.private_key_representation),
))
}
pub fn secure_enclave_p256_dh(
private_key: &str,
ephemeral_public_key_bytes: &[u8],
) -> XResult<Vec<u8>> {
let dh_result = unsafe {
compute_secure_enclave_p256_ecdh(
SRString::from(private_key),
SRString::from(base64_encode(ephemeral_public_key_bytes).as_str()),
)
};
let dh_result_str = dh_result.as_str();
debugging!("DH result: {}", &dh_result_str);
if !dh_result_str.starts_with("ok:SharedSecret:") {
return simple_error!("ECDH P256 in secure enclave failed: {}", dh_result_str);
}
let shared_secret_hex = dh_result_str
.chars()
.skip("ok:SharedSecret:".len())
.collect::<String>();
let shared_secret_hex = shared_secret_hex.trim();
Ok(opt_result!(
hex::decode(shared_secret_hex),
"Decrypt shared secret hex: {}, failed: {}",
shared_secret_hex
))
let private_key_representation = STANDARD.decode(private_key)?;
let shared_secret = swift_secure_enclave_tool_rs::private_key_ecdh(
&private_key_representation,
ephemeral_public_key_bytes,
)?;
Ok(shared_secret)
}
pub fn secure_enclave_p256_sign(private_key: &str, content: &[u8]) -> XResult<Vec<u8>> {
let signature_result = unsafe {
compute_secure_enclave_p256_ecsign(
SRString::from(private_key),
SRString::from(base64_encode(content).as_str()),
)
};
let signature_result_str = signature_result.as_str();
debugging!("Signature result: {}", &signature_result_str);
if !signature_result_str.starts_with("ok:") {
return simple_error!(
"Sign P256 in secure enclave failed: {}",
signature_result_str
);
}
let signature = signature_result_str.chars().skip(3).collect::<String>();
debugging!("Signature: {}", &signature);
Ok(base64_decode(&signature)?)
}
fn parse_p256_keypair_result(p256_keypair_result_str: &str) -> XResult<(Vec<u8>, Vec<u8>, String)> {
if !p256_keypair_result_str.starts_with("ok:") {
return simple_error!(
"Generate P256 in secure enclave failed: {}",
p256_keypair_result_str
);
}
let public_key_and_private_key = p256_keypair_result_str.chars().skip(3).collect::<String>();
let public_key_and_private_keys = public_key_and_private_key.split(',').collect::<Vec<_>>();
if public_key_and_private_keys.len() != 3 {
return simple_error!(
"Generate P256 in secure enclave result is bad: {}",
public_key_and_private_key
);
}
let public_key_point = opt_result!(
base64_decode(public_key_and_private_keys[0]),
"Public key point is not base64 encoded: {}"
);
let public_key_der = opt_result!(
base64_decode(public_key_and_private_keys[1]),
"Public key der is not base64 encoded: {}"
);
let private_key = public_key_and_private_keys[2].to_string();
Ok((public_key_point, public_key_der, private_key))
let private_key_representation = STANDARD.decode(private_key)?;
let signature =
swift_secure_enclave_tool_rs::private_key_ecdsa_sign(&private_key_representation, content)?;
Ok(signature)
}