# Security Guide for Savings Feature

This document provides security guidance for developers implementing the savings feature in their wallet applications (mobile apps, browser extensions, desktop apps).

## Table of Contents

1. [Security Model](#security-model)
2. [Two Implementation Patterns](#two-implementation-patterns)
3. [Secure Storage](#secure-storage)
4. [Authentication & Authorization](#authentication--authorization)
5. [Memory Management](#memory-management)
6. [Session Management](#session-management)
7. [Best Practices](#best-practices)
8. [Security Checklist](#security-checklist)

## Security Model

### SDK Responsibilities

This SDK provides:
- ✅ Cryptographic primitives for key derivation
- ✅ Input validation for all operations
- ✅ Memory cleanup utilities
- ✅ Two operation patterns (stateful and stateless)
- ✅ Security documentation and examples

### Implementer Responsibilities

Your application must handle:
- 🔐 **Secure Storage**: Encrypting and storing mnemonics/keys
- 🔐 **Authentication**: Verifying user identity (biometrics, password, PIN)
- 🔐 **Authorization**: Controlling access to wallet operations
- 🔐 **App Lifecycle**: Clearing memory when app backgrounds/closes
- 🔐 **User Education**: Teaching users about security best practices

## Two Implementation Patterns

Choose the pattern that best fits your application architecture:

### Pattern 1: Stateless Operations (Recommended for Extensions)

**Best for**: Browser extensions, short-lived sessions

```typescript
import { SavingsOperations } from '@wallet/utils/savings/savings-operations';

// Create operations handler (no sensitive data stored)
const operations = new SavingsOperations();

// Each operation requires mnemonic
async function transferFromPocket(pocketIndex: number, to: string, amount: bigint) {
  // Get mnemonic from secure storage (implementer handles this)
  const mnemonic = await secureStorage.getMnemonic();

  // Perform operation - mnemonic not cached
  const result = await operations.transferFromPocket(
    mnemonic,
    { accountIndex: pocketIndex, to, amount },
    provider,
    chain
  );

  // Mnemonic automatically cleared after operation
  return result;
}
```

**Advantages**:
- No persistent mnemonic in memory
- Automatic cleanup after each operation
- Better for browser extension background scripts

### Pattern 2: Stateful Manager (Recommended for Mobile Apps)

**Best for**: Mobile apps, long-lived sessions

```typescript
import { SavingsManager } from '@wallet/utils/savings/saving-manager';

let savingsManager: SavingsManager | null = null;

// Initialize when user authenticates
async function initializeWallet() {
  const mnemonic = await secureStorage.getMnemonic();
  savingsManager = new SavingsManager(mnemonic, chainConfig);
}

// Use manager for operations
async function transferToPocket(pocketIndex: number, amount: string) {
  if (!savingsManager) throw new Error('Wallet not initialized');
  return await savingsManager.transferToPocket(walletClient, pocketIndex, amount);
}

// Clean up when user locks wallet or app backgrounds
function lockWallet() {
  if (savingsManager) {
    savingsManager.dispose();
    savingsManager = null;
  }
}
```

**Advantages**:
- Better performance (no repeated key derivation)
- Simpler code for multiple operations
- Suitable for authenticated sessions

## Secure Storage

### iOS (React Native / Swift)

Use iOS Keychain for maximum security:

```typescript
// React Native example with react-native-keychain
import * as Keychain from 'react-native-keychain';

async function storeMnemonic(mnemonic: string) {
  await Keychain.setGenericPassword(
    'wallet-mnemonic',
    mnemonic,
    {
      accessible: Keychain.ACCESSIBLE.WHEN_UNLOCKED_THIS_DEVICE_ONLY,
      service: 'com.yourapp.wallet'
    }
  );
}

async function getMnemonic(): Promise<string> {
  const credentials = await Keychain.getGenericPassword({
    service: 'com.yourapp.wallet'
  });

  if (!credentials) {
    throw new Error('Mnemonic not found');
  }

  return credentials.password;
}
```

**Security Features**:
- Hardware-backed encryption (Secure Enclave on newer devices)
- Data protected by device passcode
- Automatic deletion on app uninstall

### Android (React Native / Kotlin)

Use Android Keystore:

```typescript
// React Native example with react-native-keychain
import * as Keychain from 'react-native-keychain';

async function storeMnemonic(mnemonic: string) {
  await Keychain.setGenericPassword(
    'wallet-mnemonic',
    mnemonic,
    {
      accessible: Keychain.ACCESSIBLE.WHEN_UNLOCKED_THIS_DEVICE_ONLY,
      service: 'com.yourapp.wallet',
      securityLevel: Keychain.SECURITY_LEVEL.SECURE_HARDWARE
    }
  );
}
```

**Security Features**:
- Hardware-backed encryption (TEE/StrongBox on supported devices)
- Biometric authentication integration
- Key material never leaves secure hardware

### Browser Extensions

Use extension storage APIs with encryption:

```typescript
import { encrypt, decrypt } from './crypto'; // Your encryption implementation

async function storeMnemonic(mnemonic: string, password: string) {
  // Derive encryption key from user password
  const encryptionKey = await deriveKey(password);

  // Encrypt mnemonic
  const encrypted = await encrypt(mnemonic, encryptionKey);

  // Store in extension storage
  await chrome.storage.local.set({
    'encrypted-mnemonic': encrypted
  });
}

async function getMnemonic(password: string): Promise<string> {
  const { 'encrypted-mnemonic': encrypted } = await chrome.storage.local.get(
    'encrypted-mnemonic'
  );

  if (!encrypted) {
    throw new Error('Mnemonic not found');
  }

  // Derive encryption key from password
  const encryptionKey = await deriveKey(password);

  // Decrypt mnemonic
  return await decrypt(encrypted, encryptionKey);
}
```

**Security Considerations**:
- Use strong encryption (AES-256-GCM)
- Derive encryption key using PBKDF2 or Argon2
- Never store encryption key in storage
- Clear decrypted mnemonic from memory after use

## Authentication & Authorization

### Biometric Authentication (Mobile)

```typescript
import TouchID from 'react-native-touch-id';

async function authenticateForTransaction(): Promise<boolean> {
  try {
    await TouchID.authenticate('Confirm transaction', {
      title: 'Authentication Required',
      fallbackLabel: 'Use Passcode',
      passcodeFallback: true
    });
    return true;
  } catch (error) {
    console.error('Authentication failed:', error);
    return false;
  }
}

// Use before sensitive operations
async function sendFromPocket(pocketIndex: number, to: string, amount: bigint) {
  // Require authentication
  const authenticated = await authenticateForTransaction();
  if (!authenticated) {
    throw new Error('Authentication required');
  }

  // Proceed with operation
  const mnemonic = await secureStorage.getMnemonic();
  return await operations.transferFromPocket(mnemonic, { ... });
}
```

### Password Authentication (Browser Extensions)

```typescript
// Session management for browser extensions
class SessionManager {
  private decryptedMnemonic: string | null = null;
  private sessionTimeout: number = 15 * 60 * 1000; // 15 minutes
  private timeoutId?: NodeJS.Timeout;

  async unlock(password: string): Promise<void> {
    // Decrypt and cache mnemonic
    this.decryptedMnemonic = await getMnemonic(password);

    // Set auto-lock timer
    this.resetTimeout();
  }

  lock(): void {
    // Clear mnemonic from memory
    if (this.decryptedMnemonic) {
      this.decryptedMnemonic = '';
      this.decryptedMnemonic = null;
    }

    if (this.timeoutId) {
      clearTimeout(this.timeoutId);
    }
  }

  private resetTimeout(): void {
    if (this.timeoutId) {
      clearTimeout(this.timeoutId);
    }

    this.timeoutId = setTimeout(() => {
      this.lock();
    }, this.sessionTimeout);
  }

  getMnemonic(): string {
    if (!this.decryptedMnemonic) {
      throw new Error('Wallet locked');
    }

    // Reset timeout on each access
    this.resetTimeout();

    return this.decryptedMnemonic;
  }
}
```

## Memory Management

### Using Stateful Manager

```typescript
// Initialize manager when user authenticates
let manager: SavingsManager | null = null;

function initManager(mnemonic: string) {
  manager = new SavingsManager(mnemonic, chainConfig);
}

// Clear memory when appropriate
function cleanup() {
  if (manager) {
    // Clear all cached data
    manager.dispose();
    manager = null;
  }
}

// App lifecycle hooks
// React Native example
import { AppState } from 'react-native';

AppState.addEventListener('change', (nextAppState) => {
  if (nextAppState === 'background' || nextAppState === 'inactive') {
    // Clear sensitive data when app backgrounds
    cleanup();
  }
});
```

### Using Stateless Operations

```typescript
// No persistent state - mnemonic cleared after each operation
const operations = new SavingsOperations();

async function transfer() {
  // Get mnemonic only for this operation
  const mnemonic = await secureStorage.getMnemonic();

  try {
    return await operations.transferFromPocket(
      mnemonic,
      { accountIndex: 0, to: '0x...', amount: 1000n },
      provider,
      chain
    );
  } finally {
    // Mnemonic automatically cleared by operations class
  }
}
```

### JavaScript Memory Limitations

**Important**: JavaScript strings are immutable. When you "clear" a string, you're only removing your reference to it. The actual data remains in memory until garbage collected.

**Best Practices**:
1. Minimize the lifetime of sensitive data in memory
2. Call disposal methods when done
3. Remove all references to allow garbage collection
4. Consider using `ArrayBuffer` for highly sensitive operations (advanced)

```typescript
// Example with ArrayBuffer (advanced)
function secureStringToBuffer(str: string): ArrayBuffer {
  const encoder = new TextEncoder();
  return encoder.encode(str).buffer;
}

function clearBuffer(buffer: ArrayBuffer): void {
  const view = new Uint8Array(buffer);
  view.fill(0);
}
```

## Session Management

### Mobile Apps

```typescript
import { AppState } from 'react-native';

class WalletSession {
  private manager: SavingsManager | null = null;
  private lockTimer?: NodeJS.Timeout;
  private autoLockDelay = 5 * 60 * 1000; // 5 minutes

  constructor() {
    // Listen for app state changes
    AppState.addEventListener('change', this.handleAppStateChange);
  }

  async unlock(mnemonic: string) {
    this.manager = new SavingsManager(mnemonic, chainConfig);
    this.resetLockTimer();
  }

  lock() {
    if (this.manager) {
      this.manager.dispose();
      this.manager = null;
    }

    if (this.lockTimer) {
      clearTimeout(this.lockTimer);
    }
  }

  private resetLockTimer() {
    if (this.lockTimer) {
      clearTimeout(this.lockTimer);
    }

    this.lockTimer = setTimeout(() => {
      this.lock();
    }, this.autoLockDelay);
  }

  private handleAppStateChange = (nextAppState: string) => {
    if (nextAppState === 'background' || nextAppState === 'inactive') {
      // Lock immediately when app backgrounds
      this.lock();
    }
  };

  getManager(): SavingsManager {
    if (!this.manager) {
      throw new Error('Wallet locked - authentication required');
    }

    // Reset auto-lock timer on each access
    this.resetLockTimer();

    return this.manager;
  }
}
```

### Browser Extensions

```typescript
// Background script session management
class ExtensionSession {
  private operations = new SavingsOperations();
  private encryptedMnemonic: string | null = null;
  private password: string | null = null;

  async unlock(password: string): Promise<void> {
    // Verify password by attempting decryption
    const mnemonic = await this.decrypt(password);

    // Store for session
    this.password = password;

    // Keep background script alive (Chrome MV3)
    this.keepAlive();
  }

  lock(): void {
    this.password = null;
  }

  async performOperation<T>(
    operation: (mnemonic: string) => Promise<T>
  ): Promise<T> {
    if (!this.password) {
      throw new Error('Extension locked');
    }

    // Decrypt mnemonic for this operation only
    const mnemonic = await this.decrypt(this.password);

    try {
      return await operation(mnemonic);
    } finally {
      // Mnemonic goes out of scope and will be garbage collected
    }
  }

  private async decrypt(password: string): Promise<string> {
    // Implement decryption logic
    // ...
  }

  private keepAlive(): void {
    // For Chrome MV3 extensions
    setInterval(() => {
      chrome.runtime.getPlatformInfo(() => {
        // Keep background script alive
      });
    }, 20000);
  }
}
```

## Best Practices

### 1. Defense in Depth

Implement multiple layers of security:

```typescript
class SecureWallet {
  // Layer 1: Encrypted storage
  private async getEncryptedMnemonic(): Promise<string> {
    return await secureStorage.get('mnemonic');
  }

  // Layer 2: Password/biometric authentication
  private async authenticate(): Promise<boolean> {
    return await biometric.authenticate();
  }

  // Layer 3: Session timeout
  private sessionManager = new SessionManager();

  // Layer 4: Transaction confirmation
  async sendTransaction(tx: Transaction): Promise<TransactionResult> {
    // Require authentication
    if (!await this.authenticate()) {
      throw new Error('Authentication failed');
    }

    // Check session
    const mnemonic = this.sessionManager.getMnemonic();

    // Show confirmation dialog
    const confirmed = await this.confirmTransaction(tx);
    if (!confirmed) {
      throw new Error('Transaction cancelled');
    }

    // Perform operation
    return await this.operations.transferFromPocket(mnemonic, tx, ...);
  }
}
```

### 2. User Education

Educate users about:
- Never sharing their mnemonic phrase
- Importance of secure device passcode
- Enabling biometric authentication
- Risks of rooted/jailbroken devices
- Importance of software updates

### 3. Rate Limiting

Implement rate limiting for failed authentication attempts:

```typescript
class RateLimiter {
  private attempts = 0;
  private lockUntil: number = 0;

  async checkAndIncrement(): Promise<void> {
    if (Date.now() < this.lockUntil) {
      const remainingMs = this.lockUntil - Date.now();
      throw new Error(`Too many attempts. Try again in ${Math.ceil(remainingMs / 1000)}s`);
    }

    this.attempts++;

    if (this.attempts >= 5) {
      // Lock for 5 minutes after 5 failed attempts
      this.lockUntil = Date.now() + 5 * 60 * 1000;
      this.attempts = 0;
      throw new Error('Too many failed attempts. Account locked for 5 minutes.');
    }
  }

  reset(): void {
    this.attempts = 0;
    this.lockUntil = 0;
  }
}
```

### 4. Input Validation

Always validate user inputs before operations:

```typescript
// The SDK provides validation utilities
import { SavingsValidation } from '@wallet/utils/savings/validation';

async function validateAndSend(to: string, amount: string) {
  try {
    // Validate inputs
    SavingsValidation.validateAddress(to, 'Recipient address');
    SavingsValidation.validateAmountString(amount, 'Amount');

    // Parse amount
    const amountBigInt = parseUnits(amount, 18);

    // Perform operation
    return await operations.transferFromPocket(mnemonic, {
      accountIndex: 0,
      to,
      amount: amountBigInt
    }, provider, chain);
  } catch (error) {
    // Show user-friendly error message
    throw new Error(`Invalid input: ${error.message}`);
  }
}
```

### 5. Logging and Monitoring

Never log sensitive data:

```typescript
// ❌ NEVER DO THIS
console.log('Mnemonic:', mnemonic);
console.log('Private key:', privateKey);

// ✅ DO THIS
console.log('Transaction sent:', {
  hash: result.hash,
  from: publicAddress,
  to: recipientAddress,
  // No sensitive data
});
```

### 6. Testing

Test security features thoroughly:

```typescript
describe('Wallet Security', () => {
  it('should clear mnemonic on lock', async () => {
    const manager = new SavingsManager(mnemonic, chainConfig);
    manager.dispose();

    // Verify internal state is cleared
    expect((manager as any).mnemonic).toBe('');
  });

  it('should require authentication for transactions', async () => {
    // Mock authentication failure
    jest.spyOn(biometric, 'authenticate').mockRejectedValue(new Error('Failed'));

    await expect(
      wallet.sendTransaction({ ... })
    ).rejects.toThrow('Authentication failed');
  });

  it('should lock after timeout', async () => {
    const session = new SessionManager(5000); // 5s timeout
    await session.unlock('password');

    // Wait for timeout
    await new Promise(resolve => setTimeout(resolve, 6000));

    expect(() => session.getMnemonic()).toThrow('Wallet locked');
  });
});
```

## Security Checklist

Before deploying your wallet application, verify:

### Secure Storage
- [ ] Mnemonic encrypted at rest
- [ ] Using platform-specific secure storage (Keychain/Keystore)
- [ ] Encryption key derived from strong password
- [ ] No sensitive data in logs or analytics

### Authentication
- [ ] Biometric authentication enabled (mobile)
- [ ] Strong password requirements (extensions)
- [ ] Rate limiting on failed attempts
- [ ] Session timeout implemented

### Memory Management
- [ ] Dispose methods called on lock/logout
- [ ] Sensitive data cleared on app background
- [ ] No persistent references to sensitive data
- [ ] Session management implemented

### Input Validation
- [ ] All user inputs validated
- [ ] Address checksums verified
- [ ] Amount limits enforced
- [ ] Transaction confirmations required

### User Experience
- [ ] Clear security warnings
- [ ] Transaction confirmation dialogs
- [ ] User education materials
- [ ] Secure backup instructions

### Testing
- [ ] Security features tested
- [ ] Attack scenarios simulated
- [ ] Third-party security audit completed
- [ ] Penetration testing performed

### Compliance
- [ ] Privacy policy published
- [ ] Terms of service published
- [ ] GDPR compliance (if applicable)
- [ ] Local regulations followed

## Additional Resources

- [OWASP Mobile Security Guide](https://owasp.org/www-project-mobile-security/)
- [Chrome Extension Security Best Practices](https://developer.chrome.com/docs/extensions/mv3/security/)
- [iOS Security Guide](https://support.apple.com/guide/security/welcome/web)
- [Android Security Best Practices](https://developer.android.com/privacy-and-security/security-tips)

## Reporting Security Issues

If you discover a security vulnerability in this SDK, please report it to:
- Email: security@yourcompany.com
- Use responsible disclosure practices
- Allow time for patching before public disclosure

## License

This security guide is provided as-is for educational purposes.
