883 lines
26 KiB
Markdown
883 lines
26 KiB
Markdown
|
|
# Keys for All - Key Generation & Validation System
|
||
|
|
|
||
|
|
## System Architecture Overview
|
||
|
|
|
||
|
|
The VoiceUwu key system is designed with security, scalability, and user privacy as core principles. It uses a hybrid approach combining cryptographic validation with clever encoding techniques.
|
||
|
|
|
||
|
|
```
|
||
|
|
┌─────────────────────────────────────────────────────────┐
|
||
|
|
│ Key Generation │
|
||
|
|
│ (Server-Side) │
|
||
|
|
├─────────────────────────────────────────────────────────┤
|
||
|
|
│ Random Generator → Format Builder → Checksum Embedder │
|
||
|
|
│ ↓ ↓ ↓ │
|
||
|
|
│ Entropy Pool Structure Rules Crypto Algorithm │
|
||
|
|
└─────────────────────────────────────────────────────────┘
|
||
|
|
↓
|
||
|
|
┌─────────────────────────────────────────────────────────┐
|
||
|
|
│ Key Distribution │
|
||
|
|
├─────────────────────────────────────────────────────────┤
|
||
|
|
│ App Store → Key Delivery → User Activation → Storage │
|
||
|
|
└─────────────────────────────────────────────────────────┘
|
||
|
|
↓
|
||
|
|
┌─────────────────────────────────────────────────────────┐
|
||
|
|
│ Key Validation │
|
||
|
|
│ (Client-Side) │
|
||
|
|
├─────────────────────────────────────────────────────────┤
|
||
|
|
│ Format Check → Checksum Verify → Level Extract → Store │
|
||
|
|
└─────────────────────────────────────────────────────────┘
|
||
|
|
```
|
||
|
|
|
||
|
|
## Key Format Specification
|
||
|
|
|
||
|
|
### Structure
|
||
|
|
```
|
||
|
|
VUUW-XXXX-XXXX-XXXX-LN
|
||
|
|
│ │ │ │ │
|
||
|
|
│ │ │ │ └─ License Level (L1 or L2)
|
||
|
|
│ │ │ └────── Segment 3 (4 chars)
|
||
|
|
│ │ └─────────── Segment 2 (4 chars)
|
||
|
|
│ └──────────────── Segment 1 (4 chars)
|
||
|
|
└───────────────────── Product Identifier (always VUUW)
|
||
|
|
```
|
||
|
|
|
||
|
|
### Character Set
|
||
|
|
- **Allowed Characters**: `ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789`
|
||
|
|
- **Excluded Characters**: `O, 0, I, 1` (to avoid confusion)
|
||
|
|
- **Effective Character Set**: 32 characters
|
||
|
|
- **Total Possible Combinations**: 32^12 = ~1.15 x 10^18
|
||
|
|
|
||
|
|
### Checksum Embedding
|
||
|
|
|
||
|
|
The checksum is not appended but cleverly embedded within the key segments using a proprietary algorithm:
|
||
|
|
|
||
|
|
```swift
|
||
|
|
// Conceptual representation (actual implementation is obfuscated)
|
||
|
|
struct ChecksumEmbedder {
|
||
|
|
private let prime1 = 31
|
||
|
|
private let prime2 = 37
|
||
|
|
private let prime3 = 41
|
||
|
|
|
||
|
|
func embed(segments: [String], checksum: UInt32) -> [String] {
|
||
|
|
var result = segments
|
||
|
|
|
||
|
|
// Distribute checksum bits across segments
|
||
|
|
let bits = checksumToBits(checksum)
|
||
|
|
|
||
|
|
for (index, segment) in segments.enumerated() where index > 0 {
|
||
|
|
let modifiedSegment = embedBitsInSegment(
|
||
|
|
segment: segment,
|
||
|
|
bits: bits.subset(for: index),
|
||
|
|
position: calculatePosition(index)
|
||
|
|
)
|
||
|
|
result[index] = modifiedSegment
|
||
|
|
}
|
||
|
|
|
||
|
|
return result
|
||
|
|
}
|
||
|
|
|
||
|
|
private func calculatePosition(_ index: Int) -> Int {
|
||
|
|
// Use prime numbers for better distribution
|
||
|
|
return (index * prime1) % 4
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## Generation Algorithm
|
||
|
|
|
||
|
|
### Server-Side Key Generation
|
||
|
|
|
||
|
|
```swift
|
||
|
|
// Runs on secure server, not in client app
|
||
|
|
class KeyGenerationService {
|
||
|
|
private let entropyPool = EntropyPool()
|
||
|
|
private let database = KeyDatabase()
|
||
|
|
|
||
|
|
struct GenerationRequest {
|
||
|
|
let level: LicenseLevel
|
||
|
|
let quantity: Int
|
||
|
|
let purchaseID: String
|
||
|
|
let metadata: PurchaseMetadata
|
||
|
|
}
|
||
|
|
|
||
|
|
func generateKeys(_ request: GenerationRequest) async throws -> [String] {
|
||
|
|
var keys: [String] = []
|
||
|
|
|
||
|
|
for _ in 0..<request.quantity {
|
||
|
|
var attempts = 0
|
||
|
|
var key: String
|
||
|
|
|
||
|
|
// Ensure uniqueness with retry logic
|
||
|
|
repeat {
|
||
|
|
key = try generateSingleKey(level: request.level)
|
||
|
|
attempts += 1
|
||
|
|
|
||
|
|
if attempts > 10 {
|
||
|
|
throw KeyGenerationError.tooManyCollisions
|
||
|
|
}
|
||
|
|
} while try await database.exists(key)
|
||
|
|
|
||
|
|
// Store key with metadata
|
||
|
|
try await database.store(
|
||
|
|
key: key,
|
||
|
|
purchaseID: request.purchaseID,
|
||
|
|
metadata: request.metadata
|
||
|
|
)
|
||
|
|
|
||
|
|
keys.append(key)
|
||
|
|
}
|
||
|
|
|
||
|
|
return keys
|
||
|
|
}
|
||
|
|
|
||
|
|
private func generateSingleKey(level: LicenseLevel) throws -> String {
|
||
|
|
// Step 1: Generate random segments
|
||
|
|
let segment1 = generateSegment()
|
||
|
|
let segment2 = generateSegment()
|
||
|
|
let segment3 = generateSegment()
|
||
|
|
|
||
|
|
// Step 2: Create base key
|
||
|
|
let baseKey = "VUUW-\(segment1)-\(segment2)-\(segment3)"
|
||
|
|
|
||
|
|
// Step 3: Calculate checksum
|
||
|
|
let checksum = calculateChecksum(baseKey, level: level)
|
||
|
|
|
||
|
|
// Step 4: Embed checksum in segments
|
||
|
|
let modifiedSegments = embedChecksum(
|
||
|
|
segments: [segment1, segment2, segment3],
|
||
|
|
checksum: checksum
|
||
|
|
)
|
||
|
|
|
||
|
|
// Step 5: Construct final key
|
||
|
|
let finalKey = "VUUW-\(modifiedSegments.joined(separator: "-"))-\(level.rawValue)"
|
||
|
|
|
||
|
|
return finalKey
|
||
|
|
}
|
||
|
|
|
||
|
|
private func generateSegment() -> String {
|
||
|
|
let chars = "ABCDEFGHJKLMNPQRSTUVWXYZ23456789" // No O,0,I,1
|
||
|
|
return String((0..<4).map { _ in
|
||
|
|
chars.randomElement()!
|
||
|
|
})
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Checksum Calculation
|
||
|
|
|
||
|
|
```swift
|
||
|
|
struct ChecksumCalculator {
|
||
|
|
private let salt = Data("VoiceUwU2024KeyGen!@#$%".utf8)
|
||
|
|
|
||
|
|
func calculate(_ baseKey: String, level: LicenseLevel) -> UInt32 {
|
||
|
|
// Combine key components
|
||
|
|
let combined = baseKey + level.rawValue
|
||
|
|
let data = Data(combined.utf8)
|
||
|
|
|
||
|
|
// Add salt for security
|
||
|
|
var hasher = SHA256()
|
||
|
|
hasher.update(data)
|
||
|
|
hasher.update(salt)
|
||
|
|
|
||
|
|
// Generate hash
|
||
|
|
let hash = hasher.finalize()
|
||
|
|
|
||
|
|
// Convert to UInt32 checksum
|
||
|
|
let checksum = hash.withUnsafeBytes { bytes in
|
||
|
|
bytes.bindMemory(to: UInt32.self).first ?? 0
|
||
|
|
}
|
||
|
|
|
||
|
|
return checksum
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Entropy Pool Management
|
||
|
|
|
||
|
|
```swift
|
||
|
|
class EntropyPool {
|
||
|
|
private var pool: [UInt8] = []
|
||
|
|
private let minPoolSize = 1024
|
||
|
|
private let source = SystemRandomNumberGenerator()
|
||
|
|
private let queue = DispatchQueue(label: "entropy.pool", attributes: .concurrent)
|
||
|
|
|
||
|
|
init() {
|
||
|
|
refillPool()
|
||
|
|
|
||
|
|
// Periodic refill
|
||
|
|
Timer.scheduledTimer(withTimeInterval: 60, repeats: true) { _ in
|
||
|
|
self.refillPoolIfNeeded()
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
func getBytes(_ count: Int) -> [UInt8] {
|
||
|
|
queue.sync {
|
||
|
|
// Ensure pool has enough entropy
|
||
|
|
while pool.count < count {
|
||
|
|
refillPool()
|
||
|
|
}
|
||
|
|
|
||
|
|
// Extract bytes
|
||
|
|
let bytes = Array(pool.prefix(count))
|
||
|
|
pool.removeFirst(count)
|
||
|
|
|
||
|
|
// Async refill if needed
|
||
|
|
if pool.count < minPoolSize {
|
||
|
|
queue.async(flags: .barrier) {
|
||
|
|
self.refillPool()
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return bytes
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
private func refillPool() {
|
||
|
|
// Add system entropy
|
||
|
|
for _ in 0..<1024 {
|
||
|
|
pool.append(UInt8.random(in: 0...255))
|
||
|
|
}
|
||
|
|
|
||
|
|
// Add time-based entropy
|
||
|
|
let timestamp = UInt64(Date().timeIntervalSince1970 * 1_000_000)
|
||
|
|
withUnsafeBytes(of: timestamp) { bytes in
|
||
|
|
pool.append(contentsOf: bytes)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Shuffle pool
|
||
|
|
pool.shuffle()
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## Validation Algorithm
|
||
|
|
|
||
|
|
### Client-Side Validation
|
||
|
|
|
||
|
|
```swift
|
||
|
|
class KeyValidator {
|
||
|
|
private let checksumVerifier = ChecksumVerifier()
|
||
|
|
|
||
|
|
struct ValidationResult {
|
||
|
|
let isValid: Bool
|
||
|
|
let level: LicenseLevel?
|
||
|
|
let error: ValidationError?
|
||
|
|
}
|
||
|
|
|
||
|
|
enum ValidationError: Error {
|
||
|
|
case invalidFormat
|
||
|
|
case checksumMismatch
|
||
|
|
case invalidLevel
|
||
|
|
case suspiciousPattern
|
||
|
|
}
|
||
|
|
|
||
|
|
func validate(_ key: String) -> ValidationResult {
|
||
|
|
// Step 1: Format validation
|
||
|
|
let pattern = #"^VUUW-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}-L[12]$"#
|
||
|
|
guard key.range(of: pattern, options: .regularExpression) != nil else {
|
||
|
|
return ValidationResult(isValid: false, level: nil, error: .invalidFormat)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Step 2: Extract components
|
||
|
|
let components = key.split(separator: "-").map(String.init)
|
||
|
|
let segments = Array(components[1...3])
|
||
|
|
let levelString = components[4]
|
||
|
|
|
||
|
|
// Step 3: Validate level
|
||
|
|
guard let level = LicenseLevel(rawValue: levelString) else {
|
||
|
|
return ValidationResult(isValid: false, level: nil, error: .invalidLevel)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Step 4: Check for suspicious patterns
|
||
|
|
if hasSuspiciousPattern(segments) {
|
||
|
|
return ValidationResult(isValid: false, level: nil, error: .suspiciousPattern)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Step 5: Verify checksum
|
||
|
|
let baseKey = components[0...3].joined(separator: "-")
|
||
|
|
let isValid = checksumVerifier.verify(
|
||
|
|
baseKey: baseKey,
|
||
|
|
segments: segments,
|
||
|
|
level: level
|
||
|
|
)
|
||
|
|
|
||
|
|
if !isValid {
|
||
|
|
return ValidationResult(isValid: false, level: nil, error: .checksumMismatch)
|
||
|
|
}
|
||
|
|
|
||
|
|
return ValidationResult(isValid: true, level: level, error: nil)
|
||
|
|
}
|
||
|
|
|
||
|
|
private func hasSuspiciousPattern(_ segments: [String]) -> Bool {
|
||
|
|
// Check for obviously fake patterns
|
||
|
|
let patterns = [
|
||
|
|
"AAAA", "1111", "1234", "ABCD",
|
||
|
|
"0000", "XXXX", "TEST", "DEMO"
|
||
|
|
]
|
||
|
|
|
||
|
|
for segment in segments {
|
||
|
|
if patterns.contains(segment) {
|
||
|
|
return true
|
||
|
|
}
|
||
|
|
|
||
|
|
// Check if all characters are the same
|
||
|
|
if Set(segment).count == 1 {
|
||
|
|
return true
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return false
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Checksum Verification
|
||
|
|
|
||
|
|
```swift
|
||
|
|
struct ChecksumVerifier {
|
||
|
|
private let calculator = ChecksumCalculator()
|
||
|
|
|
||
|
|
func verify(baseKey: String, segments: [String], level: LicenseLevel) -> Bool {
|
||
|
|
// Calculate expected checksum
|
||
|
|
let expectedChecksum = calculator.calculate(baseKey, level: level)
|
||
|
|
|
||
|
|
// Extract embedded checksum from segments
|
||
|
|
let extractedChecksum = extractChecksum(from: segments)
|
||
|
|
|
||
|
|
// Constant-time comparison to prevent timing attacks
|
||
|
|
return constantTimeCompare(expectedChecksum, extractedChecksum)
|
||
|
|
}
|
||
|
|
|
||
|
|
private func extractChecksum(from segments: [String]) -> UInt32 {
|
||
|
|
var checksum: UInt32 = 0
|
||
|
|
|
||
|
|
for (index, segment) in segments.enumerated() {
|
||
|
|
let position = calculateExtractionPosition(index)
|
||
|
|
let char = segment[segment.index(segment.startIndex, offsetBy: position)]
|
||
|
|
|
||
|
|
// Extract bits from character
|
||
|
|
let bits = extractBitsFromChar(char)
|
||
|
|
checksum |= (bits << (index * 8))
|
||
|
|
}
|
||
|
|
|
||
|
|
return checksum
|
||
|
|
}
|
||
|
|
|
||
|
|
private func constantTimeCompare(_ a: UInt32, _ b: UInt32) -> Bool {
|
||
|
|
// Prevent timing attacks by always taking the same time
|
||
|
|
var result: UInt32 = 0
|
||
|
|
|
||
|
|
for i in 0..<4 {
|
||
|
|
let aByte = UInt8((a >> (i * 8)) & 0xFF)
|
||
|
|
let bByte = UInt8((b >> (i * 8)) & 0xFF)
|
||
|
|
result |= UInt32(aByte ^ bByte)
|
||
|
|
}
|
||
|
|
|
||
|
|
return result == 0
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## Security Measures
|
||
|
|
|
||
|
|
### Anti-Piracy Protection
|
||
|
|
|
||
|
|
```swift
|
||
|
|
class AntiPiracySystem {
|
||
|
|
private let obfuscator = CodeObfuscator()
|
||
|
|
private let integrityChecker = BinaryIntegrityChecker()
|
||
|
|
|
||
|
|
func protectValidationLogic() {
|
||
|
|
// Obfuscate critical validation functions
|
||
|
|
obfuscator.obfuscate([
|
||
|
|
"validate",
|
||
|
|
"calculateChecksum",
|
||
|
|
"extractChecksum",
|
||
|
|
"verifyEmbeddedChecksum"
|
||
|
|
])
|
||
|
|
|
||
|
|
// Add integrity checks
|
||
|
|
integrityChecker.addCheck(for: KeyValidator.self)
|
||
|
|
integrityChecker.addCheck(for: ChecksumCalculator.self)
|
||
|
|
|
||
|
|
// Runtime protection
|
||
|
|
setupRuntimeProtection()
|
||
|
|
}
|
||
|
|
|
||
|
|
private func setupRuntimeProtection() {
|
||
|
|
// Detect debugger
|
||
|
|
if isDebuggerAttached() {
|
||
|
|
// Subtly fail validation
|
||
|
|
corruptValidationLogic()
|
||
|
|
}
|
||
|
|
|
||
|
|
// Detect jailbreak
|
||
|
|
if isJailbroken() {
|
||
|
|
// Add random delays
|
||
|
|
addValidationDelays()
|
||
|
|
}
|
||
|
|
|
||
|
|
// Check binary signature
|
||
|
|
if !isBinarySignatureValid() {
|
||
|
|
// Return random validation results
|
||
|
|
enableRandomMode()
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Key Rotation Strategy
|
||
|
|
|
||
|
|
```swift
|
||
|
|
class KeyRotationManager {
|
||
|
|
private var currentAlgorithmVersion = 1
|
||
|
|
private let algorithms: [Int: KeyAlgorithm] = [
|
||
|
|
1: KeyAlgorithmV1(),
|
||
|
|
2: KeyAlgorithmV2() // Ready for future rotation
|
||
|
|
]
|
||
|
|
|
||
|
|
func validateWithRotation(_ key: String) -> Bool {
|
||
|
|
// Try current algorithm first
|
||
|
|
if let currentAlgo = algorithms[currentAlgorithmVersion] {
|
||
|
|
if currentAlgo.validate(key) {
|
||
|
|
return true
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Try previous algorithms for backward compatibility
|
||
|
|
for version in (1..<currentAlgorithmVersion).reversed() {
|
||
|
|
if let algo = algorithms[version], algo.validate(key) {
|
||
|
|
// Migrate to new format if needed
|
||
|
|
migrateKey(key, fromVersion: version)
|
||
|
|
return true
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return false
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## Storage Security
|
||
|
|
|
||
|
|
### Secure Key Storage
|
||
|
|
|
||
|
|
```swift
|
||
|
|
class SecureKeyStorage {
|
||
|
|
private let keychain = KeychainServices()
|
||
|
|
private let encryption = AES256Encryption()
|
||
|
|
|
||
|
|
private let serviceIdentifier = "com.voiceuwu.keys"
|
||
|
|
private let accessGroup = "group.voiceuwu.shared"
|
||
|
|
|
||
|
|
func storeKey(_ key: String, level: LicenseLevel) throws {
|
||
|
|
// Generate unique identifier
|
||
|
|
let identifier = generateIdentifier(for: key)
|
||
|
|
|
||
|
|
// Encrypt key data
|
||
|
|
let keyData = KeyData(
|
||
|
|
key: key,
|
||
|
|
level: level,
|
||
|
|
activatedDate: Date(),
|
||
|
|
deviceID: getDeviceIdentifier()
|
||
|
|
)
|
||
|
|
|
||
|
|
let encrypted = try encryption.encrypt(keyData)
|
||
|
|
|
||
|
|
// Store in keychain with maximum security
|
||
|
|
let query: [String: Any] = [
|
||
|
|
kSecClass as String: kSecClassGenericPassword,
|
||
|
|
kSecAttrService as String: serviceIdentifier,
|
||
|
|
kSecAttrAccount as String: identifier,
|
||
|
|
kSecAttrAccessGroup as String: accessGroup,
|
||
|
|
kSecValueData as String: encrypted,
|
||
|
|
kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
|
||
|
|
kSecAttrSynchronizable as String: false
|
||
|
|
]
|
||
|
|
|
||
|
|
let status = SecItemAdd(query as CFDictionary, nil)
|
||
|
|
guard status == errSecSuccess else {
|
||
|
|
throw KeychainError.storeFailed(status)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Store metadata separately
|
||
|
|
storeMetadata(for: identifier, level: level)
|
||
|
|
}
|
||
|
|
|
||
|
|
private func generateIdentifier(for key: String) -> String {
|
||
|
|
// Use SHA256 to create consistent identifier
|
||
|
|
let data = Data(key.utf8)
|
||
|
|
let hash = SHA256.hash(data: data)
|
||
|
|
return hash.compactMap { String(format: "%02x", $0) }.joined()
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Backup and Recovery
|
||
|
|
|
||
|
|
```swift
|
||
|
|
class KeyBackupManager {
|
||
|
|
private let cloudKit = CKContainer.default()
|
||
|
|
|
||
|
|
func backupKey(_ key: String) async throws {
|
||
|
|
// Never store actual key in cloud
|
||
|
|
let backup = KeyBackup(
|
||
|
|
keyHash: hashKey(key),
|
||
|
|
activatedDate: Date(),
|
||
|
|
deviceName: getCurrentDeviceName(),
|
||
|
|
backupDate: Date()
|
||
|
|
)
|
||
|
|
|
||
|
|
// Encrypt backup data
|
||
|
|
let encrypted = try encryptBackup(backup)
|
||
|
|
|
||
|
|
// Store in private CloudKit database
|
||
|
|
let record = CKRecord(recordType: "KeyBackup")
|
||
|
|
record["data"] = encrypted
|
||
|
|
record["deviceID"] = getDeviceIdentifier()
|
||
|
|
|
||
|
|
try await cloudKit.privateCloudDatabase.save(record)
|
||
|
|
}
|
||
|
|
|
||
|
|
func recoverKeys() async throws -> [RecoveryHint] {
|
||
|
|
// Fetch backup records
|
||
|
|
let predicate = NSPredicate(value: true)
|
||
|
|
let query = CKQuery(recordType: "KeyBackup", predicate: predicate)
|
||
|
|
|
||
|
|
let results = try await cloudKit.privateCloudDatabase.records(matching: query)
|
||
|
|
|
||
|
|
// Decrypt and process
|
||
|
|
var hints: [RecoveryHint] = []
|
||
|
|
|
||
|
|
for case let (_, result) in results.matchResults {
|
||
|
|
if case .success(let record) = result,
|
||
|
|
let encryptedData = record["data"] as? Data {
|
||
|
|
|
||
|
|
let backup = try decryptBackup(encryptedData)
|
||
|
|
hints.append(RecoveryHint(
|
||
|
|
partialKey: "VUUW-****-****-****-\(backup.level)",
|
||
|
|
activatedDate: backup.activatedDate,
|
||
|
|
deviceName: backup.deviceName
|
||
|
|
))
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return hints
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## Bulk Key Management
|
||
|
|
|
||
|
|
### Bulk Generation
|
||
|
|
|
||
|
|
```swift
|
||
|
|
class BulkKeyGenerator {
|
||
|
|
private let batchSize = 100
|
||
|
|
private let concurrency = 4
|
||
|
|
|
||
|
|
struct BulkGenerationRequest {
|
||
|
|
let quantity: Int
|
||
|
|
let level: LicenseLevel
|
||
|
|
let organization: String?
|
||
|
|
let validUntil: Date?
|
||
|
|
}
|
||
|
|
|
||
|
|
func generateBulk(_ request: BulkGenerationRequest) async throws -> BulkKeyPackage {
|
||
|
|
let batches = stride(from: 0, to: request.quantity, by: batchSize).map { start in
|
||
|
|
min(batchSize, request.quantity - start)
|
||
|
|
}
|
||
|
|
|
||
|
|
// Generate keys in parallel batches
|
||
|
|
let keyBatches = try await withThrowingTaskGroup(of: [String].self) { group in
|
||
|
|
for batchSize in batches {
|
||
|
|
group.addTask {
|
||
|
|
try await self.generateBatch(
|
||
|
|
size: batchSize,
|
||
|
|
level: request.level
|
||
|
|
)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
var allKeys: [String] = []
|
||
|
|
for try await batch in group {
|
||
|
|
allKeys.append(contentsOf: batch)
|
||
|
|
}
|
||
|
|
|
||
|
|
return allKeys
|
||
|
|
}
|
||
|
|
|
||
|
|
// Create distribution package
|
||
|
|
let package = BulkKeyPackage(
|
||
|
|
keys: keyBatches.flatMap { $0 },
|
||
|
|
level: request.level,
|
||
|
|
generatedDate: Date(),
|
||
|
|
organization: request.organization,
|
||
|
|
validUntil: request.validUntil
|
||
|
|
)
|
||
|
|
|
||
|
|
// Store package metadata
|
||
|
|
try await storeBulkPackage(package)
|
||
|
|
|
||
|
|
return package
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Distribution Tracking
|
||
|
|
|
||
|
|
```swift
|
||
|
|
class KeyDistributionTracker {
|
||
|
|
private let database = DistributionDatabase()
|
||
|
|
|
||
|
|
struct DistributionRecord {
|
||
|
|
let keyHash: String
|
||
|
|
let distributedTo: String?
|
||
|
|
let distributionMethod: DistributionMethod
|
||
|
|
let timestamp: Date
|
||
|
|
let activated: Bool
|
||
|
|
}
|
||
|
|
|
||
|
|
enum DistributionMethod {
|
||
|
|
case direct
|
||
|
|
case email
|
||
|
|
case qrCode
|
||
|
|
case bulkCSV
|
||
|
|
case api
|
||
|
|
}
|
||
|
|
|
||
|
|
func trackDistribution(
|
||
|
|
key: String,
|
||
|
|
to recipient: String?,
|
||
|
|
method: DistributionMethod
|
||
|
|
) async throws {
|
||
|
|
let record = DistributionRecord(
|
||
|
|
keyHash: hashKey(key),
|
||
|
|
distributedTo: recipient,
|
||
|
|
distributionMethod: method,
|
||
|
|
timestamp: Date(),
|
||
|
|
activated: false
|
||
|
|
)
|
||
|
|
|
||
|
|
try await database.store(record)
|
||
|
|
}
|
||
|
|
|
||
|
|
func getDistributionAnalytics() async throws -> DistributionAnalytics {
|
||
|
|
let records = try await database.fetchAll()
|
||
|
|
|
||
|
|
return DistributionAnalytics(
|
||
|
|
totalDistributed: records.count,
|
||
|
|
activationRate: calculateActivationRate(records),
|
||
|
|
methodBreakdown: analyzeByMethod(records),
|
||
|
|
timeToActivation: calculateAverageActivationTime(records)
|
||
|
|
)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## Performance Optimization
|
||
|
|
|
||
|
|
### Validation Caching
|
||
|
|
|
||
|
|
```swift
|
||
|
|
actor ValidationCache {
|
||
|
|
private var cache: LRUCache<String, ValidationResult> = LRUCache(capacity: 1000)
|
||
|
|
private var validationStats = ValidationStats()
|
||
|
|
|
||
|
|
func validate(_ key: String) async -> ValidationResult {
|
||
|
|
// Check cache first
|
||
|
|
if let cached = cache.get(key) {
|
||
|
|
validationStats.cacheHits += 1
|
||
|
|
return cached
|
||
|
|
}
|
||
|
|
|
||
|
|
validationStats.cacheMisses += 1
|
||
|
|
|
||
|
|
// Perform validation
|
||
|
|
let result = KeyValidator().validate(key)
|
||
|
|
|
||
|
|
// Cache result
|
||
|
|
cache.set(key, value: result)
|
||
|
|
|
||
|
|
return result
|
||
|
|
}
|
||
|
|
|
||
|
|
func getCacheStats() -> ValidationStats {
|
||
|
|
return validationStats
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
struct LRUCache<Key: Hashable, Value> {
|
||
|
|
private let capacity: Int
|
||
|
|
private var cache: [Key: Value] = [:]
|
||
|
|
private var order: [Key] = []
|
||
|
|
|
||
|
|
mutating func get(_ key: Key) -> Value? {
|
||
|
|
guard let value = cache[key] else { return nil }
|
||
|
|
|
||
|
|
// Move to end (most recently used)
|
||
|
|
order.removeAll { $0 == key }
|
||
|
|
order.append(key)
|
||
|
|
|
||
|
|
return value
|
||
|
|
}
|
||
|
|
|
||
|
|
mutating func set(_ key: Key, value: Value) {
|
||
|
|
// Remove oldest if at capacity
|
||
|
|
if cache.count >= capacity && cache[key] == nil {
|
||
|
|
if let oldest = order.first {
|
||
|
|
cache.removeValue(forKey: oldest)
|
||
|
|
order.removeFirst()
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
cache[key] = value
|
||
|
|
order.removeAll { $0 == key }
|
||
|
|
order.append(key)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## Testing and Quality Assurance
|
||
|
|
|
||
|
|
### Comprehensive Test Suite
|
||
|
|
|
||
|
|
```swift
|
||
|
|
class KeySystemTests: XCTestCase {
|
||
|
|
let generator = KeyGenerationService()
|
||
|
|
let validator = KeyValidator()
|
||
|
|
|
||
|
|
func testKeyUniqueness() async throws {
|
||
|
|
// Generate large batch
|
||
|
|
let keys = try await generator.generateKeys(
|
||
|
|
GenerationRequest(
|
||
|
|
level: .level1,
|
||
|
|
quantity: 10000,
|
||
|
|
purchaseID: "test",
|
||
|
|
metadata: .init()
|
||
|
|
)
|
||
|
|
)
|
||
|
|
|
||
|
|
// Check uniqueness
|
||
|
|
let uniqueKeys = Set(keys)
|
||
|
|
XCTAssertEqual(keys.count, uniqueKeys.count)
|
||
|
|
}
|
||
|
|
|
||
|
|
func testValidationPerformance() throws {
|
||
|
|
let key = "VUUW-AB2C-D3EF-G4HJ-L1"
|
||
|
|
|
||
|
|
measure {
|
||
|
|
for _ in 0..<10000 {
|
||
|
|
_ = validator.validate(key)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Should complete 10k validations in < 1 second
|
||
|
|
}
|
||
|
|
|
||
|
|
func testChecksumSecurity() throws {
|
||
|
|
let validKey = "VUUW-AB2C-D3EF-G4HJ-L1"
|
||
|
|
|
||
|
|
// Try all single-character modifications
|
||
|
|
for i in 0..<validKey.count {
|
||
|
|
var modifiedKey = Array(validKey)
|
||
|
|
if modifiedKey[i].isLetter {
|
||
|
|
modifiedKey[i] = "X"
|
||
|
|
} else if modifiedKey[i].isNumber {
|
||
|
|
modifiedKey[i] = "9"
|
||
|
|
}
|
||
|
|
|
||
|
|
let result = validator.validate(String(modifiedKey))
|
||
|
|
XCTAssertFalse(result.isValid, "Modified key should fail validation")
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
### Fuzzing Tests
|
||
|
|
|
||
|
|
```swift
|
||
|
|
class KeyFuzzingTests: XCTestCase {
|
||
|
|
let fuzzer = KeyFuzzer()
|
||
|
|
let validator = KeyValidator()
|
||
|
|
|
||
|
|
func testFuzzValidation() throws {
|
||
|
|
// Generate random inputs
|
||
|
|
for _ in 0..<100000 {
|
||
|
|
let fuzzedInput = fuzzer.generateRandomInput()
|
||
|
|
|
||
|
|
// Validation should never crash
|
||
|
|
let result = validator.validate(fuzzedInput)
|
||
|
|
|
||
|
|
// Only properly formatted keys should validate
|
||
|
|
if result.isValid {
|
||
|
|
XCTAssertTrue(isProperlyFormatted(fuzzedInput))
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
class KeyFuzzer {
|
||
|
|
func generateRandomInput() -> String {
|
||
|
|
let strategies = [
|
||
|
|
generateRandomString,
|
||
|
|
generateNearValidKey,
|
||
|
|
generateMalformedKey,
|
||
|
|
generateSQLInjection,
|
||
|
|
generateBufferOverflow
|
||
|
|
]
|
||
|
|
|
||
|
|
return strategies.randomElement()!()
|
||
|
|
}
|
||
|
|
|
||
|
|
private func generateNearValidKey() -> String {
|
||
|
|
let base = "VUUW-XXXX-XXXX-XXXX-L1"
|
||
|
|
let chars = Array(base)
|
||
|
|
var modified = chars
|
||
|
|
|
||
|
|
// Change 1-3 characters
|
||
|
|
for _ in 0..<Int.random(in: 1...3) {
|
||
|
|
let index = Int.random(in: 0..<chars.count)
|
||
|
|
modified[index] = Character.random()
|
||
|
|
}
|
||
|
|
|
||
|
|
return String(modified)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
## Monitoring and Analytics
|
||
|
|
|
||
|
|
### Key Usage Analytics
|
||
|
|
|
||
|
|
```swift
|
||
|
|
class KeyAnalytics {
|
||
|
|
private let telemetry = TelemetryService()
|
||
|
|
|
||
|
|
func trackKeyEvent(_ event: KeyEvent) {
|
||
|
|
// Anonymous tracking only
|
||
|
|
let anonymizedEvent = AnonymizedKeyEvent(
|
||
|
|
type: event.type,
|
||
|
|
level: event.level,
|
||
|
|
timestamp: event.timestamp.timeIntervalSince1970,
|
||
|
|
success: event.success
|
||
|
|
)
|
||
|
|
|
||
|
|
telemetry.record(anonymizedEvent)
|
||
|
|
}
|
||
|
|
|
||
|
|
func generateReport() async -> KeyUsageReport {
|
||
|
|
let events = await telemetry.fetchEvents()
|
||
|
|
|
||
|
|
return KeyUsageReport(
|
||
|
|
totalActivations: countActivations(events),
|
||
|
|
activationsByLevel: groupByLevel(events),
|
||
|
|
successRate: calculateSuccessRate(events),
|
||
|
|
peakUsageTimes: findPeakTimes(events),
|
||
|
|
averageTimeToActivation: calculateAverageTime(events)
|
||
|
|
)
|
||
|
|
}
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
This comprehensive key generation and validation system ensures security, scalability, and excellent user experience while maintaining the highest standards of privacy and data protection.
|