An easy-to-host PDS on the ATProtocol, MacOS. Grandma-approved.

feat(identity-wallet): add keychain module for iOS credential storage

authored by malpercio.dev and committed by

Tangled 0906ab95 01439672

+32
+32
apps/identity-wallet/src-tauri/src/keychain.rs
··· 1 + //! iOS Keychain storage for identity-wallet credentials. 2 + //! 3 + //! All items are stored as `kSecClassGenericPassword` under 4 + //! service `"ezpds-identity-wallet"`. Use the `SERVICE` constant 5 + //! to ensure consistency. 6 + 7 + // Suppressed until Phase 2 wires up the IPC command that calls these functions. 8 + #![allow(dead_code)] 9 + 10 + use security_framework::passwords::{get_generic_password, set_generic_password}; 11 + 12 + pub const SERVICE: &str = "ezpds-identity-wallet"; 13 + 14 + #[derive(Debug, thiserror::Error)] 15 + pub enum KeychainError { 16 + #[error("keychain error: {0}")] 17 + Security(#[from] security_framework::base::Error), 18 + } 19 + 20 + /// Store arbitrary bytes in the Keychain under the given account name. 21 + /// 22 + /// Creates the entry if it doesn't exist, or updates it if it does. 23 + pub fn store_item(account: &str, data: &[u8]) -> Result<(), KeychainError> { 24 + set_generic_password(SERVICE, account, data).map_err(KeychainError::Security) 25 + } 26 + 27 + /// Retrieve bytes from the Keychain for the given account name. 28 + /// 29 + /// Returns `Err` with `errSecItemNotFound` if no entry exists. 30 + pub fn get_item(account: &str) -> Result<Vec<u8>, KeychainError> { 31 + get_generic_password(SERVICE, account).map_err(KeychainError::Security) 32 + }