mirror of
				https://github.com/maxgoedjen/secretive.git
				synced 2025-11-04 01:10:56 +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