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
- File → Add Package Dependencies
- Enter:
https://github.com/metamui/crypto-swift - 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
}
}