diff --git a/.github/workflows/nightly.yml b/.github/workflows/nightly.yml index b5f109c..53735cf 100644 --- a/.github/workflows/nightly.yml +++ b/.github/workflows/nightly.yml @@ -20,7 +20,7 @@ jobs: APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }} run: ./.github/scripts/signing.sh - name: Set Environment - run: sudo xcrun xcode-select -s /Applications/Xcode_26_beta_5.app + run: sudo xcrun xcode-select -s /Applications/Xcode_26.0.app - name: Update Build Number env: RUN_ID: ${{ github.run_id }} diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 0d8fb65..ebd0b01 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -21,9 +21,9 @@ jobs: APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }} run: ./.github/scripts/signing.sh - name: Set Environment - run: sudo xcrun xcode-select -s /Applications/Xcode_26_beta_5.app + run: sudo xcrun xcode-select -s /Applications/Xcode_26.0.app - name: Test - run: swift build --build-system swiftbuild --package-path Sources/Packages + run: swift test --build-system swiftbuild --package-path Sources/Packages build: # runs-on: macOS-latest runs-on: macos-15 @@ -44,7 +44,7 @@ jobs: APPLE_API_KEY_ID: ${{ secrets.APPLE_API_KEY_ID }} run: ./.github/scripts/signing.sh - name: Set Environment - run: sudo xcrun xcode-select -s /Applications/Xcode_26_beta_5.app + run: sudo xcrun xcode-select -s /Applications/Xcode_26.0.app - name: Update Build Number env: TAG_NAME: ${{ github.ref }} diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f471bc6..e790e2f 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -9,6 +9,8 @@ jobs: steps: - uses: actions/checkout@v5 - name: Set Environment - run: sudo xcrun xcode-select -s /Applications/Xcode_26_beta_5.app - - name: Test - run: swift build --build-system swiftbuild --package-path Sources/Packages + run: sudo xcrun xcode-select -s /Applications/Xcode_26.0.app + - name: Test Main Packages + run: swift test --build-system swiftbuild --package-path Sources/Packages + - name: Test SecretKit Packages + run: swift test --build-system swiftbuild diff --git a/Package.swift b/Package.swift new file mode 100644 index 0000000..700486e --- /dev/null +++ b/Package.swift @@ -0,0 +1,69 @@ +// swift-tools-version:6.2 +// The swift-tools-version declares the minimum version of Swift required to build this package. + +import PackageDescription + +// This is basically the same package as `Sources/Packages/Package.swift`, but thinned slightly. +// Ideally this would be the same package, but SPM requires it to be at the root of the project, +// and Xcode does _not_ like that, so they're separate. +let package = Package( + name: "SecretKit", + defaultLocalization: "en", + platforms: [ + .macOS(.v14) + ], + products: [ + .library( + name: "SecretKit", + targets: ["SecretKit"]), + .library( + name: "SecureEnclaveSecretKit", + targets: ["SecureEnclaveSecretKit"]), + .library( + name: "SmartCardSecretKit", + targets: ["SmartCardSecretKit"]), + ], + dependencies: [ + ], + targets: [ + .target( + name: "SecretKit", + dependencies: [], + path: "Sources/Packages/Sources/SecretKit", + resources: [localization], + swiftSettings: swiftSettings + ), + .testTarget( + name: "SecretKitTests", + dependencies: ["SecretKit", "SecureEnclaveSecretKit", "SmartCardSecretKit"], + path: "Sources/Packages/Tests/SecretKitTests", + swiftSettings: swiftSettings + ), + .target( + name: "SecureEnclaveSecretKit", + dependencies: ["SecretKit"], + path: "Sources/Packages/Sources/SecureEnclaveSecretKit", + resources: [localization], + swiftSettings: swiftSettings + ), + .target( + name: "SmartCardSecretKit", + dependencies: ["SecretKit"], + path: "Sources/Packages/Sources/SmartCardSecretKit", + resources: [localization], + swiftSettings: swiftSettings + ), + ] +) + +var localization: Resource { + .process("../../Localizable.xcstrings") +} + +var swiftSettings: [PackageDescription.SwiftSetting] { + [ + .swiftLanguageMode(.v6), + // This freaks out Xcode in a dependency context. + // .treatAllWarnings(as: .error), + ] +} diff --git a/README.md b/README.md index 50c32b2..21b10ea 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,7 @@ There's a [FAQ here](FAQ.md). ### Auditable Build Process -Builds are produced by GitHub Actions with an auditable build and release generation process. Each build has a "Document SHAs" step, which will output SHA checksums for the build produced by the GitHub Action, so you can verify that the source code for a given build corresponds to any given release. +Builds are produced by GitHub Actions with an auditable build and release generation process. Starting with Secretive 3.0, builds are attested using [GitHub Artifact Attestation](https://docs.github.com/en/actions/concepts/security/artifact-attestations). Attestations are viewable in the build log for a build, and also on the [main attestation page](https://github.com/maxgoedjen/secretive/attestations). ### A Note Around Code Signing and Keychains diff --git a/Sources/Packages/Package.swift b/Sources/Packages/Package.swift index 820da97..82322b2 100644 --- a/Sources/Packages/Package.swift +++ b/Sources/Packages/Package.swift @@ -36,47 +36,47 @@ let package = Package( name: "SecretKit", dependencies: [], resources: [localization], - swiftSettings: swiftSettings + swiftSettings: swiftSettings, ), .testTarget( name: "SecretKitTests", dependencies: ["SecretKit", "SecureEnclaveSecretKit", "SmartCardSecretKit"], - swiftSettings: swiftSettings + swiftSettings: swiftSettings, ), .target( name: "SecureEnclaveSecretKit", dependencies: ["SecretKit"], resources: [localization], - swiftSettings: swiftSettings + swiftSettings: swiftSettings, ), .target( name: "SmartCardSecretKit", dependencies: ["SecretKit"], resources: [localization], - swiftSettings: swiftSettings + swiftSettings: swiftSettings, ), .target( name: "SecretAgentKit", dependencies: ["SecretKit", "SecretAgentKitHeaders"], resources: [localization], - swiftSettings: swiftSettings + swiftSettings: swiftSettings, ), .systemLibrary( - name: "SecretAgentKitHeaders" + name: "SecretAgentKitHeaders", ), .testTarget( name: "SecretAgentKitTests", - dependencies: ["SecretAgentKit"]) - , + dependencies: ["SecretAgentKit"], + ), .target( name: "Brief", dependencies: [], resources: [localization], - swiftSettings: swiftSettings + swiftSettings: swiftSettings, ), .testTarget( name: "BriefTests", - dependencies: ["Brief"] + dependencies: ["Brief"], ), ] ) diff --git a/Sources/Packages/Sources/SecretKit/Erasers/AnySecret.swift b/Sources/Packages/Sources/SecretKit/Erasers/AnySecret.swift index eb7ef0f..cd48212 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 { - let base: Any + public let base: Any private let hashable: AnyHashable private let _id: () -> AnyHashable private let _name: () -> String diff --git a/Sources/Packages/Sources/SecretKit/Erasers/AnySecretStore.swift b/Sources/Packages/Sources/SecretKit/Erasers/AnySecretStore.swift index 3af4b8c..747abc5 100644 --- a/Sources/Packages/Sources/SecretKit/Erasers/AnySecretStore.swift +++ b/Sources/Packages/Sources/SecretKit/Erasers/AnySecretStore.swift @@ -1,8 +1,7 @@ import Foundation -import Combine /// Type eraser for SecretStore. -public class AnySecretStore: SecretStore, @unchecked Sendable { +open class AnySecretStore: SecretStore, @unchecked Sendable { let base: any Sendable private let _isAvailable: @MainActor @Sendable () -> Bool @@ -10,7 +9,6 @@ public class AnySecretStore: SecretStore, @unchecked Sendable { private let _name: @MainActor @Sendable () -> String private let _secrets: @MainActor @Sendable () -> [AnySecret] private let _sign: @Sendable (Data, AnySecret, SigningRequestProvenance) async throws -> Data - private let _verify: @Sendable (Data, Data, AnySecret) async throws -> Bool private let _existingPersistedAuthenticationContext: @Sendable (AnySecret) async -> PersistedAuthenticationContext? private let _persistAuthentication: @Sendable (AnySecret, TimeInterval) async throws -> Void private let _reloadSecrets: @Sendable () async -> Void @@ -22,7 +20,6 @@ public class AnySecretStore: SecretStore, @unchecked Sendable { _id = { secretStore.id } _secrets = { secretStore.secrets.map { AnySecret($0) } } _sign = { try await secretStore.sign(data: $0, with: $1.base as! SecretStoreType.SecretType, for: $2) } - _verify = { try await secretStore.verify(signature: $0, for: $1, with: $2.base as! SecretStoreType.SecretType) } _existingPersistedAuthenticationContext = { await secretStore.existingPersistedAuthenticationContext(secret: $0.base as! SecretStoreType.SecretType) } _persistAuthentication = { try await secretStore.persistAuthentication(secret: $0.base as! SecretStoreType.SecretType, forDuration: $1) } _reloadSecrets = { await secretStore.reloadSecrets() } @@ -48,10 +45,6 @@ public class AnySecretStore: SecretStore, @unchecked Sendable { try await _sign(data, secret, provenance) } - public func verify(signature: Data, for data: Data, with secret: AnySecret) async throws -> Bool { - try await _verify(signature, data, secret) - } - public func existingPersistedAuthenticationContext(secret: AnySecret) async -> PersistedAuthenticationContext? { await _existingPersistedAuthenticationContext(secret) } diff --git a/Sources/Packages/Sources/SecretKit/Types/SecretStore.swift b/Sources/Packages/Sources/SecretKit/Types/SecretStore.swift index d9d3edb..6308a5b 100644 --- a/Sources/Packages/Sources/SecretKit/Types/SecretStore.swift +++ b/Sources/Packages/Sources/SecretKit/Types/SecretStore.swift @@ -1,5 +1,4 @@ import Foundation -import Combine /// Manages access to Secrets, and performs signature operations on data using those Secrets. public protocol SecretStore: Identifiable, Sendable { @@ -23,14 +22,6 @@ public protocol SecretStore: Identifiable, Sendable { /// - Returns: The signed data. func sign(data: Data, with secret: SecretType, for provenance: SigningRequestProvenance) async throws -> Data - /// Verifies that a signature is valid over a specified payload. - /// - Parameters: - /// - signature: The signature over the data. - /// - data: The data to verify the signature of. - /// - secret: The secret whose signature to verify. - /// - Returns: Whether the signature was verified. - func verify(signature: Data, for data: Data, with secret: SecretType) async throws -> Bool - /// Checks to see if there is currently a valid persisted authentication for a given secret. /// - Parameters: /// - secret: The ``Secret`` to check if there is a persisted authentication for. diff --git a/Sources/Packages/Sources/SecureEnclaveSecretKit/SecureEnclaveSecret.swift b/Sources/Packages/Sources/SecureEnclaveSecretKit/SecureEnclaveSecret.swift index d6858c7..272c3a6 100644 --- a/Sources/Packages/Sources/SecureEnclaveSecretKit/SecureEnclaveSecret.swift +++ b/Sources/Packages/Sources/SecureEnclaveSecretKit/SecureEnclaveSecret.swift @@ -1,5 +1,4 @@ import Foundation -import Combine import SecretKit extension SecureEnclave { diff --git a/Sources/Packages/Sources/SecureEnclaveSecretKit/SecureEnclaveStore.swift b/Sources/Packages/Sources/SecureEnclaveSecretKit/SecureEnclaveStore.swift index d1134f5..3956525 100644 --- a/Sources/Packages/Sources/SecureEnclaveSecretKit/SecureEnclaveStore.swift +++ b/Sources/Packages/Sources/SecureEnclaveSecretKit/SecureEnclaveStore.swift @@ -73,41 +73,6 @@ extension SecureEnclave { return signature as Data } - public func verify(signature: Data, for data: Data, with secret: Secret) throws -> Bool { - let context = LAContext() - context.localizedReason = String(localized: .authContextRequestVerifyDescription(secretName: secret.name)) - context.localizedCancelTitle = String(localized: .authContextRequestDenyButton) - let attributes = KeychainDictionary([ - kSecClass: kSecClassKey, - kSecAttrKeyClass: kSecAttrKeyClassPrivate, - kSecAttrApplicationLabel: secret.id as CFData, - kSecAttrKeyType: Constants.keyType, - kSecAttrTokenID: kSecAttrTokenIDSecureEnclave, - kSecAttrApplicationTag: Constants.keyTag, - kSecUseAuthenticationContext: context, - kSecReturnRef: true - ]) - var verifyError: SecurityError? - var untyped: CFTypeRef? - let status = SecItemCopyMatching(attributes, &untyped) - if status != errSecSuccess { - throw KeychainError(statusCode: status) - } - guard let untypedSafe = untyped else { - throw KeychainError(statusCode: errSecSuccess) - } - let key = untypedSafe as! SecKey - let verified = SecKeyVerifySignature(key, .ecdsaSignatureMessageX962SHA256, data as CFData, signature as CFData, &verifyError) - if !verified, let verifyError { - if verifyError.takeUnretainedValue() ~= .verifyError { - return false - } else { - throw SigningError(error: verifyError) - } - } - return verified - } - public func existingPersistedAuthenticationContext(secret: Secret) async -> PersistedAuthenticationContext? { await persistentAuthenticationHandler.existingPersistedAuthenticationContext(secret: secret) } @@ -262,9 +227,9 @@ extension SecureEnclave.Store { extension SecureEnclave { - enum Constants { - static let keyTag = Data("com.maxgoedjen.secretive.secureenclave.key".utf8) - static let keyType = kSecAttrKeyTypeECSECPrimeRandom as String + public enum Constants { + public static let keyTag = Data("com.maxgoedjen.secretive.secureenclave.key".utf8) + public static let keyType = kSecAttrKeyTypeECSECPrimeRandom as String static let unauthenticatedThreshold: TimeInterval = 0.05 } diff --git a/Sources/Packages/Sources/SmartCardSecretKit/SmartCardSecret.swift b/Sources/Packages/Sources/SmartCardSecretKit/SmartCardSecret.swift index d73038a..977355e 100644 --- a/Sources/Packages/Sources/SmartCardSecretKit/SmartCardSecret.swift +++ b/Sources/Packages/Sources/SmartCardSecretKit/SmartCardSecret.swift @@ -1,5 +1,4 @@ import Foundation -import Combine import SecretKit extension SmartCard { diff --git a/Sources/Packages/Sources/SmartCardSecretKit/SmartCardStore.swift b/Sources/Packages/Sources/SmartCardSecretKit/SmartCardStore.swift index b42275e..39f84dc 100644 --- a/Sources/Packages/Sources/SmartCardSecretKit/SmartCardStore.swift +++ b/Sources/Packages/Sources/SmartCardSecretKit/SmartCardStore.swift @@ -1,7 +1,7 @@ import Foundation import Observation import Security -import CryptoTokenKit +@preconcurrency import CryptoTokenKit import LocalAuthentication import SecretKit @@ -23,6 +23,9 @@ extension SmartCard { public var isAvailable: Bool { state.isAvailable } + @MainActor public var smartcardTokenID: String? { + state.tokenID + } public let id = UUID() @MainActor public var name: String { @@ -34,17 +37,18 @@ extension SmartCard { /// Initializes a Store. public init() { - Task { @MainActor in - if let tokenID = state.tokenID { - state.isAvailable = true - state.watcher.addRemovalHandler(self.smartcardRemoved, forTokenID: tokenID) + Task { + await MainActor.run { + if let tokenID = smartcardTokenID { + state.isAvailable = true + state.watcher.addRemovalHandler(self.smartcardRemoved, forTokenID: tokenID) + } + loadSecrets() } - loadSecrets() - state.watcher.setInsertionHandler { id in - // Setting insertion handler will cause it to be called immediately. - // Make a thread jump so we don't hit a recursive lock attempt. + // Doing this inside a regular mainactor handler casues thread assertions in CryptoTokenKit to blow up when the handler executes. + await state.watcher.setInsertionHandler { id in Task { - self.smartcardInserted(for: id) + await self.smartcardInserted(for: id) } } } @@ -81,29 +85,6 @@ extension SmartCard { return signature as Data } - public func verify(signature: Data, for data: Data, with secret: Secret) throws -> Bool { - let attributes = KeychainDictionary([ - kSecAttrKeyType: secret.keyType.secAttrKeyType as Any, - kSecAttrKeySizeInBits: secret.keyType.size, - kSecAttrKeyClass: kSecAttrKeyClassPublic - ]) - var verifyError: SecurityError? - let untyped: CFTypeRef? = SecKeyCreateWithData(secret.publicKey as CFData, attributes, &verifyError) - guard let untypedSafe = untyped else { - throw KeychainError(statusCode: errSecSuccess) - } - let key = untypedSafe as! SecKey - let verified = SecKeyVerifySignature(key, signatureAlgorithm(for: secret, allowRSA: true), data as CFData, signature as CFData, &verifyError) - if !verified, let verifyError { - if verifyError.takeUnretainedValue() ~= .verifyError { - return false - } else { - throw SigningError(error: verifyError) - } - } - return verified - } - public func existingPersistedAuthenticationContext(secret: Secret) -> PersistedAuthenticationContext? { nil } @@ -135,12 +116,13 @@ extension SmartCard.Store { /// Resets the token ID and reloads secrets. /// - Parameter tokenID: The ID of the token that was inserted. @MainActor private func smartcardInserted(for tokenID: String? = nil) { - guard let string = state.watcher.nonSecureEnclaveTokens.first else { return } - guard state.tokenID == nil else { return } - guard !string.contains("setoken") else { return } - state.tokenID = string - state.watcher.addRemovalHandler(self.smartcardRemoved, forTokenID: string) - state.tokenID = string + guard let string = state.watcher.nonSecureEnclaveTokens.first else { return } + guard state.tokenID == nil else { return } + guard !string.contains("setoken") else { return } + state.tokenID = string + state.watcher.addRemovalHandler(self.smartcardRemoved, forTokenID: string) + state.tokenID = string + reloadSecretsInternal() } /// Resets the token ID and reloads secrets. @@ -188,88 +170,6 @@ extension SmartCard.Store { } - -// MARK: Smart Card specific encryption/decryption/verification -extension SmartCard.Store { - - /// Encrypts a payload with a specified key. - /// - Parameters: - /// - data: The payload to encrypt. - /// - secret: The secret to encrypt with. - /// - Returns: The encrypted data. - /// - Warning: Encryption functions are deliberately only exposed on a library level, and are not exposed in Secretive itself to prevent users from data loss. Any pull requests which expose this functionality in the app will not be merged. - public func encrypt(data: Data, with secret: SecretType) throws -> Data { - let context = LAContext() - context.localizedReason = String(localized: .authContextRequestEncryptDescription(secretName: secret.name)) - context.localizedCancelTitle = String(localized: .authContextRequestDenyButton) - let attributes = KeychainDictionary([ - kSecAttrKeyType: secret.keyType.secAttrKeyType as Any, - kSecAttrKeySizeInBits: secret.keyType.size, - kSecAttrKeyClass: kSecAttrKeyClassPublic, - kSecUseAuthenticationContext: context - ]) - var encryptError: SecurityError? - let untyped: CFTypeRef? = SecKeyCreateWithData(secret.publicKey as CFData, attributes, &encryptError) - guard let untypedSafe = untyped else { - throw KeychainError(statusCode: errSecSuccess) - } - let key = untypedSafe as! SecKey - guard let signature = SecKeyCreateEncryptedData(key, encryptionAlgorithm(for: secret), data as CFData, &encryptError) else { - throw SigningError(error: encryptError) - } - return signature as Data - } - - /// Decrypts a payload with a specified key. - /// - Parameters: - /// - data: The payload to decrypt. - /// - secret: The secret to decrypt with. - /// - Returns: The decrypted data. - /// - Warning: Encryption functions are deliberately only exposed on a library level, and are not exposed in Secretive itself to prevent users from data loss. Any pull requests which expose this functionality in the app will not be merged. - public func decrypt(data: Data, with secret: SecretType) async throws -> Data { - guard let tokenID = await state.tokenID else { fatalError() } - let context = LAContext() - context.localizedReason = String(localized: .authContextRequestDecryptDescription(secretName: secret.name)) - context.localizedCancelTitle = String(localized: .authContextRequestDenyButton) - let attributes = KeychainDictionary([ - kSecClass: kSecClassKey, - kSecAttrKeyClass: kSecAttrKeyClassPrivate, - kSecAttrApplicationLabel: secret.id as CFData, - kSecAttrTokenID: tokenID, - kSecUseAuthenticationContext: context, - kSecReturnRef: true - ]) - var untyped: CFTypeRef? - let status = SecItemCopyMatching(attributes, &untyped) - if status != errSecSuccess { - throw KeychainError(statusCode: status) - } - guard let untypedSafe = untyped else { - throw KeychainError(statusCode: errSecSuccess) - } - let key = untypedSafe as! SecKey - var encryptError: SecurityError? - guard let signature = SecKeyCreateDecryptedData(key, encryptionAlgorithm(for: secret), data as CFData, &encryptError) else { - throw SigningError(error: encryptError) - } - return signature as Data - } - - private func encryptionAlgorithm(for secret: SecretType) -> SecKeyAlgorithm { - switch (secret.keyType.algorithm, secret.keyType.size) { - case (.ecdsa, 256): - return .eciesEncryptionCofactorVariableIVX963SHA256AESGCM - case (.ecdsa, 384): - return .eciesEncryptionCofactorVariableIVX963SHA384AESGCM - case (.rsa, 1024), (.rsa, 2048): - return .rsaEncryptionOAEPSHA512AESGCM - default: - fatalError() - } - } - -} - extension TKTokenWatcher { /// All available tokens, excluding the Secure Enclave. diff --git a/Sources/Packages/Tests/SecretAgentKitTests/AgentTests.swift b/Sources/Packages/Tests/SecretAgentKitTests/AgentTests.swift index 63734ef..7cd519e 100644 --- a/Sources/Packages/Tests/SecretAgentKitTests/AgentTests.swift +++ b/Sources/Packages/Tests/SecretAgentKitTests/AgentTests.swift @@ -60,18 +60,10 @@ import CryptoKit } var rs = r rs.append(s) - let signature = try! P256.Signing.ECDSASignature(rawRepresentation: rs) - let referenceValid = try! P256.Signing.PublicKey(x963Representation: Constants.Secrets.ecdsa256Secret.publicKey).isValidSignature(signature, for: dataToSign) - let store = await list.stores.first! - let derVerifies = try await store.verify(signature: signature.derRepresentation, for: dataToSign, with: AnySecret(Constants.Secrets.ecdsa256Secret)) - let invalidRandomSignature = try await store.verify(signature: "invalid".data(using: .utf8)!, for: dataToSign, with: AnySecret(Constants.Secrets.ecdsa256Secret)) - let invalidRandomData = try await store.verify(signature: signature.derRepresentation, for: "invalid".data(using: .utf8)!, with: AnySecret(Constants.Secrets.ecdsa256Secret)) - let invalidWrongKey = try await store.verify(signature: signature.derRepresentation, for: dataToSign, with: AnySecret(Constants.Secrets.ecdsa384Secret)) - #expect(referenceValid) - #expect(derVerifies) - #expect(invalidRandomSignature == false) - #expect(invalidRandomData == false) - #expect(invalidWrongKey == false) + let signature = try P256.Signing.ECDSASignature(rawRepresentation: rs) + // Correct signature + #expect(try P256.Signing.PublicKey(x963Representation: Constants.Secrets.ecdsa256Secret.publicKey) + .isValidSignature(signature, for: dataToSign)) } // MARK: Witness protocol diff --git a/Sources/Packages/Tests/SecretAgentKitTests/StubStore.swift b/Sources/Packages/Tests/SecretAgentKitTests/StubStore.swift index a390e25..b168614 100644 --- a/Sources/Packages/Tests/SecretAgentKitTests/StubStore.swift +++ b/Sources/Packages/Tests/SecretAgentKitTests/StubStore.swift @@ -61,29 +61,6 @@ extension Stub { return SecKeyCreateSignature(privateKey, signatureAlgorithm(for: secret), data as CFData, nil)! as Data } - public func verify(signature: Data, for data: Data, with secret: Stub.Secret) throws -> Bool { - let attributes = KeychainDictionary([ - kSecAttrKeyType: secret.algorithm.secAttrKeyType, - kSecAttrKeySizeInBits: secret.keySize, - kSecAttrKeyClass: kSecAttrKeyClassPublic - ]) - var verifyError: Unmanaged? - let untyped: CFTypeRef? = SecKeyCreateWithData(secret.publicKey as CFData, attributes, &verifyError) - guard let untypedSafe = untyped else { - throw NSError(domain: "test", code: 0, userInfo: nil) - } - let key = untypedSafe as! SecKey - let verified = SecKeyVerifySignature(key, signatureAlgorithm(for: secret), data as CFData, signature as CFData, &verifyError) - if let verifyError { - if verifyError.takeUnretainedValue() ~= .verifyError { - return false - } else { - throw NSError(domain: "test", code: 0, userInfo: nil) - } - } - return verified - } - public func existingPersistedAuthenticationContext(secret: Stub.Secret) -> PersistedAuthenticationContext? { nil } diff --git a/Sources/SecretAgent/AppDelegate.swift b/Sources/SecretAgent/AppDelegate.swift index e11e188..86e187d 100644 --- a/Sources/SecretAgent/AppDelegate.swift +++ b/Sources/SecretAgent/AppDelegate.swift @@ -1,6 +1,5 @@ import Cocoa import OSLog -import Combine import SecretKit import SecureEnclaveSecretKit import SmartCardSecretKit @@ -28,7 +27,6 @@ class AppDelegate: NSObject, NSApplicationDelegate { let path = (NSHomeDirectory() as NSString).appendingPathComponent("socket.ssh") as String return SocketController(path: path) }() - private var updateSink: AnyCancellable? private let logger = Logger(subsystem: "com.maxgoedjen.secretive.secretagent", category: "AppDelegate") func applicationDidFinishLaunching(_ aNotification: Notification) { diff --git a/Sources/Secretive/Controllers/AgentStatusChecker.swift b/Sources/Secretive/Controllers/AgentStatusChecker.swift index 8ff234a..3c85f3f 100644 --- a/Sources/Secretive/Controllers/AgentStatusChecker.swift +++ b/Sources/Secretive/Controllers/AgentStatusChecker.swift @@ -1,5 +1,4 @@ import Foundation -import Combine import AppKit import SecretKit import Observation diff --git a/Sources/Secretive/Controllers/JustUpdatedChecker.swift b/Sources/Secretive/Controllers/JustUpdatedChecker.swift index 4e8ea72..7b25eef 100644 --- a/Sources/Secretive/Controllers/JustUpdatedChecker.swift +++ b/Sources/Secretive/Controllers/JustUpdatedChecker.swift @@ -1,5 +1,4 @@ import Foundation -import Combine import AppKit protocol JustUpdatedCheckerProtocol: Observable { diff --git a/Sources/Secretive/Preview Content/PreviewAgentStatusChecker.swift b/Sources/Secretive/Preview Content/PreviewAgentStatusChecker.swift index 5fce50d..51a5c09 100644 --- a/Sources/Secretive/Preview Content/PreviewAgentStatusChecker.swift +++ b/Sources/Secretive/Preview Content/PreviewAgentStatusChecker.swift @@ -1,5 +1,4 @@ import Foundation -import Combine class PreviewAgentStatusChecker: AgentStatusCheckerProtocol { diff --git a/Sources/Secretive/Preview Content/PreviewStore.swift b/Sources/Secretive/Preview Content/PreviewStore.swift index 57b291c..924e6bc 100644 --- a/Sources/Secretive/Preview Content/PreviewStore.swift +++ b/Sources/Secretive/Preview Content/PreviewStore.swift @@ -42,10 +42,6 @@ extension Preview { return data } - func verify(signature data: Data, for signature: Data, with secret: Preview.Secret) throws -> Bool { - true - } - func existingPersistedAuthenticationContext(secret: Preview.Secret) -> PersistedAuthenticationContext? { nil } @@ -85,10 +81,6 @@ extension Preview { return data } - func verify(signature data: Data, for signature: Data, with secret: Preview.Secret) throws -> Bool { - true - } - func existingPersistedAuthenticationContext(secret: Preview.Secret) -> PersistedAuthenticationContext? { nil } diff --git a/Sources/Secretive/Views/StoreListView.swift b/Sources/Secretive/Views/StoreListView.swift index c0e6d3e..2c0dc2c 100644 --- a/Sources/Secretive/Views/StoreListView.swift +++ b/Sources/Secretive/Views/StoreListView.swift @@ -1,5 +1,4 @@ import SwiftUI -import Combine import SecretKit struct StoreListView: View {