跳到主要内容

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

  1. Use HTTPS for network communications
  2. Implement proper authentication and authorization
  3. Secure sensitive data storage
  4. Validate all user input
  5. Keep dependencies updated
  6. Use secure random number generation
  7. Implement proper error handling
  8. Use app transport security

Common Security Issues

Prevention Techniques

  1. 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)
  1. 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

  1. Static Analysis
  2. Dynamic Analysis
  3. Penetration Testing
  4. Code Signing Verification
  5. Network Traffic Analysis

Next Steps

  1. Review Testing and Debugging
  2. Study Performance Optimization
  3. Explore Package Management