Swift API Reference

Complete API documentation for MetaMUI Crypto Primitives in Swift.

Installation

Swift Package Manager

// Package.swift
dependencies: [
    .package(url: "https://github.com/metamui/crypto-swift", from: "3.0.0")
]

Xcode

  1. File → Add Package Dependencies
  2. Enter: https://github.com/metamui/crypto-swift
  3. Select version: 3.0.0 or later

Quick Start

import MetaMUICrypto

// Generate keypair
let keypair = try Ed25519.generateKeypair()

// Sign message
let message = "Hello".data(using: .utf8)!
let signature = try Ed25519.sign(message, privateKey: keypair.privateKey)

// Verify signature
let isValid = try Ed25519.verify(
    signature: signature,
    message: message,
    publicKey: keypair.publicKey
)

API Documentation

For detailed API documentation, see:

Available Modules

Hash Functions

import MetaMUICrypto

// Simple hashing
let hash = SHA256.hash(data: messageData)
let blake3Hash = Blake3.hash(data: messageData)

// Streaming hash
var hasher = Blake3.Hasher()
hasher.update(data: chunk1)
hasher.update(data: chunk2)
let finalHash = hasher.finalize()

Digital Signatures

// Ed25519
let keypair = try Ed25519.generateKeypair()
let signature = try keypair.sign(message)
let isValid = try keypair.verify(signature: signature, message: message)

// Post-quantum signatures
let pqKeypair = try Dilithium.generateKeypair()
let pqSignature = try pqKeypair.sign(message)

Encryption

// ChaCha20-Poly1305
let key = ChaCha20Poly1305.generateKey()
let sealed = try ChaCha20Poly1305.seal(plaintext, using: key)
let decrypted = try ChaCha20Poly1305.open(sealed, using: key)

// AES-256-GCM
let aesKey = AES256.generateKey()
let aesSealed = try AES256.seal(plaintext, using: aesKey)

Key Exchange

// X25519 ECDH
let alice = try X25519.generateKeypair()
let bob = try X25519.generateKeypair()
let sharedSecret = try alice.computeSharedSecret(
    with: bob.publicKey
)

// Post-quantum KEM
let kemKeypair = try MLKem768.generateKeypair()
let (ciphertext, sharedSecret) = try MLKem768.encapsulate(
    to: kemKeypair.publicKey
)

Key Derivation

// Password hashing
let salt = Argon2.generateSalt()
let hash = try Argon2.hash(
    password: password,
    salt: salt,
    memory: 256 * 1024, // 256MB
    iterations: 4,
    parallelism: 2
)

// Key derivation
let derivedKey = try HKDF.deriveKey(
    from: inputKey,
    salt: salt,
    info: "encryption key".data(using: .utf8)!,
    outputByteCount: 32
)

SwiftUI Integration

import SwiftUI
import MetaMUICrypto

struct SecureView: View {
    @State private var isUnlocked = false
    @State private var password = ""
    
    private let secureStorage = SecureStorage()
    
    var body: some View {
        if isUnlocked {
            Text("Secure Content")
        } else {
            SecureField("Password", text: $password)
                .onSubmit {
                    unlock()
                }
        }
    }
    
    private func unlock() {
        Task {
            do {
                let isValid = try await secureStorage.verify(password)
                await MainActor.run {
                    isUnlocked = isValid
                }
            } catch {
                print("Unlock failed: \(error)")
            }
        }
    }
}

Combine Support

import Combine
import MetaMUICrypto

class CryptoService: ObservableObject {
    @Published var isEncrypting = false
    
    func encrypt(_ data: Data) -> AnyPublisher<Data, Error> {
        Future { promise in
            Task {
                do {
                    let key = ChaCha20Poly1305.generateKey()
                    let sealed = try ChaCha20Poly1305.seal(data, using: key)
                    promise(.success(sealed.combined))
                } catch {
                    promise(.failure(error))
                }
            }
        }
        .eraseToAnyPublisher()
    }
}

Async/Await

All CPU-intensive operations support async/await:

// Async key generation
let keypair = try await Ed25519.generateKeypair()

