feat: 1.13.15, make clippy happy

This commit is contained in:
2025-06-29 23:23:19 +08:00
parent d272904357
commit 6bd4d0ba57
16 changed files with 69 additions and 57 deletions

2
Cargo.lock generated
View File

@@ -519,7 +519,7 @@ dependencies = [
[[package]]
name = "card-cli"
version = "1.13.14"
version = "1.13.15"
dependencies = [
"aes-gcm-stream",
"authenticator 0.3.1",

View File

@@ -1,6 +1,6 @@
[package]
name = "card-cli"
version = "1.13.14"
version = "1.13.15"
authors = ["Hatter Jiang <jht5945@gmail.com>"]
edition = "2018"

View File

@@ -58,14 +58,14 @@ pub fn ecdh(
sub_arg_matches: &ArgMatches,
) -> XResult<Vec<u8>> {
match key_uri {
KeyUri::SecureEnclaveKey(key) => {
KeyUri::SecureEnclave(key) => {
if key.usage != KeyUsage::Singing {
return simple_error!("Not singing key");
}
let private_key = cmd_hmac_decrypt::try_decrypt(&mut None, &key.private_key)?;
seutil::secure_enclave_p256_dh(&private_key, ephemeral_public_key_bytes)
}
KeyUri::YubikeyPivKey(key) => {
KeyUri::YubikeyPiv(key) => {
let mut yk = yubikeyutil::open_yubikey_with_args(sub_arg_matches)?;
let pin_opt = pivutil::check_read_pin(&mut yk, key.slot, sub_arg_matches);
@@ -108,7 +108,7 @@ pub fn ecdh(
Ok(decrypted_shared_secret.to_vec())
}
KeyUri::YubikeyHmacEncSoftKey(key) => {
KeyUri::YubikeyHmacEncSoft(key) => {
if key.algorithm.is_ecc() {
let private_key = cmd_hmac_decrypt::try_decrypt(&mut None, &key.hmac_enc_private_key)?;
let private_key_bytes = try_decode(&private_key)?;
@@ -128,7 +128,7 @@ pub fn ecdh(
simple_error!("Invalid algorithm: {}", key.algorithm.to_str())
}
}
KeyUri::ExternalCommandKey(key) => {
KeyUri::ExternalCommand(key) => {
let parameter = cmd_hmac_decrypt::try_decrypt(&mut None, &key.parameter)?;
external_command_rs::external_ecdh(&key.external_command, &parameter, ephemeral_public_key_bytes)
}

View File

@@ -51,7 +51,7 @@ impl Command for CommandImpl {
fn fetch_public_key(parameter: &str, serial_opt: &Option<&str>) -> XResult<Vec<u8>> {
let key_uri = parse_key_uri(parameter)?;
match key_uri {
KeyUri::SecureEnclaveKey(key) => {
KeyUri::SecureEnclave(key) => {
if key.usage != KeyUsage::Singing {
simple_error!("Not singing key")
} else {
@@ -61,7 +61,7 @@ fn fetch_public_key(parameter: &str, serial_opt: &Option<&str>) -> XResult<Vec<u
Ok(public_key_der)
}
}
KeyUri::YubikeyPivKey(key) => {
KeyUri::YubikeyPiv(key) => {
let mut yk = yubikeyutil::open_yubikey_with_serial(serial_opt)?;
if let Some(key) = find_key_or_error(&mut yk, &key.slot)? {
let cert_der = key.certificate().cert.to_der()?;
@@ -71,7 +71,7 @@ fn fetch_public_key(parameter: &str, serial_opt: &Option<&str>) -> XResult<Vec<u
}
simple_error!("Slot {} not found", key.slot)
}
KeyUri::YubikeyHmacEncSoftKey(key) => {
KeyUri::YubikeyHmacEncSoft(key) => {
if key.algorithm.is_ecc() {
let private_key = cmd_hmac_decrypt::try_decrypt(&mut None, &key.hmac_enc_private_key)?;
let p256_public_key = ecdsautil::parse_p256_private_key_to_public_key(&private_key).ok();
@@ -98,7 +98,7 @@ fn fetch_public_key(parameter: &str, serial_opt: &Option<&str>) -> XResult<Vec<u
simple_error!("Invalid algorithm: {}", key.algorithm.to_str())
}
}
KeyUri::ExternalCommandKey(key) => {
KeyUri::ExternalCommand(key) => {
let parameter = cmd_hmac_decrypt::try_decrypt(&mut None, &key.parameter)?;
external_command_rs::external_public_key(&key.external_command, &parameter)
}

View File

@@ -58,7 +58,7 @@ impl Command for CommandImpl {
pub fn sign(alg: &str, message: &[u8], key_uri: KeyUri, sub_arg_matches: &ArgMatches) -> XResult<Vec<u8>> {
match key_uri {
KeyUri::SecureEnclaveKey(key) => {
KeyUri::SecureEnclave(key) => {
if "ES256" != alg {
return simple_error!("Invalid alg: {}", alg);
}
@@ -68,7 +68,7 @@ pub fn sign(alg: &str, message: &[u8], key_uri: KeyUri, sub_arg_matches: &ArgMat
let private_key = cmd_hmac_decrypt::try_decrypt(&mut None, &key.private_key)?;
seutil::secure_enclave_p256_sign(&private_key, message)
}
KeyUri::YubikeyPivKey(key) => {
KeyUri::YubikeyPiv(key) => {
let mut yk = yubikeyutil::open_yubikey_with_args(sub_arg_matches)?;
let pin_opt = pivutil::check_read_pin(&mut yk, key.slot, sub_arg_matches);
@@ -94,7 +94,7 @@ pub fn sign(alg: &str, message: &[u8], key_uri: KeyUri, sub_arg_matches: &ArgMat
);
Ok(signed_data.to_vec())
}
KeyUri::YubikeyHmacEncSoftKey(key) => {
KeyUri::YubikeyHmacEncSoft(key) => {
if key.algorithm.is_ecc() {
let private_key = cmd_hmac_decrypt::try_decrypt(&mut None, &key.hmac_enc_private_key)?;
let (jwt_algorithm, private_key_d) = parse_ecdsa_private_key(&private_key)?;
@@ -122,9 +122,9 @@ pub fn sign(alg: &str, message: &[u8], key_uri: KeyUri, sub_arg_matches: &ArgMat
simple_error!("Invalid algorithm: {}", key.algorithm.to_str())
}
}
KeyUri::ExternalCommandKey(key) => {
KeyUri::ExternalCommand(key) => {
let parameter = cmd_hmac_decrypt::try_decrypt(&mut None, &key.parameter)?;
let alg = key.algorithm.to_jwa_name();
let alg = key.algorithm.as_jwa_name();
let signature = external_command_rs::external_sign(&key.external_command, &parameter, alg, message)?;
Ok(signature)
}

View File

@@ -54,7 +54,7 @@ pub fn try_decrypt_with_pbe_option(pin_opt: &mut Option<String>, ciphertext: &st
if is_hmac_encrypted(ciphertext) {
hmac_decrypt(pin_opt, ciphertext, auto_pbe)
} else if pbeutil::is_simple_pbe_encrypted(ciphertext) {
pbeutil::simple_pbe_decrypt_with_prompt_to_string(pin_opt,&ciphertext)
pbeutil::simple_pbe_decrypt_with_prompt_to_string(pin_opt, ciphertext)
} else {
Ok(ciphertext.to_string())
}

View File

@@ -69,7 +69,7 @@ pub fn do_encrypt(text: &str, password_opt: &mut Option<String>, sub_arg_matches
let double_pin_check = sub_arg_matches.is_present("double-pin-check");
let iteration = sub_arg_matches.value_of("pbe-iteration")
.map(|x| x.parse::<u32>().unwrap()).unwrap_or(100000);
pbeutil::simple_pbe_encrypt_with_prompt_from_string(iteration, &text, password_opt, double_pin_check)?
pbeutil::simple_pbe_encrypt_with_prompt_from_string(iteration, text, password_opt, double_pin_check)?
} else {
text.to_string()
};

View File

@@ -108,7 +108,7 @@ impl Command for CommandImpl {
algorithm: algorithm_id,
hmac_enc_private_key: pkcs8_base64.clone(),
};
Some(KeyUri::YubikeyHmacEncSoftKey(yubikey_hmac_enc_soft_key).to_string())
Some(KeyUri::YubikeyHmacEncSoft(yubikey_hmac_enc_soft_key).to_string())
} else {
None
};

View File

@@ -109,7 +109,7 @@ impl Command for CommandImpl {
algorithm: KeyAlgorithmId::from_algorithm_id(algorithm_id),
slot: slot_id,
};
json.insert("key_uri", KeyUri::YubikeyPivKey(yubikey_piv_key).to_string());
json.insert("key_uri", KeyUri::YubikeyPiv(yubikey_piv_key).to_string());
}
let serial_lower = cert.serial_number.to_string().to_lowercase();
json.insert("serial", if serial_lower.starts_with("00:") { serial_lower.chars().skip(3).collect() } else { serial_lower });

View File

@@ -19,7 +19,7 @@ impl Command for CommandImpl {
fn run(&self, _arg_matches: &ArgMatches, sub_arg_matches: &ArgMatches) -> CommandError {
let json_output = cmdutil::check_json_output(sub_arg_matches);
if let Err(_) = which::which("swift-secure-enclave-tool") {
if which::which("swift-secure-enclave-tool").is_err() {
failure!("Secure Enclave tool not found.");
}

View File

@@ -31,7 +31,7 @@ impl Command for CommandImpl {
let key = sub_arg_matches.value_of("key").unwrap();
let epk = sub_arg_matches.value_of("epk").unwrap();
let key_uri = parse_key_uri(&key)?;
let key_uri = parse_key_uri(key)?;
let se_key_uri = key_uri.as_secure_enclave_key()?;
debugging!("Secure enclave key URI: {:?}", se_key_uri);
@@ -76,7 +76,7 @@ pub fn parse_epk(epk: &str) -> XResult<Vec<u8>> {
} else {
match hex::decode(epk) {
Ok(epk_bytes) => Ok(epk_bytes),
Err(e) => match base64_decode(&epk) {
Err(e) => match base64_decode(epk) {
Ok(epk_bytes) => Ok(epk_bytes),
Err(_) => simple_error!("Decode public key from hex failed: {}", e)
}

View File

@@ -45,7 +45,7 @@ impl Command for CommandImpl {
Some(input) => input.as_bytes().to_vec(),
};
let key_uri = parse_key_uri(&key)?;
let key_uri = parse_key_uri(key)?;
let se_key_uri = key_uri.as_secure_enclave_key()?;
debugging!("Secure enclave key URI: {:?}", se_key_uri);

View File

@@ -23,7 +23,7 @@ impl Command for CommandImpl {
seutil::check_se_supported()?;
let key = sub_arg_matches.value_of("key").unwrap();
let key_uri = parse_key_uri(&key)?;
let key_uri = parse_key_uri(key)?;
let se_key_uri = key_uri.as_secure_enclave_key()?;
debugging!("Secure enclave key URI: {:?}", se_key_uri);
@@ -34,7 +34,7 @@ impl Command for CommandImpl {
se_key_uri.usage == KeyUsage::Singing,
)?;
print_se_key(json_output, &public_key_point, &public_key_der, &key);
print_se_key(json_output, &public_key_point, &public_key_der, key);
Ok(None)
}

View File

@@ -8,26 +8,26 @@ use yubikey::piv::{AlgorithmId, SlotId};
// reference: https://git.hatter.ink/hatter/card-cli/issues/6
#[derive(Debug)]
pub enum KeyUri {
SecureEnclaveKey(SecureEnclaveKey),
YubikeyPivKey(YubikeyPivKey),
YubikeyHmacEncSoftKey(YubikeyHmacEncSoftKey),
ExternalCommandKey(ExternalCommandKey),
SecureEnclave(SecureEnclaveKey),
YubikeyPiv(YubikeyPivKey),
YubikeyHmacEncSoft(YubikeyHmacEncSoftKey),
ExternalCommand(ExternalCommandKey),
}
impl KeyUri {
pub fn as_secure_enclave_key(&self) -> XResult<&SecureEnclaveKey> {
match self {
KeyUri::SecureEnclaveKey(key) => Ok(key),
KeyUri::SecureEnclave(key) => Ok(key),
_ => simple_error!("Not a secure enclave key."),
}
}
pub fn get_preferred_algorithm_type(&self) -> AlgorithmType {
let algorithm_id = match &self {
KeyUri::SecureEnclaveKey(_) => return AlgorithmType::Es256,
KeyUri::YubikeyPivKey(key) => key.algorithm,
KeyUri::YubikeyHmacEncSoftKey(key) => key.algorithm,
KeyUri::ExternalCommandKey(key) => key.algorithm,
KeyUri::SecureEnclave(_) => return AlgorithmType::Es256,
KeyUri::YubikeyPiv(key) => key.algorithm,
KeyUri::YubikeyHmacEncSoft(key) => key.algorithm,
KeyUri::ExternalCommand(key) => key.algorithm,
};
match algorithm_id {
KeyAlgorithmId::Rsa1024
@@ -41,6 +41,7 @@ impl KeyUri {
}
}
#[allow(clippy::to_string_trait_impl)]
impl ToString for KeyUri {
fn to_string(&self) -> String {
let mut key_uri = String::with_capacity(64);
@@ -48,15 +49,15 @@ impl ToString for KeyUri {
match self {
// key://hatter-mac-pro:se/p256:signing:BASE64(dataRepresentation)
// key://hatter-mac-pro:se/p256:key_agreement:BASE64(dataRepresentation)
KeyUri::SecureEnclaveKey(key) => {
KeyUri::SecureEnclave(key) => {
key_uri.push_str(&key.host);
key_uri.push_str(":se/p256:");
key_uri.push_str(&key.usage.to_string());
key_uri.push_str(":");
key_uri.push(':');
key_uri.push_str(&key.private_key);
}
// key://yubikey-5n:piv/p256::9a
KeyUri::YubikeyPivKey(key) => {
KeyUri::YubikeyPiv(key) => {
key_uri.push_str(&key.key_name);
key_uri.push_str(":piv/");
key_uri.push_str(key.algorithm.to_str());
@@ -64,7 +65,7 @@ impl ToString for KeyUri {
key_uri.push_str(key.slot.to_str());
}
// key://-:soft/p256::hmac_enc:...
KeyUri::YubikeyHmacEncSoftKey(key) => {
KeyUri::YubikeyHmacEncSoft(key) => {
key_uri.push_str(&key.key_name);
key_uri.push_str(":soft/");
key_uri.push_str(key.algorithm.to_str());
@@ -72,7 +73,7 @@ impl ToString for KeyUri {
key_uri.push_str(key.hmac_enc_private_key.as_str());
}
// key://external-command-file-name:external_command/p256::parameter
KeyUri::ExternalCommandKey(key) => {
KeyUri::ExternalCommand(key) => {
let encoded_external_command =
percent_encoding::utf8_percent_encode(&key.external_command, NON_ALPHANUMERIC)
.to_string();
@@ -140,7 +141,7 @@ impl KeyAlgorithmId {
}
}
pub fn to_jwa_name(&self) -> &str {
pub fn as_jwa_name(&self) -> &str {
match self {
KeyAlgorithmId::Rsa1024
| KeyAlgorithmId::Rsa2048
@@ -203,6 +204,7 @@ impl KeyUsage {
}
}
#[allow(clippy::to_string_trait_impl)]
impl ToString for KeyUsage {
fn to_string(&self) -> String {
match self {
@@ -269,7 +271,7 @@ pub fn parse_key_uri(key_uri: &str) -> XResult<KeyUri> {
}
Some(key_usage) => key_usage,
};
let parsed_key_uri = KeyUri::SecureEnclaveKey(SecureEnclaveKey {
let parsed_key_uri = KeyUri::SecureEnclave(SecureEnclaveKey {
host: host_or_name.to_string(),
usage: key_usage,
private_key: left_part.to_string(),
@@ -278,7 +280,7 @@ pub fn parse_key_uri(key_uri: &str) -> XResult<KeyUri> {
Ok(parsed_key_uri)
}
"piv" => {
if "" != usage {
if !usage.is_empty() {
return simple_error!("Key uri's usage must be empty.");
}
let algorithm = opt_value_result!(
@@ -291,7 +293,7 @@ pub fn parse_key_uri(key_uri: &str) -> XResult<KeyUri> {
"Invalid slot id: {}",
left_part
);
let parsed_key_uri = KeyUri::YubikeyPivKey(YubikeyPivKey {
let parsed_key_uri = KeyUri::YubikeyPiv(YubikeyPivKey {
key_name: host_or_name.to_string(),
algorithm,
slot,
@@ -300,7 +302,7 @@ pub fn parse_key_uri(key_uri: &str) -> XResult<KeyUri> {
Ok(parsed_key_uri)
}
"soft" => {
if "" != usage {
if !usage.is_empty() {
return simple_error!("Key uri's usage must be empty.");
}
let algorithm = opt_value_result!(
@@ -309,7 +311,7 @@ pub fn parse_key_uri(key_uri: &str) -> XResult<KeyUri> {
algorithm
);
let hmac_enc_private_key = left_part.to_string();
let parsed_key_uri = KeyUri::YubikeyHmacEncSoftKey(YubikeyHmacEncSoftKey {
let parsed_key_uri = KeyUri::YubikeyHmacEncSoft(YubikeyHmacEncSoftKey {
key_name: host_or_name.to_string(),
algorithm,
hmac_enc_private_key,
@@ -318,7 +320,7 @@ pub fn parse_key_uri(key_uri: &str) -> XResult<KeyUri> {
Ok(parsed_key_uri)
}
"external_command" => {
if "" != usage {
if !usage.is_empty() {
return simple_error!("Key uri's usage must be empty.");
}
let external_command = opt_result!(
@@ -331,7 +333,7 @@ pub fn parse_key_uri(key_uri: &str) -> XResult<KeyUri> {
algorithm
);
let parameter = left_part.to_string();
let parsed_key_uri = KeyUri::ExternalCommandKey(ExternalCommandKey {
let parsed_key_uri = KeyUri::ExternalCommand(ExternalCommandKey {
external_command: external_command.to_string(),
algorithm,
parameter,
@@ -352,7 +354,7 @@ fn test_parse_key_uri_01() {
se_key_uri.to_string()
);
match se_key_uri {
KeyUri::SecureEnclaveKey(se_key_uri) => {
KeyUri::SecureEnclave(se_key_uri) => {
assert_eq!("hatter-mac-pro", se_key_uri.host);
assert_eq!(KeyUsage::Singing, se_key_uri.usage);
assert_eq!("BASE64(dataRepresentation)", se_key_uri.private_key);
@@ -373,7 +375,7 @@ fn test_parse_key_uri_02() {
se_key_uri.to_string()
);
match se_key_uri {
KeyUri::SecureEnclaveKey(se_key_uri) => {
KeyUri::SecureEnclave(se_key_uri) => {
assert_eq!("hatter-mac-m1", se_key_uri.host);
assert_eq!(KeyUsage::KeyAgreement, se_key_uri.usage);
assert_eq!("BASE64(dataRepresentation)", se_key_uri.private_key);
@@ -392,7 +394,7 @@ fn test_parse_key_uri_03() {
se_key_uri.to_string()
);
match se_key_uri {
KeyUri::YubikeyPivKey(piv_key_uri) => {
KeyUri::YubikeyPiv(piv_key_uri) => {
assert_eq!("yubikey-5n", piv_key_uri.key_name);
assert_eq!(KeyAlgorithmId::EccP256, piv_key_uri.algorithm);
assert_eq!(SlotId::Authentication, piv_key_uri.slot);

View File

@@ -94,16 +94,26 @@ pub fn is_simple_pbe_encrypted(ciphertext: &str) -> bool {
fn simple_pbe_kdf(password: &str, pbe_salt: &[u8], iteration: u32) -> XResult<[u8; 32]> {
let mut init_data = password.as_bytes().to_vec();
init_data.extend_from_slice(&pbe_salt);
init_data.extend_from_slice(pbe_salt);
let mut loop_hash = sha256_bytes(&init_data);
for i in 0..iteration {
let i_to_bytes = i.to_be_bytes();
for x in 0..4 {
loop_hash[x] = i_to_bytes[x];
}
loop_hash[..4].copy_from_slice(&i_to_bytes);
loop_hash = sha256_bytes(&loop_hash);
}
let key = copy_sha256(&sha256_bytes(&loop_hash))?;
Ok(key)
}
#[test]
fn test_simple_pbe_kdf() {
assert_eq!("cea7eb6424132aa4d6b1880c3cb570df17c41d766826e144088fd16b334c80c5",
hex::encode(simple_pbe_kdf("hello_world", b"salt", 1).unwrap()));
assert_eq!("e3ed4a0a2f451180cfa4a0f8f3e1181d8863fc192d161e4c1480e3612135ca27",
hex::encode(simple_pbe_kdf("hello_world", b"salt", 2).unwrap()));
assert_eq!("e552900ad3f14a96629c8056bd7bc4b2431250ef4a47e78856626f45807cd87e",
hex::encode(simple_pbe_kdf("hello_world 2", b"salt", 2).unwrap()));
assert_eq!("37e71484f00033c99db444c77553364b31614d5145e38aad5bd5caa6676d40f9",
hex::encode(simple_pbe_kdf("hello_world", b"salt 2", 2).unwrap()));
}

View File

@@ -36,15 +36,15 @@ impl RsaSignAlgorithm {
pub fn sign(rsa_private_key: &RsaPrivateKey, rsa_sign_algorithm: RsaSignAlgorithm, message: &[u8]) -> XResult<Vec<u8>> {
match rsa_sign_algorithm {
RsaSignAlgorithm::Rs256 => {
let raw_in = digestutil::sha256_bytes(&message);
let raw_in = digestutil::sha256_bytes(message);
Ok(rsa_private_key.sign(Pkcs1v15Sign::new::<Sha256>(), &raw_in)?)
}
RsaSignAlgorithm::Rs384 => {
let raw_in = digestutil::sha384_bytes(&message);
let raw_in = digestutil::sha384_bytes(message);
Ok(rsa_private_key.sign(Pkcs1v15Sign::new::<Sha384>(), &raw_in)?)
}
RsaSignAlgorithm::Rs512 => {
let raw_in = digestutil::sha512_bytes(&message);
let raw_in = digestutil::sha512_bytes(message);
Ok(rsa_private_key.sign(Pkcs1v15Sign::new::<Sha512>(), &raw_in)?)
}
}