Files

66 lines
1.8 KiB
JavaScript

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();