Đôi khi phát triển ứng dụng chúng ta sẽ phải lưu lại những dữ liệu nhạy cảm như thông tin người dùng, thẻ ngân hàng … Vậy lúc đó chúng ta sẽ phải cần đến Keychain để lưu các dữ liệu đó. Vậy hôm nay mình sẽ giới thiệu với các bạn phương pháp lưu dữ liệu sử dụng Keychain.
Tại sao không dùng các phương pháp lưu dữ liệu khác?
Có thể các bạn đã biết, những thông tin nhạy cảm của người dùng như: thông tin tài khoản(username, pass, token …), thông tin thẻ ngân hàng … nếu để lộ ra ngoài sẽ làm ảnh hưởng rất lớn tời người dùng. Vì vậy nếu chúng ta sử dụng các cách lưu dữ liệu thông thường không có tính bảo mật như: File, Property List(UserDefaults), CoreData, Realm … thì người ta hoàn toàn có thể lấy được nội dung của ứng dụng một cách đơn giản. Về cơ bản các kiểu lưu dữ liệu kia đều sử dụng 1 file để lưu trữ data ở đó mà không sử dụng bất kỳ phương pháp mã hóa nào, vì vậy nó quá dễ dàng để các tin tặc có thể lấy được những dữ liệu bạn lưu trong các file đó.
Sử dụng Keychain Services API
Để lưu trữ những dữ liệu nhạy cảm cần tính bảo mật Apple đã cung cấp cho chúng ta Security Services. Keychain services API sẽ giúp chúng ta lưu trữ các dữ liệu này ở trong một encrypted database được gọi là Keychain.
Để lưu Password vào keychain mình sẽ làm như sau:
func save(_ password: String, for account: String) {
let password = password.data(using: String.Encoding.utf8)!
let query: [String: Any] = [kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: account,
kSecValueData as String: password]
let status = SecItemAdd(query as CFDictionary, nil)
guard status == errSecSuccess else { return print("save error")}
}
Keychain service cung cấp một số kiểu để xác định nơi lưu trữ phù hợp. kSecClassGenericPassword là một trong số đó, keychain services sẽ hiểu items này là password và cần được mã hóa. Ngoài ra còn có các kiểu khác các bạn tìm hiểu ở ĐÂY.
SecItemAdd(_:_:) để lưu dữ liệu vào keychain
Để lấy lại dữ liệu chúng ta đã lưu chúng ta làm như sau:
func getPassword(for account: String) -> String? {
let query: [String: Any] = [kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: account,
kSecMatchLimit as String: kSecMatchLimitOne,
kSecReturnData as String: kCFBooleanTrue]
var retrivedData: AnyObject? = nil
let _ = SecItemCopyMatching(query as CFDictionary, &retrivedData)
guard let data = retrivedData as? Data else {return nil}
return String(data: data, encoding: String.Encoding.utf8)
}
Để lấy dữ liệu ra chúng ta sử dụng SecItemCopyMatching() truyền vào đó query mà mình muốn.
Đối với các bạn lần đầu làm việc với Keychain API thì nó cũng khá lằng nhằng. Nhưng hiện nay đã có khá nhiều thư viện ngon hỗ trợ việc code của các bạn trở nên dễ dàng hơn như: Keychain-swift, Keychain Access
Mã hóa thông tin
Ngoài Password ra đôi khi chúng ta cũng cần phải mã hóa một số loại thông tin nhạy cảm khác. Việc mã hóa bằng tay khá phức tạp, vì vậy để hỗ trợ cho việc mã hóa mình thường dùng CryptoSwift.
Tổng kết
Mình hi vọng bài viết có thể giúp các bạn khi các bạn gặp phải các bài toán cần phải lưu những dữ liệu nhạy cảm. Khi đó nhớ chọn Keychain nhé. Chúc các bạn thành công.
Bài viết tiếp theo mình sẽ chia sẻ thêm một tính năng rất hay của keychain đó là Keychain Sharing