Episode ini membahas keamanan aplikasi Swift: praktik secure coding dan validasi data, penyimpanan credential di Keychain, enkripsi dan hashing dasar dengan CryptoKit, serta secure storage, sandboxing, dan pelindungan privasi di platform Apple.

Keamanan bukan fitur yang dipasang di akhir — ia keputusan desain yang meresap di setiap lapisan aplikasi. Episode 11 membahas secure coding dan data protection di Swift: praktik validasi input, penyimpanan secret di Keychain, enkripsi dan hashing dengan CryptoKit, serta cara platform Apple melindungi data lewat sandboxing dan privacy.
Di dunia di mana data pengguna adalah target utama penyerang, aplikasi yang ceroboh bisa membocorkan data sensitif meski "berfungsi" dengan baik. Episode ini memberi kalian dasar untuk membangun aplikasi yang aman sejak baris pertama.
Empat prinsip yang menaungi seluruh praktik keamanan:
Validasi dilakukan sedekat mungkin dengan sumber input, menggunakan whitelist daripada blacklist:
struct Validator {
static func emailValid(_ email: String) -> Bool {
let pola = "^[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}$"
return email.range(of: pola, options: .regularExpression) != nil
}
static func rentangUmur(_ nilai: Int) -> Bool {
return (13...120).contains(nilai)
}
}
print(Validator.emailValid("arman@example.com"))
print(Validator.rentangUmur(200))email.range(of:options:.regularExpression) memeriksa email terhadap pola whitelist. Validasi dengan rentang eksplisit seperti (13...120).contains(nilai) menolak nilai di luar batas sejak awal — jauh lebih aman daripada membersihkan nilai buruk kemudian.
Keychain adalah penyimpanan terenkripsi khusus sistem untuk secret — token, password, dan data sensitif lainnya. Berbeda dengan UserDefaults dan file, data Keychain dienkripsi dan diikat ke perangkat serta pengguna:
import Security
func simpanKeychain(_ data: Data, untuk key: String) -> OSStatus {
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: key,
kSecValueData as String: data
]
return SecItemAdd(query as CFDictionary, nil)
}SecItemAdd(query, nil) menyimpan data ke Keychain; atribut kSecClassGenericPassword menandai entri sebagai password generik. Fungsi ini mengembalikan OSStatus yang harus diperiksa — errSecSuccess berarti berhasil.
Membaca kembali dilakukan dengan query pencarian:
func ambilKeychain(key: String) -> Data? {
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: key,
kSecReturnData as String: true,
kSecMatchLimit as String: kSecMatchLimitOne
]
var item: CFTypeRef?
let status = SecItemCopyMatching(query as CFDictionary, &item)
return status == errSecSuccess ? item as? Data : nil
}SecItemCopyMatching(query, &item) mengembalikan Data tersimpan jika ditemukan. Seluruh secret aplikasi — token API, credential — harus lewat jalur ini, bukan variabel global atau file plist yang mudah diekstrak.
Untuk memverifikasi integritas atau membuat sidik jari data, gunakan hashing — fungsi satu arah yang tidak bisa dibalik:
import CryptoKit
let pesan = Data("pesan rahasia".utf8)
let digest = SHA256.hash(data: pesan)
print(digest.map { String(format: "%02x", $0) }.joined())SHA256.hash(data: pesan) menghasilkan digest 32 byte. CryptoKit menyediakan implementasi yang dioptimasi hardware dan sudah diaudit — jangan pernah menulis algoritma kriptografi sendiri, selalu pakai library terpercaya.
Untuk menyimpan data sensitif yang perlu dibaca kembali, gunakan enkripsi simetris AES-GCM:
let key = SymmetricKey(size: .bits256)
let plainData = Data("isi rahasia".utf8)
let sealed = try AES.GCM.seal(plainData, using: key)
let dibuka = try AES.GCM.open(sealed, using: key)
print(String(data: dibuka, encoding: .utf8)!)AES.GCM.seal(plainData, using: key) mengenkripsi data dan menyertakan authentication tag untuk mendeteksi manipulasi. Kunci disimpan dengan aman di Keychain — menggabungkan enkripsi CryptoKit dengan Keychain adalah pola penyimpanan data terlindungi yang paling umum.
Aplikasi iOS berjalan dalam sandbox: akses ke sistem terbatas pada container sendiri. Data dalam container bisa dilindungi lebih lanjut dengan Data Protection — file dienkripsi otomatis dan hanya bisa diakses saat perangkat terbuka:
let data = Data("catatan pribadi".utf8)
try data.write(to: fileURL,
options: [.completeFileProtection]).completeFileProtection membuat file hanya dapat diakses saat perangkat tidak terkunci. Level proteksi lain — .completeFileProtectionUnlessOpen dan .noFileProtection — memberi keseimbangan antara keamanan dan ketersediaan saat notifikasi datang.
iOS mewajibkan kalian mendeklarasikan alasan setiap akses data pribadi (kamera, lokasi, foto) di Info.plist melalui key seperti NSCameraUsageDescription. Pengguna juga melihat indikator saat data tersebut diakses. Di luar kepatuhan, praktik privasi yang baik berarti:
Warning
Secret yang ditulis ke log adalah salah satu kebocoran paling umum. Terapkan aturan ketat: credential dan token tidak pernah masuk ke print, NSLog, maupun crash report.
Inti yang harus dibawa pulang:
Di episode 12 selanjutnya kita akan membahas authentication dan authorization — implementasi OAuth 2.0 dan OpenID Connect di aplikasi Swift, integrasi Sign in with Apple, pengelolaan token dan refresh token, serta konsumsi API yang aman dengan HTTP security headers. Keamanan kalian akan meluas ke sisi server!