// Async encryption
let encrypted = try await ChaCha20Poly1305.seal(
    plaintext,
    using: key
)

// Async password hashing
let hash = try await Argon2.hash(
    password: password,
    salt: salt
)

Error Handling

enum CryptoError: Error {
    case invalidKey
    case decryptionFailed
    case verificationFailed
    case insufficientMemory
}

do {
    let decrypted = try ChaCha20Poly1305.open(sealed, using: key)
} catch CryptoError.decryptionFailed {
    print("Decryption failed - data may be corrupted")
} catch CryptoError.invalidKey {
    print("Invalid key provided")
} catch {
    print("Unexpected error: \(error)")
}

Keychain Integration

import Security

extension Ed25519.Keypair {
    func saveToKeychain(identifier: String) throws {
        let query: [String: Any] = [
            kSecClass as String: kSecClassKey,
            kSecAttrApplicationTag as String: identifier,
            kSecValueData as String: privateKey
        ]
        
        let status = SecItemAdd(query as CFDictionary, nil)
        guard status == errSecSuccess else {
            throw KeychainError.saveFailed(status)
        }
    }
    
    static func loadFromKeychain(identifier: String) throws -> Data {
        let query: [String: Any] = [
            kSecClass as String: kSecClassKey,
            kSecAttrApplicationTag as String: identifier,
            kSecReturnData as String: true
        ]
        
        var result: AnyObject?
        let status = SecItemCopyMatching(query as CFDictionary, &result)
        
        guard status == errSecSuccess,
              let data = result as? Data else {
            throw KeychainError.loadFailed(status)
        }
        
        return data
    }
}

Performance

Hardware Acceleration

// Automatically uses hardware acceleration when available
let hash = SHA256.hash(data: largeData) // Uses Apple's CryptoKit internally

// Force software implementation
let hash = SHA256.hash(data: largeData, useHardware: false)

Batch Operations

let signatures = try Ed25519.batchSign(
    messages: messages,
    privateKey: privateKey
)

let results = try Ed25519.batchVerify(
    signatures: signatures,
    messages: messages,
    publicKeys: publicKeys
)

Memory Security

// Secure memory allocation
let secureData = SecureData(count: 32)
defer { secureData.clear() }

// Automatic clearing with property wrapper
@SecureStorage var privateKey: Data

// Manual clearing
var sensitiveData = Data(repeating: 0, count: 32)
defer { sensitiveData.withUnsafeMutableBytes { $0.initializeMemory(as: UInt8.self, repeating: 0) } }

Examples

Secure File Storage

class SecureFileManager {
    private let key: SymmetricKey
    
    init(password: String) throws {
        let salt = UserDefaults.standard.data(forKey: "salt") ?? {
            let newSalt = Argon2.generateSalt()
            UserDefaults.standard.set(newSalt, forKey: "salt")
            return newSalt
        }()
        
        self.key = try Argon2.deriveKey(
            from: password,
            salt: salt,
            outputByteCount: 32
        )
    }
    
    func save(_ data: Data, to url: URL) throws {
        let sealed = try AES256.seal(data, using: key)
        try sealed.combined.write(to: url)
    }
    
    func load(from url: URL) throws -> Data {
        let sealedData = try Data(contentsOf: url)
        let sealedBox = try AES256.SealedBox(combined: sealedData)
        return try AES256.open(sealedBox, using: key)
    }
}

Network Security

class SecureAPIClient {
    private let signingKey: Ed25519.Keypair
    
    init() throws {
        self.signingKey = try Ed25519.generateKeypair()
    }
    
    func makeRequest(_ request: URLRequest) async throws -> Data {
        var signedRequest = request
        
        // Sign request body
        if let body = request.httpBody {
            let signature = try signingKey.sign(body)
            signedRequest.setValue(
                signature.base64EncodedString(),
                forHTTPHeaderField: "X-Signature"
            )
            signedRequest.setValue(
                signingKey.publicKey.base64EncodedString(),
                forHTTPHeaderField: "X-Public-Key"
            )
        }
        
        let (data, _) = try await URLSession.shared.data(for: signedRequest)
        return data
    }
}

See Also