> TECHNICAL_DOCUMENTATION
VAULT ARCHITECTURE
Deep dive into Nu11VLT's zero-knowledge encryption system. Real code. Real security.
> SYSTEM_OVERVIEW
Zero-Knowledge Architecture
HARDWARE SECURITY
Keys stored in iOS Keychain with Secure Enclave protection. Cannot be extracted via software.
LOCAL ONLY
No network requests. No cloud storage. Everything stays on your device.
TRIPLE ENCRYPTION
Separate keys for Vault, Fade, and Decoy modes. Keys never cross-contaminate.
> SOURCE_CODE
Core Encryption Engine
import Foundation
import CryptoKit
@MainActor
class VaultCrypto: ObservableObject {
private var vaultKey: SymmetricKey?
private var fadeKey: SymmetricKey?
private let vaultKeyName = "com.nu11vlt.vaultKey"
private let fadeKeyName = "com.nu11vlt.fadeKey"
private let decoyKeyName = "com.nu11vlt.vaultKey.decoy"
/// Setup or load the vault encryption key (256-bit)
func setupVaultKey() -> Bool {
if let existingKey = KeychainHelper.loadKey(forName: vaultKeyName) {
self.vaultKey = existingKey
return true
} else {
let newKey = SymmetricKey(size: .bits256)
if KeychainHelper.saveKey(newKey, forName: vaultKeyName) {
self.vaultKey = newKey
return true
}
return false
}
}
/// Encrypt image data with ChaCha20-Poly1305 AEAD
func encryptVaultImage(_ imageData: Data) throws -> Data {
guard let key = vaultKey else {
throw CryptoError.keyNotAvailable
}
// ChaCha20-Poly1305 provides:
// - Confidentiality (encryption)
// - Authenticity (HMAC)
// - Integrity (tampering detection)
let sealedBox = try ChaChaPoly.seal(imageData, using: key)
return sealedBox.combined // Nonce + Ciphertext + Tag
}
/// Decrypt image data from vault storage
func decryptVaultImage(_ encryptedData: Data) throws -> Data {
guard let key = vaultKey else {
throw CryptoError.keyNotAvailable
}
let sealedBox = try ChaChaPoly.SealedBox(combined: encryptedData)
let decryptedData = try ChaChaPoly.open(sealedBox, using: key)
return decryptedData
}
/// Switch to decoy vault (Panic PIN triggered)
func switchToDecoyVault() {
if let decoyKey = KeychainHelper.loadKey(forName: decoyKeyName) {
self.vaultKey = decoyKey
// Adversary sees decoy photos with zero indicators
}
}
}
WHY CHACHA20-POLY1305?
- ✓ Faster than AES on mobile devices (no hardware AES needed)
- ✓ Authenticated encryption (detects tampering)
- ✓ Used by Signal, Google, Cloudflare, WireGuard
- ✓ Resistant to timing attacks
- ✓ IETF standard (RFC 8439)
KEY PROTECTION
- ✓ 256-bit keys (2^256 possible combinations)
- ✓ Stored in iOS Keychain (hardware-backed)
- ✓ Never persisted to disk unencrypted
- ✓ Cannot be extracted without device unlock
- ✓ Keys wiped on Skeleton Switch trigger
> PANIC_PIN_SYSTEM
Decoy Vault (Plausible Deniability)
/// Validate PIN and determine which vault to unlock
func validatePINAndUnlock(_ pin: String) -> UnlockResult {
// Check panic PIN first (adversary doesn't know it exists)
if PanicPINManager.shared.hasPanicPINConfigured &&
PanicPINManager.shared.validatePanicPIN(pin) {
#if DEBUG
print("[AUTH] Panic PIN detected - loading decoy vault")
#endif
// Switch to decoy vault silently
self.unlockResult = .decoyVault
self.isUnlocked = true
return .decoyVault
}
// Check real PIN (Two-Factor authentication)
if TwoFactorManager.shared.validatePIN(pin) {
#if DEBUG
print("[AUTH] Real PIN validated - loading real vault")
#endif
self.unlockResult = .realVault
self.isUnlocked = true
return .realVault
}
// PIN validation failed
self.unlockResult = .failed
return .failed
}
enum UnlockResult {
case realVault // Load real photos (VaultPhoto models)
case decoyVault // Load innocent photos (DecoyPhoto models)
case failed // Authentication failed
}
HOW PANIC PIN WORKS
1. SETUP: User configures "Backup PIN" (labeled subtly in settings)
2. DECOY PHOTOS: User adds innocent photos to decoy vault (landscapes, pets, etc.)
3. COERCION SCENARIO: Adversary demands unlock
4. ENTER PANIC PIN: User enters backup PIN instead of real PIN
5. SILENT SWITCH: App loads decoy vault with innocent photos
6. ZERO INDICATORS: UI looks identical. Albums show empty. No visual difference.
RESULT: Adversary sees a boring vault. Real photos stay hidden. Plausible deniability maintained.
> DEAD_MANS_SWITCH
Skeleton Switch (Auto-Wipe)
@MainActor
class SkeletonSwitchManager: ObservableObject {
@Published var isEnabled: Bool = false
@Published var checkInInterval: TimeInterval = 604800 // 7 days default
/// Called when app launches - check if deadline exceeded
func appDidLaunch() -> Bool {
guard isEnabled else { return true }
let lastCheckIn = getLastCheckIn()
let elapsed = Date().timeIntervalSince(lastCheckIn)
// Deadline exceeded - nuke everything
if elapsed > checkInInterval {
#if DEBUG
print("[SKELETON] ☠️ Check-in deadline exceeded. Wiping vault.")
#endif
nukeEverything()
return false // Tell app to show "Vault Wiped" screen
}
return true
}
/// User successfully authenticated - reset timer
func checkIn() {
guard isEnabled else { return }
KeychainHelper.set(
Date().timeIntervalSince1970.description,
for: "com.nu11vlt.skeletonLastCheckIn"
)
#if DEBUG
print("[SKELETON] ✓ Check-in successful. Timer reset.")
#endif
}
/// The Nuclear Option ☢️
private func nukeEverything() {
// 1. Wipe encryption keys (makes photos unrecoverable)
VaultCrypto.shared.wipeAllKeys()
// 2. Delete all photo files from disk
VaultManager.shared.nukeFileSystem()
// 3. Wipe SwiftData database
// (handled by app showing VaultWipedView)
#if DEBUG
print("[SKELETON] ☢️ Vault nuked. No recovery possible.")
#endif
}
}
SKELETON SWITCH USE CASES
SCENARIO 1: BORDER CROSSING
Set 7-day timer before international travel. If detained beyond 7 days, vault auto-wipes.
SCENARIO 2: HIGH-RISK AREA
Set 24-hour timer in dangerous location. Must check in daily or photos destroyed.
SCENARIO 3: DEATH/CAPTURE
Set 30-day timer. If you die or are captured, vault wipes automatically.
SCENARIO 4: DURESS
Forced unlock situation? Stall for time. Timer expires → photos gone.
> THREAT_MODEL
What We Protect Against
PROTECTED
Photos encrypted at rest with ChaCha20. Unreadable without unlock.
Panic PIN loads decoy vault. Real photos stay hidden.
Skeleton Switch auto-wipes after missed check-in deadline.
No cloud storage. Photos never leave device.
Secure deletion with 3-pass overwrite (DoD 5220.22-M).
Screenshot detection auto-locks app immediately.
NOT PROTECTED
If adversary has physical access while device is unlocked.
Forced Face ID unlock (can't prevent physical coercion).
If device compromised with malware before Nu11VLT installed.
Unknown iOS vulnerabilities (applies to all iOS apps).
256-bit keys vulnerable to future quantum attacks (decades away).
REALISTIC EXPECTATIONS
Nu11VLT provides strong protection against most real-world threats: device seizure, coercion, cloud breaches, forensic analysis, and unauthorized access. However, no app can protect against all threats. If an adversary has you physically captive with unlimited time and resources, encryption alone won't save you. Use Nu11VLT as part of a broader security strategy, not as a magic bullet.
> SPECIFICATIONS
Technical Details
| Component | Implementation | Security Level |
|---|---|---|
| Encryption Algorithm | ChaCha20-Poly1305 AEAD | 256-bit keys |
| Key Storage | iOS Keychain (Secure Enclave) | Hardware-backed |
| File Protection | .completeFileProtection | iOS secure storage |
| PIN Hashing | SHA-256 | One-way hash |
| Backup Encryption | ChaCha20 + AES-256-GCM | Double encryption |
| Key Derivation | PBKDF2-SHA256 (100k iterations) | Brute-force resistant |
| Secure Deletion | DoD 5220.22-M (3-pass overwrite) | Forensic protection |
| Network Activity | None (100% offline) | Zero cloud exposure |
> CRYPTOGRAPHIC_PRIMITIVES
Battle-Tested Algorithms
CHACHA20-POLY1305
- • IETF Standard (RFC 8439)
- • Used by Signal, Google, Cloudflare
- • TLS 1.3 cipher suite
- • WireGuard VPN protocol
- • Faster than AES on ARM processors
IOS KEYCHAIN
- • Hardware-backed by Secure Enclave
- • FIPS 140-2 Level 3 certified
- • Keys protected by device passcode
- • Cannot be extracted via software
- • Survives jailbreak attempts
OPEN DESIGN
Nu11VLT's security relies on strong cryptography, not obscurity. We use industry-standard algorithms that have been peer-reviewed and battle-tested for decades. This page shows real implementation code to demonstrate our commitment to transparency. Security through obscurity is not security.
> END_OF_TRANSMISSION
Zero-knowledge. Zero-compromise.
← BACK TO NU11VLT