CONFIDENTIALITY: LEVEL 0 (PUBLIC)

TECHNICAL SPECIFICATIONS

Security through obscurity is not security.
We rely on mathematics, open standards, and hardware isolation.

~/nu11vlt/system_profile READ_ONLY
ComponentImplementationSpecification
Cipher ChaCha20-Poly1305 (IETF RFC 8439) 256-bit Key, AEAD
Key Storage iOS Secure Enclave (Keychain API) Hardware Backed, On-Device Only
PIN Hashing Argon2id (libsodium) Memory-Hard KDF, Interactive Params
Secure Deletion NIST 800-88 Rev. 1 Single-Pass Random Overwrite (Pro)
Backup Encryption AES-256-GCM (Argon2id derived key) Password-Derived Key, Moderate Params
Network Access NULL (Air-Gapped) Zero Network Permissions
Cloud Sync NULL (Disabled) iCloud Backup Excluded
Analytics NULL (No Telemetry) Zero Data Collection
./VaultCrypto.swift CHACHA20
import CryptoKit

// Encrypt data with AEAD
func encrypt(data: Data, key: SymmetricKey) throws -> Data {
	// Generates random nonce internally
	let sealedBox = try ChaChaPoly.seal(
		data, 
		using: key
	)
	
	// Returns: Nonce + Ciphertext + Tag
	return sealedBox.combined
}

// 256-bit key never leaves Secure Enclave
let key = SymmetricKey(size: .bits256)
./SkeletonSwitch.swift AUTO_WIPE
// Dead Man's Switch: Irreversible Wipe
func nukeFileSystem() {
	let secureWipe = UserDefaults
		.standard
		.bool(forKey: "secureWipeEnabled")
	
	if secureWipe {
		// NIST 800-88 (single-pass random)
		secureWipeDirectory(vaultURL)
	} else {
		// Fast wipe (instant)
		FileManager.removeItem(vaultURL)
	}
	
	// Destroy keys (cryptographic erasure)
	Keychain.delete("vaultKey")
}
./Password Hashing: Argon2id MEMORY-HARD KDF

Nu11VLT uses Argon2id via libsodium for all password and PIN hashing. Argon2id is the winner of the Password Hashing Competition (2015) and is specifically designed to resist GPU/ASIC cracking attacks.

Why Argon2id?

  • Memory-hard algorithm (forces attackers to use expensive RAM)
  • Resistant to GPU/ASIC/FPGA cracking farms
  • Recommended by OWASP, Signal, 1Password, Bitwarden
  • Configurable parameters for different use cases
// PIN hashing with interactive parameters (fast)
func hashPIN(_ pin: String) -> String? {
	guard let pinData = pin.data(using: .utf8) else { return nil }
	
	let sodium = Sodium()
	return sodium.pwHash.str(
		passwd: Bytes(pinData),
		opsLimit: sodium.pwHash.OpsLimitInteractive,
		memLimit: sodium.pwHash.MemLimitInteractive
	)
}

// Archive password hashing with moderate parameters (stronger)
func deriveArchiveKey(password: String, salt: Data) -> SymmetricKey? {
	guard let passwordData = password.data(using: .utf8) else { return nil }
	
	let sodium = Sodium()
	guard let keyBytes = sodium.pwHash.hash(
		outputLength: 32,
		passwd: Bytes(passwordData),
		salt: Bytes(salt),
		opsLimit: sodium.pwHash.OpsLimitModerate,
		memLimit: sodium.pwHash.MemLimitModerate,
		alg: .argon2id13
	) else { return nil }
	
	return SymmetricKey(data: Data(keyBytes))
}

Argon2id stores the salt, algorithm, and parameters in a PHC string format. No separate salt storage needed for PINs.

./Secure Deletion: NIST 800-88 Rev. 1 FORENSIC PROTECTION

Nu11VLT implements NIST 800-88 Rev. 1 "Clear/Purge" standard for secure file deletion on modern SSDs. This Pro feature performs a single-pass random data overwrite before deletion.

Why Single-Pass?

