Key Alias Security Enhancement
Overview
This document describes the comprehensive security enhancements in the React Native Biometrics library, including configurable app-specific key aliases, advanced key integrity validation, signature verification, and enhanced logging capabilities for security monitoring.
Security Issue Fixed
Implementation (Secure)
- App-Specific Default: Each app gets a unique default key alias based on bundle ID (iOS) or package name (Android)
- Configurable Aliases: Developers can set custom key aliases for different use cases
- Isolation: Each app's biometric keys are properly isolated
API Changes
New Configuration Functions
// Configure a custom key alias
await configureKeyAlias('com.myapp.biometric.main');
// Get the current default key alias
const defaultAlias = await getDefaultKeyAlias();
// Configure using a config object
await configure({
keyAlias: 'com.myapp.biometric.main',
keyPrefix: 'com.myapp.secure'
});
// Enable security logging for monitoring
import { setDebugMode, enableLogging, LogLevel } from '@sbaiahmed1/react-native-biometrics';
await setDebugMode(true);
enableLogging(true);
setLogLevel(LogLevel.INFO);
Enhanced Key Management
// Create keys with default (configured) alias
const keyResult = await createKeys();
console.log('Public key:', keyResult.publicKey);
// Create keys with a specific alias
await createKeys('com.myapp.biometric.backup');
// Get all keys for audit purposes
const allKeys = await getAllKeys();
console.log('Total keys:', allKeys.keys.length);
// Delete keys with default (configured) alias
const deleteResult = await deleteKeys();
console.log('Deletion success:', deleteResult.success);
// Delete keys with a specific alias
await deleteKeys('com.myapp.biometric.backup');
Default Key Alias Generation
iOS
- Format:
{bundleId}.ReactNativeBiometrics - Example:
com.mycompany.myapp.ReactNativeBiometrics - Storage: Stored in
UserDefaultswith keyReactNativeBiometrics_KeyAlias
Android
- Format:
{packageName}.ReactNativeBiometrics - Example:
com.mycompany.myapp.ReactNativeBiometrics - Storage: Stored in
SharedPreferenceswith keykeyAlias
Migration Guide
For Existing Apps
-
No Action Required: Existing apps will continue to work with the old hardcoded alias until you explicitly configure a new one.
-
Recommended Migration:
// Get all existing keysconst existingKeys = await getAllKeys();// Configure new app-specific aliasawait configureKeyAlias('com.myapp.biometric.main');// Create new keys with the new aliasawait createKeys();// Optionally delete old keys (be careful!)// await deleteKeys('ReactNativeBiometricsKey'); -
Gradual Migration:
// Check if old keys existconst allKeys = await getAllKeys();const hasOldKeys = allKeys.keys.some(key =>key.alias === 'ReactNativeBiometricsKey');if (hasOldKeys) {// Use old keys for now, migrate laterconsole.log('Using legacy keys');} else {// Configure new alias for new installationsawait configureKeyAlias('com.myapp.biometric.main');}
Advanced Security Features
Key Integrity Validation
// Comprehensive key integrity check
const integrityResult = await validateKeyIntegrity('com.myapp.biometric.main');
if (integrityResult.valid) {
console.log('Key integrity verified');
console.log('Hardware-backed:', integrityResult.integrityChecks.hardwareBacked);
console.log('Key accessible:', integrityResult.integrityChecks.keyAccessible);
console.log('Signature test:', integrityResult.integrityChecks.signatureTestPassed);
} else {
console.error('Key integrity compromised:', integrityResult.error);
}
Signature Verification
// Generate and verify signatures for data integrity
const data = 'sensitive transaction data';
// Generate signature
const signatureResult = await verifyKeySignature('com.myapp.biometric.main', data);
if (signatureResult.success && signatureResult.signature) {
const signature = signatureResult.signature;
// Later, validate the signature
const validationResult = await validateSignature(
'com.myapp.biometric.main',
data,
signature
);
if (validationResult.valid) {
console.log('Data integrity verified');
} else {
console.error('Data may have been tampered with');
}
}
Key Attributes and Security Level
// Get detailed key attributes for security assessment
const keyAttributes = await getKeyAttributes('com.myapp.biometric.main');
if (keyAttributes.exists && keyAttributes.attributes) {
const attrs = keyAttributes.attributes;
console.log('Algorithm:', attrs.algorithm);
console.log('Key size:', attrs.keySize);
console.log('Security level:', attrs.securityLevel);
console.log('Hardware-backed:', attrs.hardwareBacked);
console.log('User auth required:', attrs.userAuthenticationRequired);
console.log('Creation date:', attrs.creationDate);
}
Security Best Practices
1. Use Descriptive Key Aliases
// Good: Descriptive and app-specific
await configureKeyAlias('com.myapp.biometric.login');
await configureKeyAlias('com.myapp.biometric.payment');
// Avoid: Generic or potentially conflicting
await configureKeyAlias('biometric');
await configureKeyAlias('key');
2. Multiple Key Aliases for Different Purposes
// Different aliases for different security contexts
const LOGIN_KEY_ALIAS = 'com.myapp.biometric.login';
const PAYMENT_KEY_ALIAS = 'com.myapp.biometric.payment';
const ADMIN_KEY_ALIAS = 'com.myapp.biometric.admin';
// Create keys for different purposes
await createKeys(LOGIN_KEY_ALIAS);
await createKeys(PAYMENT_KEY_ALIAS);
3. Key Rotation Strategy
// Implement secure key rotation with integrity validation
const rotateKeys = async () => {
const oldAlias = 'com.myapp.biometric.v1';
const newAlias = 'com.myapp.biometric.v2';
try {
// Create new keys
const newKeyResult = await createKeys(newAlias);
// Validate new key integrity
const integrityCheck = await validateKeyIntegrity(newAlias);
if (!integrityCheck.valid) {
throw new Error('New key integrity validation failed');
}
// Test signature with new key
const testData = 'key rotation test';
const signatureTest = await verifyKeySignature(newAlias, testData);
if (!signatureTest.success) {
throw new Error('New key signature test failed');
}
// Persist the new alias only after all validation succeeded
await configureKeyAlias(newAlias);
// Delete old keys after successful validation
await deleteKeys(oldAlias);
console.log('Key rotation completed successfully');
} catch (error) {
console.error('Key rotation failed:', error);
// Rollback: point the configured alias back at the old keys, then remove the new keys.
// (Covers the case where the failure happened after configureKeyAlias(newAlias).)
await configureKeyAlias(oldAlias);
await deleteKeys(newAlias);
throw error;
}
};
Validation Rules
Key Alias Requirements
- Minimum Length: 3 characters
- Maximum Length: 100 characters
- Allowed Characters: Letters, numbers, dots, hyphens, underscores
- Pattern: Must match
^[a-zA-Z0-9._-]+$
Examples
// Valid aliases
'com.myapp.biometric'
'myapp_biometric_key'
'biometric-key-v1'
'app.biometric.2024'
// Invalid aliases
'' // Too short
'a' // Too short
'key with spaces' // Contains spaces
'key@domain.com' // Contains @
'key#1' // Contains #
Error Handling and Security Monitoring
Enhanced Error Handling
import { logger, getLogs, clearLogs } from '@sbaiahmed1/react-native-biometrics';
try {
await configureKeyAlias('com.myapp.biometric');
} catch (error) {
if (error.message.includes('Invalid key alias')) {
// Handle validation error
logger.error('Key alias format is invalid', 'configureKeyAlias', error);
} else if (error.message.includes('Key already exists')) {
// Handle key collision
logger.warn('Key alias already in use', 'configureKeyAlias', error);
} else {
// Handle other errors
logger.error('Failed to configure key alias', 'configureKeyAlias', error);
}
}
Security Event Logging
// Monitor security events
const monitorSecurityEvents = async () => {
try {
// Enable comprehensive logging
await setDebugMode(true);
// Perform security operations
await createKeys('com.myapp.secure.key');
const integrity = await validateKeyIntegrity('com.myapp.secure.key');
// Get security logs for analysis
const logs = getLogs();
const securityLogs = logs.filter(log =>
log.context?.includes('security') ||
log.context?.includes('integrity') ||
log.context?.includes('signature')
);
// Send to security monitoring system
await sendToSecurityMonitoring(securityLogs);
// Clear logs after processing
clearLogs();
} catch (error) {
logger.error('Security monitoring failed', 'monitorSecurityEvents', error);
}
};
Testing
Unit Tests
// Test key alias validation
it('should reject invalid key aliases', async () => {
await expect(configureKeyAlias('')).rejects.toThrow('Invalid key alias');
await expect(configureKeyAlias('a')).rejects.toThrow('Invalid key alias');
await expect(configureKeyAlias('key with spaces')).rejects.toThrow('Invalid key alias');
});
// Test key isolation
it('should isolate keys by alias', async () => {
await createKeys('alias1');
await createKeys('alias2');
const keys = await getAllKeys();
expect(keys.keys).toHaveLength(2);
await deleteKeys('alias1');
const remainingKeys = await getAllKeys();
expect(remainingKeys.keys).toHaveLength(1);
expect(remainingKeys.keys[0].alias).toBe('alias2');
});
Performance Considerations
- Configuration Persistence: Key alias configuration is persisted locally and loaded once during module initialization
- No Network Calls: All key alias operations are local
- Minimal Overhead: Key alias resolution adds negligible performance overhead
Security Audit Checklist
- ✅ Hardcoded key aliases removed
- ✅ App-specific default aliases implemented
- ✅ Key alias validation implemented
- ✅ Secure storage for configuration
- ✅ Cross-app key isolation verified
- ✅ Migration path documented
- ✅ Error handling implemented
- ✅ Input validation added
Security Compliance and Auditing
Compliance Checklist
// Security compliance validation
const validateSecurityCompliance = async (keyAlias: string) => {
const compliance = {
keyExists: false,
hardwareBacked: false,
integrityValid: false,
signatureWorking: false,
userAuthRequired: false,
securityLevel: 'unknown'
};
try {
// Check key existence and attributes
const attributes = await getKeyAttributes(keyAlias);
if (attributes.exists) {
compliance.keyExists = true;
compliance.hardwareBacked = attributes.attributes?.hardwareBacked || false;
compliance.userAuthRequired = attributes.attributes?.userAuthenticationRequired || false;
compliance.securityLevel = attributes.attributes?.securityLevel || 'unknown';
}
// Validate key integrity
const integrity = await validateKeyIntegrity(keyAlias);
compliance.integrityValid = integrity.valid;
compliance.signatureWorking = integrity.integrityChecks.signatureTestPassed;
return compliance;
} catch (error) {
logger.error('Security compliance check failed', 'validateSecurityCompliance', error);
return compliance;
}
};
Audit Trail
// Generate security audit report
const generateSecurityAudit = async () => {
const audit = {
timestamp: new Date().toISOString(),
keys: [],
securityEvents: [],
complianceStatus: 'unknown'
};
try {
// Get all keys for audit
const allKeys = await getAllKeys();
for (const key of allKeys.keys) {
const compliance = await validateSecurityCompliance(key.alias);
audit.keys.push({
alias: key.alias,
compliance
});
}
// Get security-related logs
const logs = getLogs();
audit.securityEvents = logs.filter(log =>
log.level === 'error' || log.level === 'warn'
);
// Determine overall compliance status.
// Note: every() returns true for an empty array, so treat "no keys" as its own status.
const allCompliant = audit.keys.length > 0 && audit.keys.every(key =>
key.compliance.keyExists &&
key.compliance.hardwareBacked &&
key.compliance.integrityValid &&
key.compliance.signatureWorking &&
key.compliance.userAuthRequired
);
audit.complianceStatus =
audit.keys.length === 0
? 'no-keys-audited'
: allCompliant
? 'compliant'
: 'non-compliant';
return audit;
} catch (error) {
logger.error('Security audit generation failed', 'generateSecurityAudit', error);
return audit;
}
};
Future Enhancements
- Key Alias Encryption: Encrypt key alias configuration in storage
- Automatic Key Rotation: Scheduled key rotation policies with integrity validation
- Advanced Audit Logging: Comprehensive security event logging with tamper detection
- Remote Security Policies: Support for remote security configuration and compliance policies
- Key Alias Templates: Predefined templates for industry-specific security requirements
- Biometric Template Protection: Enhanced protection for biometric template data
- Multi-Factor Key Validation: Combine multiple validation methods for enhanced security
- Real-time Security Monitoring: Live monitoring of key integrity and usage patterns