2022-01-29 18:59:42 +01:00
|
|
|
import Foundation
|
|
|
|
import CryptoKit
|
|
|
|
import SwiftUI
|
|
|
|
|
|
|
|
final class KeyManagement {
|
2022-04-09 17:43:33 +02:00
|
|
|
|
|
|
|
static let tag = "com.ch.sesame.key".data(using: .utf8)!
|
|
|
|
|
|
|
|
private static let label = "sesame"
|
|
|
|
|
|
|
|
private static let keyType = kSecAttrKeyTypeEC
|
|
|
|
|
|
|
|
private static let keyClass = kSecAttrKeyClassSymmetric
|
|
|
|
|
|
|
|
private static let query: [String: Any] = [
|
|
|
|
kSecClass as String: kSecClassInternetPassword,
|
|
|
|
kSecAttrAccount as String: "account",
|
|
|
|
kSecAttrServer as String: "christophhagen.de",
|
2022-04-13 14:55:47 +02:00
|
|
|
kSecAttrLabel as String: "sesame"]
|
2022-04-09 17:43:33 +02:00
|
|
|
|
|
|
|
private static func loadKeys() -> Data? {
|
|
|
|
var query = query
|
|
|
|
query[kSecReturnData as String] = kCFBooleanTrue
|
|
|
|
|
|
|
|
var item: CFTypeRef?
|
|
|
|
let status = SecItemCopyMatching(query as CFDictionary, &item)
|
|
|
|
guard status == errSecSuccess else {
|
|
|
|
print("Failed to get key: \(status)")
|
|
|
|
return nil
|
2022-01-29 18:59:42 +01:00
|
|
|
}
|
2022-04-09 17:43:33 +02:00
|
|
|
let key = item as! CFData
|
|
|
|
print("Key loaded from keychain")
|
|
|
|
return key as Data
|
2022-01-29 18:59:42 +01:00
|
|
|
}
|
2022-04-09 17:43:33 +02:00
|
|
|
|
|
|
|
private static func deleteKeys() {
|
|
|
|
let status = SecItemDelete(query as CFDictionary)
|
|
|
|
guard status == errSecSuccess || status == errSecItemNotFound else {
|
|
|
|
print("Failed to remove key: \(status)")
|
|
|
|
return
|
2022-01-29 18:59:42 +01:00
|
|
|
}
|
2022-04-09 17:43:33 +02:00
|
|
|
print("Key removed from keychain")
|
2022-01-29 18:59:42 +01:00
|
|
|
}
|
2022-04-09 17:43:33 +02:00
|
|
|
|
|
|
|
private static func saveKeys(_ data: Data) {
|
|
|
|
var query = query
|
|
|
|
query[kSecValueData as String] = data
|
|
|
|
let status = SecItemAdd(query as CFDictionary, nil)
|
|
|
|
guard status == errSecSuccess else {
|
|
|
|
print("Failed to store key: \(status)")
|
2022-01-29 18:59:42 +01:00
|
|
|
return
|
|
|
|
}
|
2022-04-09 17:43:33 +02:00
|
|
|
print("Key saved to keychain")
|
2022-01-29 18:59:42 +01:00
|
|
|
}
|
2022-04-09 17:43:33 +02:00
|
|
|
|
|
|
|
private static var keyData: Data? = loadKeys() {
|
|
|
|
didSet {
|
|
|
|
guard let data = keyData else {
|
|
|
|
deleteKeys()
|
|
|
|
return
|
|
|
|
}
|
|
|
|
saveKeys(data)
|
2022-01-29 18:59:42 +01:00
|
|
|
}
|
|
|
|
}
|
2022-04-09 17:43:33 +02:00
|
|
|
|
|
|
|
static var hasKey: Bool {
|
|
|
|
key != nil
|
2022-01-29 18:59:42 +01:00
|
|
|
}
|
2022-04-09 17:43:33 +02:00
|
|
|
|
|
|
|
private(set) static var key: (device: SymmetricKey, remote: SymmetricKey)? {
|
|
|
|
get {
|
|
|
|
guard let data = keyData else {
|
|
|
|
return nil
|
2022-01-29 18:59:42 +01:00
|
|
|
}
|
2022-04-09 17:43:33 +02:00
|
|
|
let device = SymmetricKey(data: data.prefix(32))
|
|
|
|
let remote = SymmetricKey(data: data.advanced(by: 32))
|
|
|
|
return (device, remote)
|
2022-01-29 18:59:42 +01:00
|
|
|
}
|
2022-04-09 17:43:33 +02:00
|
|
|
set {
|
|
|
|
guard let key = newValue else {
|
|
|
|
keyData = nil
|
|
|
|
return
|
|
|
|
}
|
|
|
|
keyData = key.device.data + key.remote.data
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static func generateNewKeys() {
|
|
|
|
let device = SymmetricKey(size: .bits256)
|
|
|
|
let remote = SymmetricKey(size: .bits256)
|
|
|
|
key = (device, remote)
|
|
|
|
print("New keys:")
|
|
|
|
print("Device: \(device.data.hexEncoded)")
|
|
|
|
print("Remote: \(remote.data.hexEncoded)")
|
2022-01-29 18:59:42 +01:00
|
|
|
}
|
|
|
|
}
|