diff --git a/crates/alknet-vault/src/derivation.rs b/crates/alknet-vault/src/derivation.rs index dcbd73e..7865cc5 100644 --- a/crates/alknet-vault/src/derivation.rs +++ b/crates/alknet-vault/src/derivation.rs @@ -11,7 +11,6 @@ //! | `m/74'/0'/0'/0'` | Primary identity keypair | Ed25519 (alknet auth) | //! | `m/74'/0'/0'/{n}'` | Worker/device identity | Ed25519 | //! | `m/74'/0'/1'/0'` | SSH host key | Ed25519 | -//! | `m/74'/1'/0'/{hash}'` | Site-specific password | Deterministic | //! | `m/74'/2'/0'/0'` | Encryption key for external credentials | AES-256-GCM | //! | `m/44'/60'/0'/0/0` | Ethereum signing key | secp256k1 | @@ -52,13 +51,6 @@ pub fn device_path(index: u32) -> String { format!("m/74'/0'/0'/{}'", index) } -/// Construct a site-specific password derivation path with the given hash. -/// -/// Path: `m/74'/1'/0'/{hash}'` -pub fn site_password_path(site_hash: &str) -> String { - format!("m/74'/1'/0'/{}'", site_hash) -} - /// A derived extended private key with its public key. /// /// Contains the private key bytes and public key bytes from @@ -248,11 +240,6 @@ mod tests { assert_eq!(device_path(1), "m/74'/0'/0'/1'"); } - #[test] - fn test_site_password_path() { - assert_eq!(site_password_path("abc123"), "m/74'/1'/0'/abc123'"); - } - #[test] fn test_derive_master_key_from_seed() { // Use a known 64-byte seed diff --git a/crates/alknet-vault/src/service.rs b/crates/alknet-vault/src/service.rs index d365d41..410c624 100644 --- a/crates/alknet-vault/src/service.rs +++ b/crates/alknet-vault/src/service.rs @@ -42,9 +42,6 @@ use std::sync::{Arc, RwLock}; -use base64::engine::general_purpose::URL_SAFE_NO_PAD; -use base64::Engine; - use crate::cache::{CacheConfig, CachedKey, KeyCache}; use crate::derivation::{self, DerivationError, PATHS}; use crate::encryption::{self, EncryptedData, EncryptionKey}; @@ -283,29 +280,6 @@ impl VaultServiceHandle { } } - pub fn derive_password(&self, path: &str, length: usize) -> Result, VaultServiceError> { - let inner = self.inner.read().unwrap(); - if !inner.unlocked { - return Err(VaultServiceError::VaultLocked); - } - let seed = inner.seed.as_ref().ok_or(VaultServiceError::VaultLocked)?; - - let key = derivation::derive_path_from_seed(seed.as_bytes(), path)?; - let private_key = key.private_key(); - let truncated_len = length.min(private_key.len()); - let result = private_key[..truncated_len].to_vec(); - Ok(result) - } - - pub fn derive_password_string( - &self, - path: &str, - length: usize, - ) -> Result { - let bytes = self.derive_password(path, length)?; - Ok(URL_SAFE_NO_PAD.encode(&bytes)) - } - /// Encrypt plaintext using the derived encryption key. /// /// Uses the key at path `m/74'/2'/0'/0'` (PATHS::ENCRYPTION) by default. @@ -463,76 +437,6 @@ mod tests { assert!(service.decrypt(&encrypted).is_err()); } - #[test] - fn test_derive_password_deterministic() { - let service = VaultServiceHandle::new(); - service.unlock_new(24).unwrap(); - - let path = "m/74'/1'/0'/12345'"; - let pw1 = service.derive_password(path, 16).unwrap(); - let pw2 = service.derive_password(path, 16).unwrap(); - assert_eq!(pw1, pw2, "derive_password must be deterministic"); - } - - #[test] - fn test_derive_password_different_paths() { - let service = VaultServiceHandle::new(); - service.unlock_new(24).unwrap(); - - let pw_a = service.derive_password("m/74'/1'/0'/100'", 16).unwrap(); - let pw_b = service.derive_password("m/74'/1'/0'/200'", 16).unwrap(); - assert_ne!( - pw_a, pw_b, - "different paths must produce different passwords" - ); - } - - #[test] - fn test_derive_password_length_truncation() { - let service = VaultServiceHandle::new(); - service.unlock_new(24).unwrap(); - - let path = "m/74'/1'/0'/999'"; - let pw_full = service.derive_password(path, 32).unwrap(); - let pw_short = service.derive_password(path, 16).unwrap(); - - assert_eq!(pw_short.len(), 16); - assert_eq!(pw_full.len(), 32); - assert_eq!( - &pw_full[..16], - &pw_short[..], - "truncated bytes must match prefix of full key" - ); - } - - #[test] - fn test_derive_password_locked_error() { - let service = VaultServiceHandle::new(); - let result = service.derive_password("m/74'/1'/0'/1'", 16); - assert!(matches!(result, Err(VaultServiceError::VaultLocked))); - } - - #[test] - fn test_derive_password_string_base64url() { - let service = VaultServiceHandle::new(); - service.unlock_new(24).unwrap(); - - let path = "m/74'/1'/0'/42'"; - let encoded = service.derive_password_string(path, 16).unwrap(); - - assert!(!encoded.contains('='), "Base64url must not contain padding"); - assert!( - encoded - .chars() - .all(|c| c.is_ascii_alphanumeric() || c == '-' || c == '_'), - "Base64url must only contain URL-safe characters" - ); - - let raw_bytes = service.derive_password(path, 16).unwrap(); - let decoded = URL_SAFE_NO_PAD.decode(&encoded).unwrap(); - assert_eq!(raw_bytes, decoded); - } - #[cfg(feature = "secp256k1")] #[test] fn test_derive_ethereum_key_bip32() {