use auths_core::crypto::signer::encrypt_keypair;
use auths_core::storage::keychain::{KeyAlias, KeyRole, KeyStorage};
use auths_verifier::IdentityDID;
use thiserror::Error;
use zeroize::Zeroizing;
#[derive(Debug, Error)]
#[non_exhaustive]
pub enum KeyImportError {
#[error("seed must be exactly 32 bytes, got {0}")]
InvalidSeedLength(usize),
#[error("key alias cannot be empty")]
EmptyAlias,
#[error("failed to generate PKCS#8 from seed: {0}")]
Pkcs8Generation(String),
#[error("failed to encrypt private key: {0}")]
Encryption(String),
#[error("failed to store key in keychain: {0}")]
KeychainStore(String),
}
#[derive(Debug, Clone)]
pub struct KeyImportResult {
pub public_key: Vec<u8>,
pub curve: auths_crypto::CurveType,
pub alias: String,
}
pub fn import_seed(
seed: &Zeroizing<[u8; 32]>,
curve: auths_crypto::CurveType,
passphrase: &Zeroizing<String>,
alias: &str,
controller_did: &IdentityDID,
keychain: &dyn KeyStorage,
) -> Result<KeyImportResult, KeyImportError> {
if alias.trim().is_empty() {
return Err(KeyImportError::EmptyAlias);
}
let typed_seed = match curve {
auths_crypto::CurveType::Ed25519 => auths_crypto::TypedSeed::Ed25519(**seed),
auths_crypto::CurveType::P256 => auths_crypto::TypedSeed::P256(**seed),
};
let signer = auths_crypto::TypedSignerKey::from_seed(typed_seed)
.map_err(|e| KeyImportError::Pkcs8Generation(format!("failed to derive keypair: {e}")))?;
let pkcs8 = signer
.to_pkcs8()
.map_err(|e| KeyImportError::Pkcs8Generation(e.to_string()))?;
let encrypted = encrypt_keypair(pkcs8.as_ref(), passphrase)
.map_err(|e| KeyImportError::Encryption(e.to_string()))?;
keychain
.store_key(
&KeyAlias::new_unchecked(alias),
controller_did,
KeyRole::Primary,
&encrypted,
)
.map_err(|e| KeyImportError::KeychainStore(e.to_string()))?;
Ok(KeyImportResult {
public_key: signer.public_key().to_vec(),
curve,
alias: alias.to_string(),
})
}