feat: v1.10.10, se-ecdh and se-ecsign

This commit is contained in:
2024-12-15 12:55:44 +08:00
parent 25b0efd272
commit df6e7eee55
10 changed files with 343 additions and 5 deletions

110
src/keyutil.rs Normal file
View File

@@ -0,0 +1,110 @@
use regex::Regex;
use rust_util::XResult;
// reference: https://git.hatter.ink/hatter/card-cli/issues/6
#[derive(Debug)]
pub enum KeyUri {
SecureEnclaveKey(SecureEnclaveKey),
}
#[derive(Debug, PartialEq, Eq)]
pub enum KeyModule {
SecureEnclave,
OpenPgpCard,
PersonalIdentityVerification,
}
impl KeyModule {
pub fn from(module: &str) -> Option<Self> {
match module {
"se" => Some(Self::SecureEnclave),
"pgp" => Some(Self::OpenPgpCard),
"piv" => Some(Self::PersonalIdentityVerification),
_ => None,
}
}
}
#[derive(Debug, PartialEq, Eq)]
pub enum KeyUsage {
Any,
Singing,
KeyAgreement,
}
impl KeyUsage {
pub fn from(usage: &str) -> Option<Self> {
match usage {
"signing" => Some(Self::Singing),
"key_agreement" => Some(Self::KeyAgreement),
"*" => Some(Self::Singing),
_ => None,
}
}
}
#[derive(Debug)]
pub struct SecureEnclaveKey {
pub host: String,
pub usage: KeyUsage,
pub private_key: String,
}
pub fn parse_key_uri(key_uri: &str) -> XResult<KeyUri> {
let regex = Regex::new(r##"^key://([a-zA-Z\-\._]*):(\w+)/(\w+):(\w+)?:(.*)$"##).unwrap();
let captures = match regex.captures(key_uri) {
None => return simple_error!("Invalid key uri: {}", key_uri),
Some(captures) => captures,
};
let host = captures.get(1).unwrap().as_str();
let module = captures.get(2).unwrap().as_str();
let algorithm = captures.get(3).unwrap().as_str();
let usage = captures.get(4).unwrap().as_str();
let left_part = captures.get(5).unwrap().as_str();
if "se" != module {
return simple_error!("Key uri's module must be se.");
}
if "p256" != algorithm {
return simple_error!("Key uri's algorithm must be p256.");
}
let key_usage = match KeyUsage::from(usage) {
None | Some(KeyUsage::Any) => {
return simple_error!("Key uri's usage must be signing or key_agreement.")
}
Some(key_usage) => key_usage,
};
Ok(KeyUri::SecureEnclaveKey(SecureEnclaveKey {
host: host.to_string(),
usage: key_usage,
private_key: left_part.to_string(),
}))
}
#[test]
fn test_parse_key_uri_01() {
let se_key_uri =
parse_key_uri("key://hatter-mac-pro:se/p256:signing:BASE64(dataRepresentation)").unwrap();
match se_key_uri {
KeyUri::SecureEnclaveKey(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);
}
}
}
#[test]
fn test_parse_key_uri_02() {
let se_key_uri =
parse_key_uri("key://hatter-mac-pro:se/p256:key_agreement:BASE64(dataRepresentation)")
.unwrap();
match se_key_uri {
KeyUri::SecureEnclaveKey(se_key_uri) => {
assert_eq!("hatter-mac-pro", se_key_uri.host);
assert_eq!(KeyUsage::KeyAgreement, se_key_uri.usage);
assert_eq!("BASE64(dataRepresentation)", se_key_uri.private_key);
}
}
}