auths_sdk/workflows/
git_integration.rs1use ssh_key::PublicKey as SshPublicKey;
4use ssh_key::public::Ed25519PublicKey;
5use thiserror::Error;
6
7#[derive(Debug, Error)]
9pub enum GitIntegrationError {
10 #[error("invalid public key length: expected 32 (Ed25519), 33/65 (P-256), got {0}")]
12 InvalidKeyLength(usize),
13 #[error("failed to encode SSH public key: {0}")]
15 SshKeyEncoding(String),
16}
17
18pub fn public_key_to_ssh(
28 key: &auths_verifier::DevicePublicKey,
29) -> Result<String, GitIntegrationError> {
30 match key.curve() {
31 auths_crypto::CurveType::Ed25519 => {
32 let signing_pk = Ed25519PublicKey::try_from(key.as_bytes())
33 .map_err(|e| GitIntegrationError::SshKeyEncoding(e.to_string()))?;
34 let ssh_pk = SshPublicKey::from(signing_pk);
35 ssh_pk
36 .to_openssh()
37 .map_err(|e| GitIntegrationError::SshKeyEncoding(e.to_string()))
38 }
39 auths_crypto::CurveType::P256 => {
40 use ssh_key::public::{EcdsaPublicKey, KeyData};
41
42 let uncompressed_bytes = if key.len() == 33 {
43 use p256::ecdsa::VerifyingKey;
44 let vk = VerifyingKey::from_sec1_bytes(key.as_bytes()).map_err(|e| {
45 GitIntegrationError::SshKeyEncoding(format!("P-256 key parse: {e}"))
46 })?;
47 vk.to_encoded_point(false).as_bytes().to_vec()
48 } else {
49 key.as_bytes().to_vec()
50 };
51
52 let ecdsa_pk = EcdsaPublicKey::from_sec1_bytes(&uncompressed_bytes)
53 .map_err(|e| GitIntegrationError::SshKeyEncoding(format!("ECDSA SSH key: {e}")))?;
54
55 let ssh_pk = SshPublicKey::from(KeyData::Ecdsa(ecdsa_pk));
56 ssh_pk
57 .to_openssh()
58 .map_err(|e| GitIntegrationError::SshKeyEncoding(e.to_string()))
59 }
60 }
61}