mirror of
https://github.com/maxgoedjen/secretive.git
synced 2025-10-07 19:50:57 +00:00
WIP
This commit is contained in:
parent
a0cf74f9dc
commit
267fe4bf27
15
Sources/Packages/Sources/CertificateKit/Certificate.swift
Normal file
15
Sources/Packages/Sources/CertificateKit/Certificate.swift
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import Foundation
|
||||||
|
//import SecretKit
|
||||||
|
|
||||||
|
//extension SecureEnclave {
|
||||||
|
|
||||||
|
public struct Certificate: Sendable, Codable, Equatable, Hashable, Identifiable {
|
||||||
|
|
||||||
|
public var id: Int { hashValue }
|
||||||
|
public var type: String
|
||||||
|
public let name: String?
|
||||||
|
public let data: Data
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//}
|
134
Sources/Packages/Sources/CertificateKit/CertificateStore.swift
Normal file
134
Sources/Packages/Sources/CertificateKit/CertificateStore.swift
Normal file
@ -0,0 +1,134 @@
|
|||||||
|
import Foundation
|
||||||
|
import Observation
|
||||||
|
import Security
|
||||||
|
import os
|
||||||
|
import SecretKit
|
||||||
|
|
||||||
|
@Observable public final class CertificateStore {
|
||||||
|
|
||||||
|
@MainActor private var certificates: [Certificate] = []
|
||||||
|
|
||||||
|
/// Initializes a Store.
|
||||||
|
@MainActor public init() {
|
||||||
|
loadCertificates()
|
||||||
|
Task {
|
||||||
|
// for await note in DistributedNotificationCenter.default().notifications(named: .certificateStoreUpdated) {
|
||||||
|
// guard Constants.notificationToken != (note.object as? String) else {
|
||||||
|
// // Don't reload if we're the ones triggering this by reloading.
|
||||||
|
// continue
|
||||||
|
// }
|
||||||
|
// loadCertificates()
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@MainActor public func reloadCertificates() {
|
||||||
|
let before = certificates
|
||||||
|
certificates.removeAll()
|
||||||
|
loadCertificates()
|
||||||
|
if certificates != before {
|
||||||
|
// NotificationCenter.default.post(name: .certificateStoreReloaded, object: self)
|
||||||
|
// DistributedNotificationCenter.default().postNotificationName(.certificateStoreUpdated, object: Constants.notificationToken, deliverImmediately: true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@MainActor public func saveCertificate(_ data: Data, for secret: any Secret) {
|
||||||
|
let certificate = SecCertificateCreateWithData(nil, data as CFData)
|
||||||
|
print(certificate as Any)
|
||||||
|
}
|
||||||
|
|
||||||
|
@MainActor public func certificates(for secret: any Secret) -> [Certificate] {
|
||||||
|
[]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extension CertificateStore {
|
||||||
|
|
||||||
|
/// Loads all certificates from the store.
|
||||||
|
@MainActor private func loadCertificates() {
|
||||||
|
// let queryAttributes = KeychainDictionary([
|
||||||
|
// kSecClass: Constants.keyClass,
|
||||||
|
// kSecAttrService: Constants.keyTag,
|
||||||
|
// kSecUseDataProtectionKeychain: true,
|
||||||
|
// kSecReturnData: true,
|
||||||
|
// kSecMatchLimit: kSecMatchLimitAll,
|
||||||
|
// kSecReturnAttributes: true
|
||||||
|
// ])
|
||||||
|
// var untyped: CFTypeRef?
|
||||||
|
// unsafe SecItemCopyMatching(queryAttributes, &untyped)
|
||||||
|
// guard let typed = untyped as? [[CFString: Any]] else { return }
|
||||||
|
// let wrapped: [SecureEnclave.Certificates] = typed.compactMap {
|
||||||
|
// do {
|
||||||
|
// let name = $0[kSecAttrLabel] as? String ?? String(localized: "unnamed_certificate")
|
||||||
|
// guard let attributesData = $0[kSecAttrGeneric] as? Data,
|
||||||
|
// let id = $0[kSecAttrAccount] as? String else {
|
||||||
|
// throw MissingAttributesError()
|
||||||
|
// }
|
||||||
|
// let attributes = try JSONDecoder().decode(Attributes.self, from: attributesData)
|
||||||
|
// let keyData = $0[kSecValueData] as! Data
|
||||||
|
// let publicKey: Data
|
||||||
|
// switch attributes.keyType {
|
||||||
|
// case .ecdsa256:
|
||||||
|
// let key = try CryptoKit.SecureEnclave.P256.Signing.PrivateKey(dataRepresentation: keyData)
|
||||||
|
// publicKey = key.publicKey.x963Representation
|
||||||
|
// case .mldsa65:
|
||||||
|
// guard #available(macOS 26.0, *) else { throw UnsupportedAlgorithmError() }
|
||||||
|
// let key = try CryptoKit.SecureEnclave.MLDSA65.PrivateKey(dataRepresentation: keyData)
|
||||||
|
// publicKey = key.publicKey.rawRepresentation
|
||||||
|
// case .mldsa87:
|
||||||
|
// guard #available(macOS 26.0, *) else { throw UnsupportedAlgorithmError() }
|
||||||
|
// let key = try CryptoKit.SecureEnclave.MLDSA87.PrivateKey(dataRepresentation: keyData)
|
||||||
|
// publicKey = key.publicKey.rawRepresentation
|
||||||
|
// default:
|
||||||
|
// throw UnsupportedAlgorithmError()
|
||||||
|
// }
|
||||||
|
// return SecureEnclave.Certificates(id: id, name: name, publicKey: publicKey, attributes: attributes)
|
||||||
|
// } catch {
|
||||||
|
// return nil
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// certificates.append(contentsOf: wrapped)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Saves a public key.
|
||||||
|
/// - Parameters:
|
||||||
|
/// - key: The data representation key to save.
|
||||||
|
/// - name: A user-facing name for the key.
|
||||||
|
/// - attributes: Attributes of the key.
|
||||||
|
/// - Note: Despite the name, the "Data" of the key is _not_ actual key material. This is an opaque data representation that the SEP can manipulate.
|
||||||
|
// @discardableResult
|
||||||
|
// func saveKey(_ key: Data, name: String, attributes: Attributes) throws -> String {
|
||||||
|
// let attributes = try JSONEncoder().encode(attributes)
|
||||||
|
// let id = UUID().uuidString
|
||||||
|
// let keychainAttributes = KeychainDictionary([
|
||||||
|
// kSecClass: Constants.keyClass,
|
||||||
|
// kSecAttrService: Constants.keyTag,
|
||||||
|
// kSecUseDataProtectionKeychain: true,
|
||||||
|
// kSecAttrAccessible: kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
|
||||||
|
// kSecAttrAccount: id,
|
||||||
|
// kSecValueData: key,
|
||||||
|
// kSecAttrLabel: name,
|
||||||
|
// kSecAttrGeneric: attributes
|
||||||
|
// ])
|
||||||
|
// let status = SecItemAdd(keychainAttributes, nil)
|
||||||
|
// if status != errSecSuccess {
|
||||||
|
// throw KeychainError(statusCode: status)
|
||||||
|
// }
|
||||||
|
// return id
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extension CertificateStore {
|
||||||
|
|
||||||
|
enum Constants {
|
||||||
|
static let keyClass = kSecClassCertificate as String
|
||||||
|
static let keyTag = Data("com.maxgoedjen.certificateive.certificate".utf8)
|
||||||
|
static let notificationToken = UUID().uuidString
|
||||||
|
}
|
||||||
|
|
||||||
|
struct UnsupportedAlgorithmError: Error {}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user