Security in Swift
Introduction
This guide covers essential security practices and guidelines for developing secure applications in Swift, including data protection, network security, and common vulnerabilities.
Data Protection
Secure Storage
import Security
class KeychainManager {
static func savePassword(_ password: String, for account: String) -> OSStatus {
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: account,
kSecValueData as String: password.data(using: .utf8)!,
kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlockedThisDeviceOnly
]
return SecItemAdd(query as CFDictionary, nil)
}
static func getPassword(for account: String) -> String? {
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: account,
kSecReturnData as String: true
]
var result: AnyObject?
let status = SecItemCopyMatching(query as CFDictionary, &result)
guard status == errSecSuccess,
let data = result as? Data,
let password = String(data: data, encoding: .utf8) else {
return nil
}
return password
}
}
Network Security
Certificate Pinning
class CertificatePinningDelegate: NSObject, URLSessionDelegate {
func urlSession(_ session: URLSession,
didReceive challenge: URLAuthenticationChallenge,
completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void) {
guard let serverTrust = challenge.protectionSpace.serverTrust,
let certificate = SecTrustGetCertificateAtIndex(serverTrust, 0) else {
completionHandler(.cancelAuthenticationChallenge, nil)
return
}
let policy = NSMutableArray()
policy.add(SecPolicyCreateSSL(true, challenge.protectionSpace.host as CFString))
let isServerTrusted = SecTrustEvaluateWithError(serverTrust, nil)
if isServerTrusted {
let remoteCertificateData = SecCertificateCopyData(certificate)
let cerPath = Bundle.main.path(forResource: "certificate", ofType: "cer")!
let localCertificateData = NSData(contentsOfFile: cerPath)!
if remoteCertificateData == localCertificateData {
let credential = URLCredential(trust: serverTrust)
completionHandler(.useCredential, credential)
return
}
}
completionHandler(.cancelAuthenticationChallenge, nil)
}
}
Encryption
Data Encryption
import CryptoKit
class EncryptionManager {
static func encrypt(_ data: Data, with key: SymmetricKey) throws -> Data {
let sealedBox = try AES.GCM.seal(data, using: key)
return sealedBox.combined!
}
static func decrypt(_ sealedData: Data, with key: SymmetricKey) throws -> Data {
let sealedBox = try AES.GCM.SealedBox(combined: sealedData)
return try AES.GCM.open(sealedBox, using: key)
}
static func generateKey() -> SymmetricKey {
return SymmetricKey(size: .bits256)
}
}
Input Validation
Secure Input Handling
struct InputValidator {
static func validate(email: String) -> Bool {
let pattern = "^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}$"
let predicate = NSPredicate(format: "SELF MATCHES %@", pattern)
return predicate.evaluate(with: email)
}
static func sanitize(_ input: String) -> String {
// Remove HTML tags and potentially dangerous characters
return input.replacingOccurrences(of: "<[^>]+>", with: "", options: .regularExpression)
.trimmingCharacters(in: .whitespacesAndNewlines)
}
}
Best Practices
- Use HTTPS for network communications
- Implement proper authentication and authorization
- Secure sensitive data storage
- Validate all user input
- Keep dependencies updated
- Use secure random number generation
- Implement proper error handling
- Use app transport security
Common Security Issues
Prevention Techniques
- SQL Injection
// Bad practice
let query = "SELECT * FROM users WHERE id = '\(userInput)'"
// Good practice
let query = "SELECT * FROM users WHERE id = ?"
statement.bind(1, userInput)
- Memory Management
// Clear sensitive data
class SecureData {
private var sensitiveData: Data?
func clear() {
sensitiveData?.withUnsafeMutableBytes { ptr in
ptr.baseAddress?.initializeMemory(as: UInt8.self, repeating: 0, count: ptr.count)
}
sensitiveData = nil
}
}
Security Testing
Common Tools and Techniques
- Static Analysis
- Dynamic Analysis
- Penetration Testing
- Code Signing Verification
- Network Traffic Analysis
Next Steps
- Review Testing and Debugging
- Study Performance Optimization
- Explore Package Management