1use auths_core::crypto::signer::encrypt_keypair;
8use auths_core::storage::keychain::{KeyAlias, KeyRole, KeyStorage};
9use auths_verifier::IdentityDID;
10use thiserror::Error;
11use zeroize::Zeroizing;
12
13#[derive(Debug, Error)]
15#[non_exhaustive]
16pub enum KeyImportError {
17 #[error("seed must be exactly 32 bytes, got {0}")]
19 InvalidSeedLength(usize),
20
21 #[error("key alias cannot be empty")]
23 EmptyAlias,
24
25 #[error("failed to generate PKCS#8 from seed: {0}")]
27 Pkcs8Generation(String),
28
29 #[error("failed to encrypt private key: {0}")]
31 Encryption(String),
32
33 #[error("failed to store key in keychain: {0}")]
35 KeychainStore(String),
36}
37
38#[derive(Debug, Clone)]
40pub struct KeyImportResult {
41 pub public_key: Vec<u8>,
43 pub curve: auths_crypto::CurveType,
45 pub alias: String,
47}
48
49pub fn import_seed(
71 seed: &Zeroizing<[u8; 32]>,
72 curve: auths_crypto::CurveType,
73 passphrase: &Zeroizing<String>,
74 alias: &str,
75 controller_did: &IdentityDID,
76 keychain: &dyn KeyStorage,
77) -> Result<KeyImportResult, KeyImportError> {
78 if alias.trim().is_empty() {
79 return Err(KeyImportError::EmptyAlias);
80 }
81
82 let typed_seed = match curve {
83 auths_crypto::CurveType::Ed25519 => auths_crypto::TypedSeed::Ed25519(**seed),
84 auths_crypto::CurveType::P256 => auths_crypto::TypedSeed::P256(**seed),
85 };
86 let signer = auths_crypto::TypedSignerKey::from_seed(typed_seed)
87 .map_err(|e| KeyImportError::Pkcs8Generation(format!("failed to derive keypair: {e}")))?;
88 let pkcs8 = signer
89 .to_pkcs8()
90 .map_err(|e| KeyImportError::Pkcs8Generation(e.to_string()))?;
91
92 let encrypted = encrypt_keypair(pkcs8.as_ref(), passphrase)
93 .map_err(|e| KeyImportError::Encryption(e.to_string()))?;
94
95 keychain
96 .store_key(
97 &KeyAlias::new_unchecked(alias),
98 controller_did,
99 KeyRole::Primary,
100 &encrypted,
101 )
102 .map_err(|e| KeyImportError::KeychainStore(e.to_string()))?;
103
104 Ok(KeyImportResult {
105 public_key: signer.public_key().to_vec(),
106 curve,
107 alias: alias.to_string(),
108 })
109}