PubPay Cryptographic Security Implementation Summary
- Overview
- Security Architecture
- Cryptographic Algorithms
- Key Management
- Data Structure
- Security Properties
- Security Best Practices Implemented
- Attack Resistance
- Security Considerations
- Compliance & Standards
- Cryptographic Parameters Summary
- Security Audit Points
- Conclusion
Overview
This document outlines the cryptographic security measures implemented for storing and protecting Nostr private keys (nsec) in PubPay. All encryption operations use the Web Crypto API, ensuring hardware-accelerated, standards-compliant cryptographic operations.
Security Architecture
Dual Encryption Modes
The system supports two encryption modes, providing users with flexibility based on their security requirements:
-
Device Key Mode (Default)
- Automatic encryption/decryption using a device-specific key
- No user interaction required
- Suitable for single-device usage
-
Password Mode (Optional)
- User-defined password encryption
- Requires password entry on each session
- Enhanced security for multi-user or shared devices
Cryptographic Algorithms
Key Derivation: PBKDF2
Algorithm: PBKDF2 (Password-Based Key Derivation Function 2)
Hash Function: SHA-256
Iterations: 100,000
Output Key Length: 256 bits (32 bytes)
Why PBKDF2?
- NIST Recommended: Approved by NIST SP 800-132
- Time-Tested: Industry standard for password-based key derivation
- Resistant to Brute Force: High iteration count (100,000) significantly increases computation time
- Salt Protection: Unique salts prevent rainbow table attacks
Implementation Details
Device Key Mode:
- Device key: 256-bit random key stored in
localStorage - Salt: Fixed application-specific salt (
pubpay-device-salt) - Key material derived from device key via PBKDF2
Password Mode:
- Salt: 128-bit (16 bytes) randomly generated per encryption
- Salt stored alongside encrypted data (not secret)
- Unique salt per encryption prevents cross-user attacks
Symmetric Encryption: AES-GCM
Algorithm: AES (Advanced Encryption Standard)
Mode: GCM (Galois/Counter Mode)
Key Size: 256 bits
IV Length: 96 bits (12 bytes)
Why AES-GCM?
- NIST Standard: FIPS 140-2 approved
- Authenticated Encryption: Provides both confidentiality and authenticity
- Performance: Hardware-accelerated on modern CPUs
- Security: Proven secure against various attack vectors
GCM Mode Benefits
- Authentication: Detects tampering automatically
- No Padding Oracle Attacks: Unlike CBC mode, GCM is resistant to padding attacks
- Parallelizable: Efficient for high-performance scenarios
- Standard IV Size: 96-bit IV is NIST recommended
Implementation Details
- IV Generation: Cryptographically secure random IV for each encryption
- IV Storage: IV stored alongside ciphertext (standard practice for GCM)
- No IV Reuse: Each encryption uses a unique random IV
Key Management
Device Key Generation
// Generate random 256-bit key
const keyBytes = crypto.getRandomValues(new Uint8Array(32));
- Source:
crypto.getRandomValues()(cryptographically secure PRNG) - Length: 256 bits (32 bytes)
- Storage: Base64-encoded in
localStorageunder key_dk - Persistence: Survives browser sessions until explicit logout
- Isolation: Separate from encrypted data storage
Password-Based Key Derivation
PBKDF2(password, salt, 100000 iterations, SHA-256) → 256-bit AES key
- Input: User-provided password (variable length)
- Salt: 128-bit random per encryption
- Output: 256-bit AES key suitable for encryption
Data Structure
Encrypted Private Key Format
interface EncryptedPrivateKey {
encrypted: string; // Base64-encoded ciphertext
salt: string; // Base64-encoded salt (128-bit)
iv: string; // Base64-encoded initialization vector (96-bit)
hasPassword: boolean; // Encryption mode flag
}
Storage Format: JSON-serialized in localStorage
Security Properties
1. Confidentiality
- Private keys are never stored in plaintext
- Encrypted using industry-standard AES-256-GCM
- Keys derived using PBKDF2 with high iteration count
2. Integrity
- AES-GCM provides built-in authentication
- Tampering with encrypted data is automatically detected
- Decryption fails if data is modified
3. Authenticity
- GCM authentication tag verifies data origin
- Prevents unauthorized modifications
4. Forward Secrecy Considerations
- Each encryption uses unique IV
- Device key can be cleared to invalidate all encrypted data
- Password changes require re-encryption
5. Salt Protection
- Password Mode: Unique 128-bit salt per encryption
- Prevents rainbow table attacks
- Prevents cross-user key derivation attacks
- Even identical passwords produce different ciphertexts
- Device Key Mode: Application-specific fixed salt
- Appropriate for device-bound encryption
- Prevents key derivation from device key alone
Security Best Practices Implemented
Industry Standards
- NIST-approved algorithms: AES-256, PBKDF2, SHA-256
- Web Crypto API: Browser-native, hardware-accelerated
- No custom crypto: Uses only standardized, reviewed algorithms
Key Strengths
- 256-bit keys: Meets current security requirements (128-bit considered minimum)
- 100,000 PBKDF2 iterations: Significantly above minimum recommendations
- Random IVs: Cryptographically secure random generation
Implementation Security
- No key material in code: All keys derived or randomly generated
- Secure random generation: Uses
crypto.getRandomValues()(CSPRNG) - No key logging: Keys never logged or exposed in error messages
- Error handling: Cryptographically safe error messages (no information leakage)
Storage Security
- Local storage only: Data never transmitted to servers
- Encrypted at rest: All private keys encrypted before storage
- Metadata separation: Encryption mode flag stored separately from sensitive data
User Experience
- Optional password: Users choose security level
- Automatic device key mode: Seamless for single-device users
- Password validation: Clear feedback on incorrect passwords
- Legacy migration: Automatic upgrade from plaintext to encrypted format
Attack Resistance
Brute Force Attacks
- Password Mode: 100,000 PBKDF2 iterations + unique salts
- Estimated time: ~milliseconds per attempt (on modern hardware)
- 128-bit salt space: 2^128 possible salt values
- Practical brute force: Computationally infeasible
- Device Key Mode: 256-bit key space
- Brute force: 2^256 operations (computationally infeasible)
Rainbow Table Attacks
- Prevented: Unique salts per encryption
- Effect: Even identical passwords produce different ciphertexts
Dictionary Attacks
- Mitigated: High iteration count (100,000)
- Mitigated: Unique salts prevent pre-computation
- User Responsibility: Strong passwords recommended
Replay Attacks
- Prevented: Unique IVs per encryption
- GCM Authentication: Detects reused IVs
Side-Channel Attacks
- Mitigated: Web Crypto API uses hardware-accelerated, constant-time operations
- Browser Security: Implementation details hidden from JavaScript
Security Considerations
Known Limitations
-
Browser Storage Security
- Data stored in
localStorage(not encrypted filesystem) - Vulnerable to XSS attacks if application is compromised
- Mitigated by: Content Security Policy, input sanitization
- Data stored in
-
Device Key Persistence
- Device key survives browser clear data (unless explicitly cleared)
- User can manually clear
_dkto invalidate all encrypted data - Design choice: Balance security vs. user experience
-
Password Strength
- No enforced password complexity requirements
- User responsibility to choose strong passwords
- Recommended: 12+ characters, mix of character types
-
Memory Security
- Decrypted keys briefly in JavaScript memory
- Memory may be accessible to browser extensions
- Standard limitation of browser-based cryptography
Security Recommendations for Users
-
Use Password Mode for:
- Shared devices
- High-value accounts
- Multi-user environments
-
Use Device Key Mode for:
- Personal devices
- Single-user scenarios
- Convenience-focused usage
-
Best Practices:
- Use strong, unique passwords (12+ characters)
- Enable password mode on shared devices
- Regularly clear browser data if device is compromised
- Log out explicitly when finished
Compliance & Standards
Algorithm Standards
- AES: FIPS 197, ISO/IEC 18033-3
- PBKDF2: RFC 2898, NIST SP 800-132
- SHA-256: FIPS 180-4, NIST approved
- AES-GCM: NIST SP 800-38D
Implementation Standards
- Web Crypto API: W3C Web Cryptography API
- Key Derivation: OWASP recommendations followed
- IV Generation: NIST guidelines (96-bit for GCM)
Cryptographic Parameters Summary
| Parameter | Value | Standard |
|---|---|---|
| Encryption Algorithm | AES-256-GCM | NIST, FIPS |
| Key Derivation | PBKDF2 | RFC 2898, NIST SP 800-132 |
| Hash Function | SHA-256 | FIPS 180-4 |
| PBKDF2 Iterations | 100,000 | OWASP Recommended |
| Key Length | 256 bits | NIST Approved |
| IV Length | 96 bits (12 bytes) | GCM Standard |
| Salt Length | 128 bits (16 bytes) | Industry Standard |
| Device Key Length | 256 bits | NIST Approved |
| Random Source | crypto.getRandomValues() |
W3C Web Crypto API |
Security Audit Points
Code Review Checklist
- No hardcoded keys or secrets
- No key material in logs or error messages
- Proper error handling (no information leakage)
- Secure random number generation
- Proper key derivation (PBKDF2 with high iterations)
- Authenticated encryption (AES-GCM)
- Unique IVs per encryption
- Unique salts per password encryption
- No key reuse across different encryptions
Conclusion
This implementation follows industry-standard cryptographic practices, using NIST-approved algorithms and the Web Crypto API for hardware-accelerated, secure operations. The dual-mode approach provides flexibility while maintaining strong security guarantees. All encryption operations are performed client-side, ensuring private keys never leave the user’s device in decrypted form.
Security Level: Production-Ready
Algorithm Maturity: Industry Standard
Compliance: NIST, FIPS, RFC Standards
Last Updated: Nov 2025
Built with 💜 by the @PUBPAY.me team