@@ -3,158 +3,9 @@ import Crypto
3
3
import Foundation
4
4
5
5
#if os(macOS)
6
- public class Keychain
7
- {
8
- public init ( ) { }
9
-
10
- public func retrieveOrGeneratePrivateKey( label: String ) -> P256 . KeyAgreement . PrivateKey ?
11
- {
12
- // Do we already have a key?
13
- if let key = retrievePrivateKey ( label: label)
14
- {
15
- return key
16
- }
17
-
18
- // We don't?
19
- // Let's create some and return those
20
- let privateKey = P256 . KeyAgreement. PrivateKey ( )
21
-
22
- // Save the key we stored
23
- let stored = storePrivateKey ( privateKey, label: label)
24
- if !stored
25
- {
26
- print ( " 😱 Failed to store our new server key. " )
27
- return nil
28
- }
29
- return privateKey
30
- }
31
-
32
- public func generateAndSavePrivateKey( label: String ) -> P256 . KeyAgreement . PrivateKey ?
33
- {
34
- let privateKey = P256 . KeyAgreement. PrivateKey ( )
35
-
36
- // Save the key we stored
37
- let stored = storePrivateKey ( privateKey, label: label)
38
- if !stored
39
- {
40
- print ( " 😱 Failed to store our new server key. " )
41
- return nil
42
- }
43
-
44
- return privateKey
45
- }
46
-
47
- public func storePrivateKey( _ key: P256 . KeyAgreement . PrivateKey , label: String ) -> Bool
48
- {
49
- let attributes = [ kSecAttrKeyType: kSecAttrKeyTypeECSECPrimeRandom,
50
- kSecAttrKeyClass: kSecAttrKeyClassPrivate] as [ String : Any ]
51
6
52
- // Get a SecKey representation.
53
- var error : Unmanaged < CFError > ?
54
- let keyData = key. x963Representation as CFData
55
- guard let secKey = SecKeyCreateWithData ( keyData,
56
- attributes as CFDictionary ,
57
- & error)
58
- else
59
- {
60
- print ( " Unable to create SecKey representation. " )
61
- if let secKeyError = error
62
- {
63
- print ( secKeyError)
64
- }
65
- return false
66
- }
67
-
68
- // Describe the add operation.
69
- let query = [ kSecClass: kSecClassKey,
70
- kSecAttrApplicationLabel: label,
71
- kSecAttrAccessible: kSecAttrAccessibleWhenUnlocked,
72
- kSecUseDataProtectionKeychain: true ,
73
- kSecValueRef: secKey] as [ String : Any ]
7
+ @_exported import KeychainMacOS
74
8
75
- // Add the key to the keychain.
76
- let status = SecItemAdd ( query as CFDictionary , nil )
77
-
78
- switch status {
79
- case errSecSuccess:
80
- return true
81
- default :
82
- if let statusString = SecCopyErrorMessageString ( status, nil )
83
- {
84
- print ( " Unable to store item: \( statusString) " )
85
- }
86
-
87
- return false
88
- }
89
- }
90
-
91
- public func retrievePrivateKey( label: String ) -> P256 . KeyAgreement . PrivateKey ?
92
- {
93
- let query : CFDictionary = generateKeySearchQuery ( label: label)
94
-
95
- // Find and cast the result as a SecKey instance.
96
- var item : CFTypeRef ?
97
- var secKey : SecKey
98
- switch SecItemCopyMatching ( query as CFDictionary , & item) {
99
- case errSecSuccess: secKey = item as! SecKey
100
- case errSecItemNotFound: return nil
101
- case let status:
102
- print ( " Keychain read failed: \( status) " )
103
- return nil
104
- }
105
-
106
- // Convert the SecKey into a CryptoKit key.
107
- var error : Unmanaged < CFError > ?
108
- guard let data = SecKeyCopyExternalRepresentation ( secKey, & error) as Data ?
109
- else
110
- {
111
- print ( error. debugDescription)
112
- return nil
113
- }
114
-
115
- do {
116
- let key = try P256 . KeyAgreement. PrivateKey ( x963Representation: data)
117
- return key
118
- }
119
- catch let keyError
120
- {
121
- print ( " Error decoding key: \( keyError) " )
122
- return nil
123
- }
124
- }
125
-
126
- public func generateKeySearchQuery( label: String ) -> CFDictionary
127
- {
128
- let query : [ String : Any ] = [ kSecClass as String : kSecClassKey,
129
- kSecAttrApplicationLabel as String : label,
130
- //kSecAttrApplicationTag as String: tag,
131
- kSecMatchLimit as String : kSecMatchLimitOne,
132
- kSecReturnRef as String : true ,
133
- kSecReturnAttributes as String : false ,
134
- kSecReturnData as String : false ]
135
-
136
- return query as CFDictionary
137
- }
138
-
139
- public func deleteKey( label: String )
140
- {
141
- print ( " \n Attempted to delete key. " )
142
- //Remove client keys from secure enclave
143
- //let query: [String: Any] = [kSecClass as String: kSecClassKey, kSecAttrApplicationTag as String: tag]
144
- let query = generateKeySearchQuery ( label: label)
145
- let deleteStatus = SecItemDelete ( query as CFDictionary )
146
-
147
- switch deleteStatus
148
- {
149
- case errSecItemNotFound:
150
- print ( " Could not find a key to delete. \n " )
151
- case noErr:
152
- print ( " Deleted a key. \n " )
153
- default :
154
- print ( " Unexpected status: \( deleteStatus. description) \n " )
155
- }
156
- }
157
- }
158
9
#else
159
10
160
11
@_exported import KeychainLinux
0 commit comments