import * as Crypto from 'expo-crypto'; /** * Handles password hashing (SHA-256) and base64 encoding of account data objects */ class CredentialEncryption { /** * Hash a password with SHA-256 and return a hex digest */ async hashPassword(password) { try { if (!password) throw new Error('Password is required'); return await Crypto.digestStringAsync( Crypto.CryptoDigestAlgorithm.SHA256, password ); } catch (error) { console.error('Password hashing error:', error); throw new Error('Failed to hash password: ' + error.message); } } /** * Compare a plaintext password against a stored hash */ async verifyPassword(password, storedHash) { try { const hash = await this.hashPassword(password); return hash === storedHash; } catch (error) { console.error('Password verification error:', error); throw new Error('Failed to verify password: ' + error.message); } } /** * Encode an object as a base64 JSON string for database storage */ encrypt(data) { try { if (!data) throw new Error('No data provided to encrypt'); const jsonString = JSON.stringify(data); return btoa(unescape(encodeURIComponent(jsonString))); } catch (error) { console.error('Encryption error:', error); throw new Error('Failed to encrypt data: ' + error.message); } } /** * Decode a base64 JSON string back to an object */ decrypt(encryptedData) { try { if (!encryptedData) return null; const jsonString = decodeURIComponent(escape(atob(encryptedData))); return JSON.parse(jsonString); } catch (error) { console.error('Decryption error:', error); throw new Error('Failed to decrypt data: ' + error.message); } } } export default new CredentialEncryption();