diff --git a/Sources/Packages/Sources/SecretAgentKit/Agent.swift b/Sources/Packages/Sources/SecretAgentKit/Agent.swift index bc8b44b..6afe2d5 100644 --- a/Sources/Packages/Sources/SecretAgentKit/Agent.swift +++ b/Sources/Packages/Sources/SecretAgentKit/Agent.swift @@ -93,7 +93,7 @@ extension Agent { for secret in secrets { let keyBlob = writer.data(secret: secret) - let curveData = writer.curveType(for: secret.keyType).data(using: .utf8)! + let curveData = Data(writer.curveType(for: secret.keyType).utf8) keyData.append(writer.lengthAndData(of: keyBlob)) keyData.append(writer.lengthAndData(of: curveData)) @@ -138,7 +138,7 @@ extension Agent { let signed = try await store.sign(data: dataToSign, with: secret, for: provenance) let derSignature = signed - let curveData = writer.curveType(for: secret.keyType).data(using: .utf8)! + let curveData = Data(writer.curveType(for: secret.keyType).utf8) // Convert from DER formatted rep to raw (r||s) diff --git a/Sources/Packages/Sources/SecretKit/Erasers/AnySecret.swift b/Sources/Packages/Sources/SecretKit/Erasers/AnySecret.swift index cd48212..3d3bc73 100644 --- a/Sources/Packages/Sources/SecretKit/Erasers/AnySecret.swift +++ b/Sources/Packages/Sources/SecretKit/Erasers/AnySecret.swift @@ -3,7 +3,7 @@ import Foundation /// Type eraser for Secret. public struct AnySecret: Secret, @unchecked Sendable { - public let base: Any + public let base: any Secret private let hashable: AnyHashable private let _id: () -> AnyHashable private let _name: () -> String @@ -19,7 +19,7 @@ public struct AnySecret: Secret, @unchecked Sendable { _publicKey = secret._publicKey _attributes = secret._attributes } else { - base = secret as Any + base = secret self.hashable = secret _id = { secret.id as AnyHashable } _name = { secret.name } diff --git a/Sources/Packages/Sources/SecretKit/Erasers/AnySecretStore.swift b/Sources/Packages/Sources/SecretKit/Erasers/AnySecretStore.swift index 03b357a..cb47e95 100644 --- a/Sources/Packages/Sources/SecretKit/Erasers/AnySecretStore.swift +++ b/Sources/Packages/Sources/SecretKit/Erasers/AnySecretStore.swift @@ -3,7 +3,7 @@ import Foundation /// Type eraser for SecretStore. open class AnySecretStore: SecretStore, @unchecked Sendable { - let base: any Sendable + let base: any SecretStore private let _isAvailable: @MainActor @Sendable () -> Bool private let _id: @Sendable () -> UUID private let _name: @MainActor @Sendable () -> String diff --git a/Sources/Packages/Sources/SecretKit/OpenSSH/OpenSSHCertificateHandler.swift b/Sources/Packages/Sources/SecretKit/OpenSSH/OpenSSHCertificateHandler.swift index dbfcc7a..ed9d293 100644 --- a/Sources/Packages/Sources/SecretKit/OpenSSH/OpenSSHCertificateHandler.swift +++ b/Sources/Packages/Sources/SecretKit/OpenSSH/OpenSSHCertificateHandler.swift @@ -40,7 +40,7 @@ public actor OpenSSHCertificateHandler: Sendable { let curveIdentifier = reader.readNextChunk() let publicKey = reader.readNextChunk() - let curveType = certType.replacingOccurrences(of: "-cert-v01@openssh.com", with: "").data(using: .utf8)! + let curveType = Data(certType.replacingOccurrences(of: "-cert-v01@openssh.com", with: "").utf8) return writer.lengthAndData(of: curveType) + writer.lengthAndData(of: curveIdentifier) + writer.lengthAndData(of: publicKey) @@ -78,14 +78,13 @@ public actor OpenSSHCertificateHandler: Sendable { throw OpenSSHCertificateError.parsingFailed } - if certElements.count >= 3, let certName = certElements[2].data(using: .utf8) { + if certElements.count >= 3 { + let certName = Data(certElements[2].utf8) return (certDecoded, certName) - } else if let certName = secret.name.data(using: .utf8) { - logger.info("Certificate for \(secret.name) does not have a name tag, using secret name instead") - return (certDecoded, certName) - } else { - throw OpenSSHCertificateError.parsingFailed } + let certName = Data(secret.name.utf8) + logger.info("Certificate for \(secret.name) does not have a name tag, using secret name instead") + return (certDecoded, certName) } } diff --git a/Sources/Packages/Sources/SecretKit/OpenSSH/OpenSSHKeyWriter.swift b/Sources/Packages/Sources/SecretKit/OpenSSH/OpenSSHKeyWriter.swift index 2539296..7906757 100644 --- a/Sources/Packages/Sources/SecretKit/OpenSSH/OpenSSHKeyWriter.swift +++ b/Sources/Packages/Sources/SecretKit/OpenSSH/OpenSSHKeyWriter.swift @@ -11,8 +11,8 @@ public struct OpenSSHKeyWriter: Sendable { /// Generates an OpenSSH data payload identifying the secret. /// - Returns: OpenSSH data payload identifying the secret. public func data(secret: SecretType) -> Data { - lengthAndData(of: curveType(for: secret.keyType).data(using: .utf8)!) + - lengthAndData(of: curveIdentifier(for: secret.keyType).data(using: .utf8)!) + + lengthAndData(of: Data(curveType(for: secret.keyType).utf8)) + + lengthAndData(of: Data(curveIdentifier(for: secret.keyType).utf8)) + lengthAndData(of: secret.publicKey) } diff --git a/Sources/Packages/Sources/SecretKit/PublicKeyStandinFileController.swift b/Sources/Packages/Sources/SecretKit/PublicKeyStandinFileController.swift index 736c0f8..ce3dcbe 100644 --- a/Sources/Packages/Sources/SecretKit/PublicKeyStandinFileController.swift +++ b/Sources/Packages/Sources/SecretKit/PublicKeyStandinFileController.swift @@ -32,7 +32,7 @@ public final class PublicKeyFileStoreController: Sendable { try? FileManager.default.createDirectory(at: URL(fileURLWithPath: directory), withIntermediateDirectories: false, attributes: nil) for secret in secrets { let path = publicKeyPath(for: secret) - guard let data = keyWriter.openSSHString(secret: secret).data(using: .utf8) else { continue } + let data = Data(keyWriter.openSSHString(secret: secret).utf8) FileManager.default.createFile(atPath: path, contents: data, attributes: nil) } logger.log("Finished writing public keys") diff --git a/Sources/Packages/Sources/SecureEnclaveSecretKit/SecureEnclaveStores/SecureEnclaveCryptoKitStore.swift b/Sources/Packages/Sources/SecureEnclaveSecretKit/SecureEnclaveStores/SecureEnclaveCryptoKitStore.swift index e7764a0..79c95d4 100644 --- a/Sources/Packages/Sources/SecureEnclaveSecretKit/SecureEnclaveStores/SecureEnclaveCryptoKitStore.swift +++ b/Sources/Packages/Sources/SecureEnclaveSecretKit/SecureEnclaveStores/SecureEnclaveCryptoKitStore.swift @@ -20,7 +20,7 @@ extension SecureEnclave { private let persistentAuthenticationHandler = PersistentAuthenticationHandler() /// Initializes a Store. - @MainActor public init() { + @MainActor init() { loadSecrets() Task { for await _ in DistributedNotificationCenter.default().notifications(named: .secretStoreUpdated) { @@ -33,7 +33,7 @@ extension SecureEnclave { // MARK: SecretStore - public func sign(data: Data, with secret: Secret, for provenance: SigningRequestProvenance) async throws -> Data { + func sign(data: Data, with secret: Secret, for provenance: SigningRequestProvenance) async throws -> Data { var context: LAContext if let existing = await persistentAuthenticationHandler.existingPersistedAuthenticationContext(secret: secret) { context = existing.context @@ -84,7 +84,7 @@ extension SecureEnclave { } - public func verify(signature: Data, for data: Data, with secret: Secret) throws -> Bool { + func verify(signature: Data, for data: Data, with secret: Secret) throws -> Bool { let context = LAContext() context.localizedReason = String(localized: "auth_context_request_verify_description_\(secret.name)") context.localizedCancelTitle = String(localized: "auth_context_request_deny_button") @@ -119,22 +119,22 @@ extension SecureEnclave { return verified } - public func existingPersistedAuthenticationContext(secret: Secret) async -> PersistedAuthenticationContext? { + func existingPersistedAuthenticationContext(secret: Secret) async -> PersistedAuthenticationContext? { await persistentAuthenticationHandler.existingPersistedAuthenticationContext(secret: secret) } - public func persistAuthentication(secret: Secret, forDuration duration: TimeInterval) async throws { + func persistAuthentication(secret: Secret, forDuration duration: TimeInterval) async throws { try await persistentAuthenticationHandler.persistAuthentication(secret: secret, forDuration: duration) } - @MainActor public func reloadSecrets() { + @MainActor func reloadSecrets() { secrets.removeAll() loadSecrets() } // MARK: SecretStoreModifiable - public func create(name: String, attributes: Attributes) async throws { + func create(name: String, attributes: Attributes) async throws { var accessError: SecurityError? let flags: SecAccessControlCreateFlags = switch attributes.authentication { case .notRequired: @@ -174,7 +174,7 @@ extension SecureEnclave { await reloadSecrets() } - public func delete(secret: Secret) async throws { + func delete(secret: Secret) async throws { let deleteAttributes = KeychainDictionary([ kSecClass: Constants.keyClass, kSecAttrService: SecureEnclave.Constants.keyTag, @@ -188,7 +188,7 @@ extension SecureEnclave { await reloadSecrets() } - public func update(secret: Secret, name: String, attributes: Attributes) async throws { + func update(secret: Secret, name: String, attributes: Attributes) async throws { let updateQuery = KeychainDictionary([ kSecClass: kSecClassKey, kSecAttrApplicationLabel: secret.id as CFData @@ -205,7 +205,7 @@ extension SecureEnclave { await reloadSecrets() } - public var supportedKeyTypes: [KeyType] { + var supportedKeyTypes: [KeyType] { [ .init(algorithm: .ecdsa, size: 256), .init(algorithm: .mldsa, size: 65), @@ -245,7 +245,7 @@ extension SecureEnclave.CryptoKitStore { switch (attributes.keyType.algorithm, attributes.keyType.size) { case (.ecdsa, 256): let key = try CryptoKit.SecureEnclave.P256.Signing.PrivateKey(dataRepresentation: keyData) - publicKey = key.publicKey.rawRepresentation + publicKey = key.publicKey.x963Representation case (.mldsa, 65): guard #available(macOS 26.0, *) else { throw UnsupportedAlgorithmError() } let key = try CryptoKit.SecureEnclave.MLDSA65.PrivateKey(dataRepresentation: keyData) diff --git a/Sources/Packages/Sources/SecureEnclaveSecretKit/SecureEnclaveStores/SecureEnclaveVanillaKeychainStore.swift b/Sources/Packages/Sources/SecureEnclaveSecretKit/SecureEnclaveStores/SecureEnclaveVanillaKeychainStore.swift index a28723f..d12dcb0 100644 --- a/Sources/Packages/Sources/SecureEnclaveSecretKit/SecureEnclaveStores/SecureEnclaveVanillaKeychainStore.swift +++ b/Sources/Packages/Sources/SecureEnclaveSecretKit/SecureEnclaveStores/SecureEnclaveVanillaKeychainStore.swift @@ -8,22 +8,22 @@ import SecretKit extension SecureEnclave { /// An implementation of Store backed by the Secure Enclave. - @Observable public final class VanillaKeychainStore: SecretStoreModifiable { + @Observable final class VanillaKeychainStore: SecretStoreModifiable { - @MainActor public var secrets: [Secret] = [] - public var isAvailable: Bool { + @MainActor var secrets: [Secret] = [] + var isAvailable: Bool { CryptoKit.SecureEnclave.isAvailable } - public let id = UUID() - public let name = String(localized: .secureEnclave) - public var supportedKeyTypes: [KeyType] { + let id = UUID() + let name = String(localized: .secureEnclave) + var supportedKeyTypes: [KeyType] { [KeyType(algorithm: .ecdsa, size: 256)] } private let persistentAuthenticationHandler = PersistentAuthenticationHandler() /// Initializes a Store. - @MainActor public init() { + @MainActor init() { loadSecrets() } @@ -31,7 +31,7 @@ extension SecureEnclave { // MARK: SecretStore - public func sign(data: Data, with secret: Secret, for provenance: SigningRequestProvenance) async throws -> Data { + func sign(data: Data, with secret: Secret, for provenance: SigningRequestProvenance) async throws -> Data { let context: LAContext if let existing = await persistentAuthenticationHandler.existingPersistedAuthenticationContext(secret: secret) { context = existing.context @@ -68,26 +68,26 @@ extension SecureEnclave { return signature as Data } - public func existingPersistedAuthenticationContext(secret: Secret) async -> PersistedAuthenticationContext? { + func existingPersistedAuthenticationContext(secret: Secret) async -> PersistedAuthenticationContext? { await persistentAuthenticationHandler.existingPersistedAuthenticationContext(secret: secret) } - public func persistAuthentication(secret: Secret, forDuration duration: TimeInterval) async throws { + func persistAuthentication(secret: Secret, forDuration duration: TimeInterval) async throws { try await persistentAuthenticationHandler.persistAuthentication(secret: secret, forDuration: duration) } - @MainActor public func reloadSecrets() { + @MainActor func reloadSecrets() { secrets.removeAll() loadSecrets() } // MARK: SecretStoreModifiable - public func create(name: String, attributes: Attributes) async throws { + func create(name: String, attributes: Attributes) async throws { throw DeprecatedCreationStore() } - public func delete(secret: Secret) async throws { + func delete(secret: Secret) async throws { let deleteAttributes = KeychainDictionary([ kSecClass: kSecClassKey, kSecAttrApplicationLabel: secret.id as CFData @@ -99,7 +99,7 @@ extension SecureEnclave { await reloadSecrets() } - public func update(secret: Secret, name: String, attributes: Attributes) async throws { + func update(secret: Secret, name: String, attributes: Attributes) async throws { let updateQuery = KeychainDictionary([ kSecClass: kSecClassKey, kSecAttrApplicationLabel: secret.id as CFData diff --git a/Sources/Packages/Tests/SecretAgentKitTests/StubStore.swift b/Sources/Packages/Tests/SecretAgentKitTests/StubStore.swift index b168614..c649daa 100644 --- a/Sources/Packages/Tests/SecretAgentKitTests/StubStore.swift +++ b/Sources/Packages/Tests/SecretAgentKitTests/StubStore.swift @@ -79,9 +79,9 @@ extension Stub { struct Secret: SecretKit.Secret, CustomDebugStringConvertible { - let id = UUID().uuidString.data(using: .utf8)! + let id = Data(UUID().uuidString.utf8) let name = UUID().uuidString - let algorithm = Algorithm.ellipticCurve + let algorithm = Algorithm.ecdsa let keySize: Int let publicKey: Data diff --git a/Sources/Packages/Tests/SecretKitTests/AnySecretTests.swift b/Sources/Packages/Tests/SecretKitTests/AnySecretTests.swift index f8229bd..3675270 100644 --- a/Sources/Packages/Tests/SecretKitTests/AnySecretTests.swift +++ b/Sources/Packages/Tests/SecretKitTests/AnySecretTests.swift @@ -7,12 +7,12 @@ import Testing @Suite struct AnySecretTests { @Test func eraser() { - let secret = SmartCard.Secret(id: UUID().uuidString.data(using: .utf8)!, name: "Name", algorithm: .ellipticCurve, keySize: 256, publicKey: UUID().uuidString.data(using: .utf8)!) + let data = Data(UUID().uuidString.utf8) + let secret = SmartCard.Secret(id: data, name: "Name", publicKey: data, attributes: Attributes(keyType: KeyType(algorithm: .ecdsa, size: 256))) let erased = AnySecret(secret) #expect(erased.id == secret.id as AnyHashable) #expect(erased.name == secret.name) - #expect(erased.algorithm == secret.algorithm) - #expect(erased.keySize == secret.keySize) + #expect(erased.keyType == secret.keyType) #expect(erased.publicKey == secret.publicKey) } diff --git a/Sources/Packages/Tests/SecretKitTests/OpenSSHWriterTests.swift b/Sources/Packages/Tests/SecretKitTests/OpenSSHWriterTests.swift index e471992..1cb5ec7 100644 --- a/Sources/Packages/Tests/SecretKitTests/OpenSSHWriterTests.swift +++ b/Sources/Packages/Tests/SecretKitTests/OpenSSHWriterTests.swift @@ -18,7 +18,7 @@ import Testing @Test func ecdsa256PublicKey() { #expect(writer.openSSHString(secret: Constants.ecdsa256Secret) == - "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBOVEjgAA5PHqRgwykjN5qM21uWCHFSY/Sqo5gkHAkn+e1MMQKHOLga7ucB9b3mif33MBid59GRK9GEPVlMiSQwo=") + "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBOVEjgAA5PHqRgwykjN5qM21uWCHFSY/Sqo5gkHAkn+e1MMQKHOLga7ucB9b3mif33MBid59GRK9GEPVlMiSQwo= test@example.com") } @Test func ecdsa256Hash() { @@ -35,7 +35,7 @@ import Testing @Test func ecdsa384PublicKey() { #expect(writer.openSSHString(secret: Constants.ecdsa384Secret) == - "ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBG2MNc/C5OTHFE2tBvbZCVcpOGa8vBMquiTLkH4lwkeqOPxhi+PyYUfQZMTRJNPiTyWPoMBqNiCIFRVv60yPN/AHufHaOgbdTP42EgMlMMImkAjYUEv9DESHTVIs2PW1yQ==") + "ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBG2MNc/C5OTHFE2tBvbZCVcpOGa8vBMquiTLkH4lwkeqOPxhi+PyYUfQZMTRJNPiTyWPoMBqNiCIFRVv60yPN/AHufHaOgbdTP42EgMlMMImkAjYUEv9DESHTVIs2PW1yQ== test@example.com") } @Test func ecdsa384Hash() { @@ -47,8 +47,8 @@ import Testing extension OpenSSHWriterTests { enum Constants { - static let ecdsa256Secret = SmartCard.Secret(id: Data(), name: "Test Key (ECDSA 256)", algorithm: .ellipticCurve, keySize: 256, publicKey: Data(base64Encoded: "BOVEjgAA5PHqRgwykjN5qM21uWCHFSY/Sqo5gkHAkn+e1MMQKHOLga7ucB9b3mif33MBid59GRK9GEPVlMiSQwo=")!) - static let ecdsa384Secret = SmartCard.Secret(id: Data(), name: "Test Key (ECDSA 384)", algorithm: .ellipticCurve, keySize: 384, publicKey: Data(base64Encoded: "BG2MNc/C5OTHFE2tBvbZCVcpOGa8vBMquiTLkH4lwkeqOPxhi+PyYUfQZMTRJNPiTyWPoMBqNiCIFRVv60yPN/AHufHaOgbdTP42EgMlMMImkAjYUEv9DESHTVIs2PW1yQ==")!) + static let ecdsa256Secret = SmartCard.Secret(id: Data(), name: "Test Key (ECDSA 256)", publicKey: Data(base64Encoded: "BOVEjgAA5PHqRgwykjN5qM21uWCHFSY/Sqo5gkHAkn+e1MMQKHOLga7ucB9b3mif33MBid59GRK9GEPVlMiSQwo=")!, attributes: Attributes(keyType: KeyType(algorithm: .ecdsa, size: 256), publicKeyAttribution: "test@example.com")) + static let ecdsa384Secret = SmartCard.Secret(id: Data(), name: "Test Key (ECDSA 384)", publicKey: Data(base64Encoded: "BG2MNc/C5OTHFE2tBvbZCVcpOGa8vBMquiTLkH4lwkeqOPxhi+PyYUfQZMTRJNPiTyWPoMBqNiCIFRVv60yPN/AHufHaOgbdTP42EgMlMMImkAjYUEv9DESHTVIs2PW1yQ==")!, attributes: Attributes(keyType: KeyType(algorithm: .ecdsa, size: 384), publicKeyAttribution: "test@example.com")) } diff --git a/Sources/Secretive/Controllers/ShellConfigurationController.swift b/Sources/Secretive/Controllers/ShellConfigurationController.swift index 2f3e4c6..2ecb17e 100644 --- a/Sources/Secretive/Controllers/ShellConfigurationController.swift +++ b/Sources/Secretive/Controllers/ShellConfigurationController.swift @@ -56,7 +56,7 @@ struct ShellConfigurationController { } catch { return false } - handle.write("\n# Secretive Config\n\(shellInstructions.text)\n".data(using: .utf8)!) + handle.write(Data("\n# Secretive Config\n\(shellInstructions.text)\n".utf8)) return true } diff --git a/Sources/Secretive/Preview Content/PreviewStore.swift b/Sources/Secretive/Preview Content/PreviewStore.swift index 924e6bc..ff8f8da 100644 --- a/Sources/Secretive/Preview Content/PreviewStore.swift +++ b/Sources/Secretive/Preview Content/PreviewStore.swift @@ -9,7 +9,7 @@ extension Preview { let id = UUID().uuidString let name: String - let publicKey = UUID().uuidString.data(using: .utf8)! + let publicKey = Data(UUID().uuidString.utf8) var attributes: Attributes { Attributes( keyType: .init(algorithm: .ecdsa, size: 256),