-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathKeychainStorage.swift
More file actions
71 lines (55 loc) · 1.98 KB
/
KeychainStorage.swift
File metadata and controls
71 lines (55 loc) · 1.98 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
//
// KeychainStorage.swift
// DataSource
//
// Created by 최정인 on 7/26/25.
//
import Foundation
final class KeychainStorage {
static let shared = KeychainStorage()
private let service: String = Bundle.main.bundleIdentifier ?? "DefaultService"
private init() { }
func save(_ value: String, forKey key: String) -> Bool {
guard let data = value.data(using: .utf8) else {
return false
}
var query = baseQuery(for: key)
let attributes: [String: Any] = [
kSecValueData as String: data,
kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlocked
]
let status = SecItemUpdate(query as CFDictionary, attributes as CFDictionary)
if status == errSecItemNotFound {
for (attributeKey, attributeValue) in attributes {
query[attributeKey] = attributeValue
}
return SecItemAdd(query as CFDictionary, nil) == errSecSuccess
}
return status == errSecSuccess
}
func load(forKey key: String) -> String? {
var query = baseQuery(for: key)
query[kSecReturnData as String] = kCFBooleanTrue
query[kSecMatchLimit as String] = kSecMatchLimitOne
var result: AnyObject?
let status = SecItemCopyMatching(query as CFDictionary, &result)
if status == errSecSuccess,
let data = result as? Data {
return String(data: data, encoding: .utf8)
}
return nil
}
func remove(forKey key: String) -> Bool {
let query = baseQuery(for: key)
let status = SecItemDelete(query as CFDictionary)
return status == errSecSuccess || status == errSecItemNotFound
}
private func baseQuery(for key: String) -> [String: Any] {
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrService as String: service,
kSecAttrAccount as String: key
]
return query
}
}