Modern SSDs use wear-leveling and internal remapping. Multi-pass overwrites (like DoD 5220.22-M) were designed for magnetic hard drives and provide no additional security on flash storage. NIST 800-88 Rev. 1 recommends:

  • Clear: Logical overwrite (single pass) - Sufficient for SSDs
  • Purge: Cryptographic erasure (key destruction) - Our primary method
  • Destroy: Physical destruction - Not applicable to apps
// NIST 800-88 Single-Pass Random Overwrite
func secureWipeFile(at url: URL) {
	guard FileManager.default.fileExists(atPath: url.path) else { return }
	
	do {
		let attributes = try FileManager.default.attributesOfItem(atPath: url.path)
		guard let fileSize = attributes[.size] as? UInt64, fileSize > 0 else {
			try FileManager.default.removeItem(at: url)
			return
		}
		
		let fileHandle = try FileHandle(forWritingTo: url)
		defer { try? fileHandle.close() }
		
		// Single-pass cryptographically secure random overwrite
		var randomData = Data(count: Int(fileSize))
		_ = randomData.withUnsafeMutableBytes { 
			SecRandomCopyBytes(kSecRandomDefault, Int(fileSize), $0.baseAddress!) 
		}
		
		try fileHandle.seek(toOffset: 0)
		fileHandle.write(randomData)
		fileHandle.synchronizeFile()
		
		// Finally delete the file
		try FileManager.default.removeItem(at: url)
	} catch {
		// Fallback to standard deletion
		try? FileManager.default.removeItem(at: url)
	}
}

Optional Pro feature. Slower and more battery-intensive than standard deletion. Primary security comes from cryptographic erasure (key destruction).

THREAT MODEL ASSESSMENT

// PROTECTED AGAINST

Device Seizure

Data encrypted at rest with ChaCha20-Poly1305. Mathematically unreadable without Face ID/PIN. Keys stored in Secure Enclave (hardware isolated).

Coerced Unlock (Border Crossings)

Backup PIN loads alternative vault with innocent photos. Zero visual indicators. Indistinguishable from primary vault.

Cloud Data Breach

Impossible. App has zero network code. No cloud sync. No servers. Data never transmitted.

Forensic Data Recovery

Primary defense: Cryptographic erasure (key destruction). Optional: NIST 800-88 single-pass random overwrite for additional protection against forensic tools.

Extended Detention

Skeleton Switch (dead man's switch) auto-wipes vault if device not unlocked within 7/14/30/60 days. Optional NIST 800-88 secure wipe.

Password Cracking

Argon2id memory-hard hashing resists GPU/ASIC farms. Even weak PINs have significant protection against brute force.

// NOT PROTECTED AGAINST

Physical Access While Unlocked

If device is snatched while vault is open, decrypted data is visible in RAM. Mitigate by using Face ID authentication on app launch.

Compromised iOS (Zero-Day Exploits)

If iOS itself has kernel-level exploit, memory hooks could theoretically read decryption keys. Keep iOS updated.

Jailbroken Devices

Jailbreaking compromises iOS security model. Keychain access can be bypassed. Do not use Nu11VLT on jailbroken devices.

Weak User Passwords (Backup Files)

Encrypted backup files (.nu11vlt) are protected by Argon2id, but still only as strong as the user's password. Use 16+ character passwords with high entropy.

State-Level Adversaries with Zero-Days

Nation-state actors with iOS zero-day exploits may bypass security. No app can protect against unknown vulnerabilities in the OS.

./Key Management & Secure Enclave HARDWARE ISOLATION

Nu11VLT stores encryption keys in iOS Keychain with kSecAttrAccessibleWhenUnlockedThisDeviceOnly attribute. This ensures keys are:

  • Hardware-backed (stored in Secure Enclave, not software)
  • Only accessible when device is unlocked
  • Never backed up to iCloud
  • Never transferred to other devices
  • Destroyed if device is reset or app is deleted
// Key storage with maximum security
let query: [String: Any] = [
	kSecClass: kSecClassGenericPassword,
	kSecAttrAccount: "vaultKey",
	kSecValueData: keyData,
	kSecAttrAccessible: kSecAttrAccessibleWhenUnlockedThisDeviceOnly
]

SecItemAdd(query as CFDictionary, nil)
~/nu11vlt/repository DOCUMENTATION

Dive Deeper

Explore detailed documentation on GitHub including architecture diagrams, threat model analysis, and implementation guides.

GitHub Repository