diff --git a/Cargo.toml b/Cargo.toml index 85d3ad2..875d87c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -63,7 +63,7 @@ which = "7.0.3" percent-encoding = "2.3.1" external-command-rs = "0.1.1" ssh-agent-lib = { version = "0.5.1" } -ssh-key = { version = "0.6", features = ["ecdsa"] } +ssh-key = { version = "0.6", features = ["ecdsa", "alloc"] } tokio = "1.45.1" ssh-encoding = { version = "0.2.0", features = ["alloc"] } #lazy_static = "1.4.0" diff --git a/src/cmd_ssh_agent.rs b/src/cmd_ssh_agent.rs index 0244e70..f3106ea 100644 --- a/src/cmd_ssh_agent.rs +++ b/src/cmd_ssh_agent.rs @@ -1,19 +1,24 @@ use std::fs::remove_file; use std::path::PathBuf; -use clap::{App, Arg, ArgMatches, SubCommand}; - -use crate::ecdsautil::{generate_ecdsa_keypair, parse_ecdsa_r_and_s, EcdsaAlgorithm}; +use crate::ecdsautil::{ + generate_ecdsa_keypair, parse_ec_public_key_to_point, parse_ecdsa_r_and_s, EcdsaAlgorithm, +}; use crate::util::base64_encode; +use clap::{App, Arg, ArgMatches, SubCommand}; +use rsa::RsaPublicKey; use rust_util::util_clap::{Command, CommandError}; use rust_util::XResult; +use spki::DecodePublicKey; use ssh_agent_lib::agent::{listen, Session}; use ssh_agent_lib::error::AgentError; use ssh_agent_lib::proto::{Extension, Identity, SignRequest}; use ssh_agent_lib::ssh_encoding::Encode; use ssh_agent_lib::ssh_key::public::KeyData; use ssh_agent_lib::ssh_key::{Algorithm, Signature}; +use ssh_key::public::EcdsaPublicKey; use ssh_key::{EcdsaCurve, Mpint}; +use std::convert::TryFrom; use tokio::net::UnixListener as Listener; #[derive(Default, Clone)] @@ -44,9 +49,7 @@ f17326c188b9d0cffeddd8ff935f24f2074bbef128ac5b04b9cac05de967df5dbfd065698dce3b8c ) .unwrap(); let identity = Identity { - pubkey: KeyData::Ecdsa( - ssh_key::public::EcdsaPublicKey::from_sec1_bytes(&public_key_point).unwrap(), - ), + pubkey: KeyData::Ecdsa(EcdsaPublicKey::from_sec1_bytes(&public_key_point).unwrap()), comment: "test".to_string(), }; let mut writer = vec![]; @@ -61,8 +64,11 @@ f17326c188b9d0cffeddd8ff935f24f2074bbef128ac5b04b9cac05de967df5dbfd065698dce3b8c let algorithm = &request.pubkey.algorithm(); match algorithm { Algorithm::Ecdsa { curve: _ } => {} - Algorithm::Ed25519 => {} Algorithm::Rsa { hash: _ } => {} + Algorithm::Ed25519 => { + debugging!("Algorithm::Ed25519 not supported"); + return Err(AgentError::Failure); + } Algorithm::Dsa => { debugging!("Algorithm::Dsa not supported"); return Err(AgentError::Failure); @@ -117,6 +123,24 @@ f17326c188b9d0cffeddd8ff935f24f2074bbef128ac5b04b9cac05de967df5dbfd065698dce3b8c } } +fn get_identity(uri: &str) -> XResult { + let public_key_bytes = external_command_rs::external_public_key("card-cli", uri)?; + + let ec_point = parse_ec_public_key_to_point(&public_key_bytes).unwrap(); // TODO ... + let identity = Identity { + pubkey: KeyData::Ecdsa(EcdsaPublicKey::from_sec1_bytes(&ec_point).unwrap()), + comment: "test".to_string(), + }; + + let rsa_public_key = RsaPublicKey::from_public_key_der(&public_key_bytes).unwrap(); + let identity = Identity { + pubkey: KeyData::Rsa(ssh_key::public::RsaPublicKey::try_from(&rsa_public_key).unwrap()), + comment: "test".to_string(), + }; + + simple_error!("Unknown uri algorithm: {}", uri) +} + pub struct CommandImpl; impl Command for CommandImpl { diff --git a/src/ecdsautil.rs b/src/ecdsautil.rs index 7f762d5..cb20d15 100644 --- a/src/ecdsautil.rs +++ b/src/ecdsautil.rs @@ -94,6 +94,36 @@ pub fn generate_ecdsa_keypair(algo: EcdsaAlgorithm) -> XResult<(String, String, } } +pub fn parse_ec_public_key_to_point(public_key_bytes: &[u8]) -> XResult> { + match parse_p521_public_key_to_point(public_key_bytes) { + Ok(point) => Ok(point), + Err(_) => match parse_p384_public_key_to_point(public_key_bytes) { + Ok(point) => Ok(point), + Err(_) => parse_p256_public_key_to_point(public_key_bytes), + } + } +} + +pub fn parse_p256_public_key_to_point(public_key_bytes: &[u8]) -> XResult> { + use p256::{PublicKey, elliptic_curve::sec1::ToEncodedPoint}; + use spki::DecodePublicKey; + let public_key = PublicKey::from_public_key_der(public_key_bytes)?; + Ok(public_key.to_encoded_point(false).as_bytes().to_vec()) +} + +pub fn parse_p384_public_key_to_point(public_key_bytes: &[u8]) -> XResult> { + use p384::{PublicKey, elliptic_curve::sec1::ToEncodedPoint}; + use spki::DecodePublicKey; + let public_key = PublicKey::from_public_key_der(public_key_bytes)?; + Ok(public_key.to_encoded_point(false).as_bytes().to_vec()) +} + +pub fn parse_p521_public_key_to_point(public_key_bytes: &[u8]) -> XResult> { + use p521::{PublicKey, elliptic_curve::sec1::ToEncodedPoint}; + use spki::DecodePublicKey; + let public_key = PublicKey::from_public_key_der(public_key_bytes)?; + Ok(public_key.to_encoded_point(false).as_bytes().to_vec()) +} macro_rules! parse_ecdsa_private_key_to_public_key { ($algo: tt, $parse_ecdsa_private_key: tt) => ({ diff --git a/src/rsautil.rs b/src/rsautil.rs index 2e9e6bf..f365b3d 100644 --- a/src/rsautil.rs +++ b/src/rsautil.rs @@ -226,7 +226,7 @@ pub fn rsa_public_key_to_jwk(rsa_public_key: &RsaPublicKey) -> XResult { Ok(serde_json::to_string(&jwk).unwrap()) } -fn try_parse_rsa(public_key: &str) -> XResult { +pub fn try_parse_rsa(public_key: &str) -> XResult { debugging!("Try parse RSA public key PEM."); // parse RSA public key PEM not works? why? if let Ok(rsa_public_key) = RsaPublicKey::from_public_key_pem(public_key) {