diff --git a/.github/readme/apple_watch_auth_mac.png b/.github/readme/apple_watch_auth_mac.png index 6bd1e06..7038307 100644 Binary files a/.github/readme/apple_watch_auth_mac.png and b/.github/readme/apple_watch_auth_mac.png differ diff --git a/.github/readme/touchid.png b/.github/readme/touchid.png index e651a27..079e6c1 100644 Binary files a/.github/readme/touchid.png and b/.github/readme/touchid.png differ diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 471d75c..24563b8 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -25,7 +25,7 @@ jobs: runs-on: macOS-latest timeout-minutes: 10 steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v2 - name: Create Release id: create_release uses: actions/create-release@v1 diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f078ca6..cdc8de4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -6,7 +6,7 @@ jobs: runs-on: macOS-latest timeout-minutes: 10 steps: - - uses: actions/checkout@v1 + - uses: actions/checkout@v2 - name: Set Environment run: sudo xcrun xcode-select -s /Applications/Xcode_12_beta.app - name: Test diff --git a/Brief/Updater.swift b/Brief/Updater.swift index a4a524f..010cb14 100644 --- a/Brief/Updater.swift +++ b/Brief/Updater.swift @@ -45,26 +45,15 @@ extension Updater { func evaluate(release: Release) { guard !userIgnored(release: release) else { return } guard !release.prerelease else { return } - let latestVersion = semVer(from: release.name) - let currentVersion = semVer(from: Bundle.main.infoDictionary!["CFBundleShortVersionString"] as! String) - for (latest, current) in zip(latestVersion, currentVersion) { - if latest > current { - DispatchQueue.main.async { - self.update = release - } - return + let latestVersion = SemVer(release.name) + let currentVersion = SemVer(Bundle.main.infoDictionary!["CFBundleShortVersionString"] as! String) + if latestVersion > currentVersion { + DispatchQueue.main.async { + self.update = release } } } - func semVer(from stringVersion: String) -> [Int] { - var split = stringVersion.split(separator: ".").compactMap { Int($0) } - while split.count < 3 { - split.append(0) - } - return split - } - func userIgnored(release: Release) -> Bool { guard !release.critical else { return false } return defaults.bool(forKey: release.name) @@ -75,6 +64,38 @@ extension Updater { } } +struct SemVer { + + let versionNumbers: [Int] + + init(_ version: String) { + // Betas have the format 1.2.3_beta1 + let strippedBeta = version.split(separator: "_").first! + var split = strippedBeta.split(separator: ".").compactMap { Int($0) } + while split.count < 3 { + split.append(0) + } + versionNumbers = split + } + +} + +extension SemVer: Comparable { + + static func < (lhs: SemVer, rhs: SemVer) -> Bool { + for (latest, current) in zip(lhs.versionNumbers, rhs.versionNumbers) { + if latest < current { + return true + } else if latest > current { + return false + } + } + return false + } + + +} + extension Updater { enum Constants { diff --git a/BriefTests/BriefTests.swift b/BriefTests/BriefTests.swift new file mode 100644 index 0000000..79a4be1 --- /dev/null +++ b/BriefTests/BriefTests.swift @@ -0,0 +1,30 @@ +import XCTest +@testable import Brief + +class SemVerTests: XCTestCase { + + func testEqual() { + let current = SemVer("1.0.2") + let old = SemVer("1.0.2") + XCTAssert(!(current > old)) + } + + func testPatchGreaterButMinorLess() { + let current = SemVer("1.1.0") + let old = SemVer("1.0.2") + XCTAssert(current > old) + } + + func testMajorSameMinorGreater() { + let current = SemVer("1.0.2") + let new = SemVer("1.0.3") + XCTAssert(current < new) + } + + func testBeta() { + let current = SemVer("1.0.2") + let new = SemVer("1.1.0_beta1") + XCTAssert(current < new) + } + +} diff --git a/BriefTests/Info.plist b/BriefTests/Info.plist new file mode 100644 index 0000000..64d65ca --- /dev/null +++ b/BriefTests/Info.plist @@ -0,0 +1,22 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/Config/Secretive.xctestplan b/Config/Secretive.xctestplan index 25eec62..1ec79fb 100644 --- a/Config/Secretive.xctestplan +++ b/Config/Secretive.xctestplan @@ -36,6 +36,14 @@ "identifier" : "50617D9323FCE48E0099B055", "name" : "SecretiveTests" } + }, + { + "parallelizable" : true, + "target" : { + "containerPath" : "container:Secretive.xcodeproj", + "identifier" : "5091D31E2519D56D0049FD9B", + "name" : "BriefTests" + } } ], "version" : 1 diff --git a/SecretAgent/Notifier.swift b/SecretAgent/Notifier.swift index cf580f7..8167a54 100644 --- a/SecretAgent/Notifier.swift +++ b/SecretAgent/Notifier.swift @@ -26,9 +26,9 @@ class Notifier { func notify(accessTo secret: AnySecret, by provenance: SigningRequestProvenance) { let notificationCenter = UNUserNotificationCenter.current() let notificationContent = UNMutableNotificationContent() - notificationContent.title = "Signed Request from \(provenance.origin.name)" + notificationContent.title = "Signed Request from \(provenance.origin.displayName)" notificationContent.subtitle = "Using secret \"\(secret.name)\"" - if let iconURL = iconURL(for: provenance), let attachment = try? UNNotificationAttachment(identifier: "icon", url: iconURL, options: nil) { + if let iconURL = provenance.origin.iconURL, let attachment = try? UNNotificationAttachment(identifier: "icon", url: iconURL, options: nil) { notificationContent.attachments = [attachment] } let request = UNNotificationRequest(identifier: UUID().uuidString, content: notificationContent, trigger: nil) @@ -54,23 +54,6 @@ class Notifier { } -extension Notifier { - - func iconURL(for provenance: SigningRequestProvenance) -> URL? { - do { - if let app = NSRunningApplication(processIdentifier: provenance.origin.pid), let icon = app.icon?.tiffRepresentation { - let temporaryURL = URL(fileURLWithPath: (NSTemporaryDirectory() as NSString).appendingPathComponent("\(UUID().uuidString).png")) - let bitmap = NSBitmapImageRep(data: icon) - try bitmap?.representation(using: .png, properties: [:])?.write(to: temporaryURL) - return temporaryURL - } - } catch { - } - return nil - } - -} - extension Notifier: SigningWitness { func speakNowOrForeverHoldYourPeace(forAccessTo secret: AnySecret, by provenance: SigningRequestProvenance) throws { diff --git a/SecretAgentKit/Agent.swift b/SecretAgentKit/Agent.swift index 879ca92..02727c3 100644 --- a/SecretAgentKit/Agent.swift +++ b/SecretAgentKit/Agent.swift @@ -93,7 +93,7 @@ extension Agent { } let dataToSign = reader.readNextChunk() - let derSignature = try store.sign(data: dataToSign, with: secret) + let derSignature = try store.sign(data: dataToSign, with: secret, for: provenance) let curveData = writer.curveType(for: secret.algorithm, length: secret.keySize).data(using: .utf8)! diff --git a/SecretAgentKit/SigningRequestTracer.swift b/SecretAgentKit/SigningRequestTracer.swift index 8c6288d..54923ce 100644 --- a/SecretAgentKit/SigningRequestTracer.swift +++ b/SecretAgentKit/SigningRequestTracer.swift @@ -1,8 +1,12 @@ import Foundation import AppKit import Security +import SecretKit struct SigningRequestTracer { +} + +extension SigningRequestTracer { func provenance(from fileHandleReader: FileHandleReader) -> SigningRequestProvenance { let firstInfo = process(from: fileHandleReader.pidOfConnectedProcess) @@ -33,7 +37,24 @@ struct SigningRequestTracer { let flags: SecCSFlags = [.considerExpiration, .enforceRevocationChecks] SecCodeCreateWithPID(pid, SecCSFlags(), &secCode) let valid = SecCodeCheckValidity(secCode.takeRetainedValue(), flags, nil) == errSecSuccess - return SigningRequestProvenance.Process(pid: pid, name: procName, path: path, validSignature: valid, parentPID: ppid) + return SigningRequestProvenance.Process(pid: pid, processName: procName, appName: appName(for: pid), iconURL: iconURL(for: pid), path: path, validSignature: valid, parentPID: ppid) + } + + func iconURL(for pid: Int32) -> URL? { + do { + if let app = NSRunningApplication(processIdentifier: pid), let icon = app.icon?.tiffRepresentation { + let temporaryURL = URL(fileURLWithPath: (NSTemporaryDirectory() as NSString).appendingPathComponent("\(UUID().uuidString).png")) + let bitmap = NSBitmapImageRep(data: icon) + try bitmap?.representation(using: .png, properties: [:])?.write(to: temporaryURL) + return temporaryURL + } + } catch { + } + return nil + } + + func appName(for pid: Int32) -> String? { + NSRunningApplication(processIdentifier: pid)?.localizedName } } diff --git a/SecretAgentKitTests/AgentTests.swift b/SecretAgentKitTests/AgentTests.swift index e068b7b..2c3e29e 100644 --- a/SecretAgentKitTests/AgentTests.swift +++ b/SecretAgentKitTests/AgentTests.swift @@ -106,7 +106,7 @@ class AgentTests: XCTestCase { let agent = Agent(storeList: list, witness: witness) agent.handle(reader: stubReader, writer: stubWriter) XCTAssertEqual(witnessTrace, speakNowTrace) - XCTAssertEqual(witnessTrace.origin.name, "Finder") + XCTAssertEqual(witnessTrace.origin.displayName, "Finder") XCTAssertEqual(witnessTrace.origin.validSignature, true) XCTAssertEqual(witnessTrace.origin.parentPID, 1) } diff --git a/SecretAgentKitTests/StubStore.swift b/SecretAgentKitTests/StubStore.swift index a226796..c96092c 100644 --- a/SecretAgentKitTests/StubStore.swift +++ b/SecretAgentKitTests/StubStore.swift @@ -48,7 +48,7 @@ extension Stub { print("Public Key OpenSSH: \(OpenSSHKeyWriter().openSSHString(secret: secret))") } - public func sign(data: Data, with secret: Secret) throws -> Data { + public func sign(data: Data, with secret: Secret, for provenance: SigningRequestProvenance) throws -> Data { guard !shouldThrow else { throw NSError() } diff --git a/SecretKit/Common/Erasers/AnySecretStore.swift b/SecretKit/Common/Erasers/AnySecretStore.swift index 12b1ea0..99f88cb 100644 --- a/SecretKit/Common/Erasers/AnySecretStore.swift +++ b/SecretKit/Common/Erasers/AnySecretStore.swift @@ -8,7 +8,7 @@ public class AnySecretStore: SecretStore { private let _id: () -> UUID private let _name: () -> String private let _secrets: () -> [AnySecret] - private let _sign: (Data, AnySecret) throws -> Data + private let _sign: (Data, AnySecret, SigningRequestProvenance) throws -> Data private var sink: AnyCancellable? public init(_ secretStore: SecretStoreType) where SecretStoreType: SecretStore { @@ -17,7 +17,7 @@ public class AnySecretStore: SecretStore { _name = { secretStore.name } _id = { secretStore.id } _secrets = { secretStore.secrets.map { AnySecret($0) } } - _sign = { try secretStore.sign(data: $0, with: $1.base as! SecretStoreType.SecretType) } + _sign = { try secretStore.sign(data: $0, with: $1.base as! SecretStoreType.SecretType, for: $2) } sink = secretStore.objectWillChange.sink { _ in self.objectWillChange.send() } @@ -39,8 +39,8 @@ public class AnySecretStore: SecretStore { return _secrets() } - public func sign(data: Data, with secret: AnySecret) throws -> Data { - try _sign(data, secret) + public func sign(data: Data, with secret: AnySecret, for provenance: SigningRequestProvenance) throws -> Data { + try _sign(data, secret, provenance) } } diff --git a/SecretKit/Common/Types/SecretStore.swift b/SecretKit/Common/Types/SecretStore.swift index ef0488d..2ab51aa 100644 --- a/SecretKit/Common/Types/SecretStore.swift +++ b/SecretKit/Common/Types/SecretStore.swift @@ -9,7 +9,7 @@ public protocol SecretStore: ObservableObject, Identifiable { var name: String { get } var secrets: [SecretType] { get } - func sign(data: Data, with secret: SecretType) throws -> Data + func sign(data: Data, with secret: SecretType, for provenance: SigningRequestProvenance) throws -> Data } diff --git a/SecretAgentKit/SigningRequestProvenance.swift b/SecretKit/Common/Types/SigningRequestProvenance.swift similarity index 55% rename from SecretAgentKit/SigningRequestProvenance.swift rename to SecretKit/Common/Types/SigningRequestProvenance.swift index b112ae5..271c8c0 100644 --- a/SecretAgentKit/SigningRequestProvenance.swift +++ b/SecretKit/Common/Types/SigningRequestProvenance.swift @@ -17,7 +17,7 @@ extension SigningRequestProvenance { } public var intact: Bool { - return chain.reduce(true) { $0 && $1.validSignature } + chain.allSatisfy { $0.validSignature } } } @@ -27,19 +27,27 @@ extension SigningRequestProvenance { public struct Process: Equatable { public let pid: Int32 - public let name: String + public let processName: String + public let appName: String? + public let iconURL: URL? public let path: String public let validSignature: Bool - let parentPID: Int32? + public let parentPID: Int32? - init(pid: Int32, name: String, path: String, validSignature: Bool, parentPID: Int32?) { + public init(pid: Int32, processName: String, appName: String?, iconURL: URL?, path: String, validSignature: Bool, parentPID: Int32?) { self.pid = pid - self.name = name + self.processName = processName + self.appName = appName + self.iconURL = iconURL self.path = path self.validSignature = validSignature self.parentPID = parentPID } + public var displayName: String { + appName ?? processName + } + } } diff --git a/SecretKit/SecureEnclave/SecureEnclaveStore.swift b/SecretKit/SecureEnclave/SecureEnclaveStore.swift index a0e00a2..c355553 100644 --- a/SecretKit/SecureEnclave/SecureEnclaveStore.swift +++ b/SecretKit/SecureEnclave/SecureEnclaveStore.swift @@ -1,6 +1,7 @@ import Foundation import Security import CryptoTokenKit +import LocalAuthentication extension SecureEnclave { @@ -75,7 +76,10 @@ extension SecureEnclave { reloadSecrets() } - public func sign(data: Data, with secret: SecretType) throws -> Data { + public func sign(data: Data, with secret: SecretType, for provenance: SigningRequestProvenance) throws -> Data { + let context = LAContext() + context.localizedReason = "sign a request from \"\(provenance.origin.displayName)\" using secret \"\(secret.name)\"" + context.localizedCancelTitle = "Deny" let attributes = [ kSecClass: kSecClassKey, kSecAttrKeyClass: kSecAttrKeyClassPrivate, @@ -83,6 +87,7 @@ extension SecureEnclave { kSecAttrKeyType: Constants.keyType, kSecAttrTokenID: kSecAttrTokenIDSecureEnclave, kSecAttrApplicationTag: Constants.keyTag, + kSecUseAuthenticationContext: context, kSecReturnRef: true ] as CFDictionary var untyped: CFTypeRef? diff --git a/SecretKit/SmartCard/SmartCardStore.swift b/SecretKit/SmartCard/SmartCardStore.swift index 2fdbe4d..236ec0c 100644 --- a/SecretKit/SmartCard/SmartCardStore.swift +++ b/SecretKit/SmartCard/SmartCardStore.swift @@ -1,6 +1,7 @@ import Foundation import Security import CryptoTokenKit +import LocalAuthentication // TODO: Might need to split this up into "sub-stores?" // ie, each token has its own Store. @@ -43,13 +44,17 @@ extension SmartCard { fatalError("Keys must be deleted on the smart card.") } - public func sign(data: Data, with secret: SecretType) throws -> Data { + public func sign(data: Data, with secret: SecretType, for provenance: SigningRequestProvenance) throws -> Data { guard let tokenID = tokenID else { fatalError() } + let context = LAContext() + context.localizedReason = "sign a request from \"\(provenance.origin.displayName)\" using secret \"\(secret.name)\"" + context.localizedCancelTitle = "Deny" let attributes = [ kSecClass: kSecClassKey, kSecAttrKeyClass: kSecAttrKeyClassPrivate, kSecAttrApplicationLabel: secret.id as CFData, kSecAttrTokenID: tokenID, + kSecUseAuthenticationContext: context, kSecReturnRef: true ] as CFDictionary var untyped: CFTypeRef? diff --git a/Secretive.xcodeproj/project.pbxproj b/Secretive.xcodeproj/project.pbxproj index bc24f35..21bb736 100644 --- a/Secretive.xcodeproj/project.pbxproj +++ b/Secretive.xcodeproj/project.pbxproj @@ -11,6 +11,7 @@ 50153E20250AFCB200525160 /* UpdateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50153E1F250AFCB200525160 /* UpdateView.swift */; }; 50153E22250DECA300525160 /* SecretListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50153E21250DECA300525160 /* SecretListView.swift */; }; 5018F54F24064786002EB505 /* Notifier.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5018F54E24064786002EB505 /* Notifier.swift */; }; + 501B7AE1251C56F700776EC7 /* SigningRequestProvenance.swift in Sources */ = {isa = PBXBuildFile; fileRef = 507CE4F32420A8C10029F750 /* SigningRequestProvenance.swift */; }; 50524B442420969E008DBD97 /* OpenSSHWriterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50524B432420969D008DBD97 /* OpenSSHWriterTests.swift */; }; 50571E0324393C2600F76F6C /* JustUpdatedChecker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50571E0224393C2600F76F6C /* JustUpdatedChecker.swift */; }; 50571E0524393D1500F76F6C /* LaunchAgentController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50571E0424393D1500F76F6C /* LaunchAgentController.swift */; }; @@ -49,7 +50,6 @@ 507CE4ED2420A3C70029F750 /* Agent.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50A3B79F24026B9900D209EA /* Agent.swift */; }; 507CE4EE2420A3CA0029F750 /* SocketController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 50A3B79D24026B9900D209EA /* SocketController.swift */; }; 507CE4F02420A4C50029F750 /* SigningWitness.swift in Sources */ = {isa = PBXBuildFile; fileRef = 507CE4EF2420A4C50029F750 /* SigningWitness.swift */; }; - 507CE4F42420A8C10029F750 /* SigningRequestProvenance.swift in Sources */ = {isa = PBXBuildFile; fileRef = 507CE4F32420A8C10029F750 /* SigningRequestProvenance.swift */; }; 507CE4F62420A96F0029F750 /* SigningRequestTracer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 507CE4F52420A96F0029F750 /* SigningRequestTracer.swift */; }; 507EE34224281E12003C4FE3 /* FileHandleProtocols.swift in Sources */ = {isa = PBXBuildFile; fileRef = 507EE34124281E12003C4FE3 /* FileHandleProtocols.swift */; }; 507EE34624281F89003C4FE3 /* StubFileHandleReader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 507EE34524281F89003C4FE3 /* StubFileHandleReader.swift */; }; @@ -62,6 +62,8 @@ 508A5911241EF09C0069DC07 /* SecretAgentKit.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 5099A06C240242BA0062B6F2 /* SecretAgentKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 508A5913241EF0B20069DC07 /* SecretKit.framework in CopyFiles */ = {isa = PBXBuildFile; fileRef = 50617DA823FCE4AB0099B055 /* SecretKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 5091D2BC25183B830049FD9B /* ApplicationDirectoryController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5091D2BB25183B830049FD9B /* ApplicationDirectoryController.swift */; }; + 5091D3222519D56D0049FD9B /* BriefTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5091D3212519D56D0049FD9B /* BriefTests.swift */; }; + 5091D3242519D56D0049FD9B /* Brief.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 506772FB2426F3F400034DED /* Brief.framework */; }; 5099A02423FD2AAA0062B6F2 /* CreateSecretView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5099A02323FD2AAA0062B6F2 /* CreateSecretView.swift */; }; 5099A02723FE34FA0062B6F2 /* SmartCard.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5099A02623FE34FA0062B6F2 /* SmartCard.swift */; }; 5099A02923FE35240062B6F2 /* SmartCardStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5099A02823FE35240062B6F2 /* SmartCardStore.swift */; }; @@ -141,6 +143,13 @@ remoteGlobalIDString = 50617DA723FCE4AB0099B055; remoteInfo = SecretKit; }; + 5091D3252519D56D0049FD9B /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 50617D7723FCE48D0099B055 /* Project object */; + proxyType = 1; + remoteGlobalIDString = 506772FA2426F3F400034DED; + remoteInfo = Brief; + }; 5099A076240242BA0062B6F2 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 50617D7723FCE48D0099B055 /* Project object */; @@ -266,6 +275,9 @@ 508A58B4241ED48F0069DC07 /* PreviewAgentStatusChecker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PreviewAgentStatusChecker.swift; sourceTree = ""; }; 508A590F241EEF6D0069DC07 /* Secretive.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = Secretive.xctestplan; sourceTree = ""; }; 5091D2BB25183B830049FD9B /* ApplicationDirectoryController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApplicationDirectoryController.swift; sourceTree = ""; }; + 5091D31F2519D56D0049FD9B /* BriefTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = BriefTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; + 5091D3212519D56D0049FD9B /* BriefTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BriefTests.swift; sourceTree = ""; }; + 5091D3232519D56D0049FD9B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 5099A02323FD2AAA0062B6F2 /* CreateSecretView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateSecretView.swift; sourceTree = ""; }; 5099A02623FE34FA0062B6F2 /* SmartCard.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SmartCard.swift; sourceTree = ""; }; 5099A02823FE35240062B6F2 /* SmartCardStore.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SmartCardStore.swift; sourceTree = ""; }; @@ -331,6 +343,14 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 5091D31C2519D56D0049FD9B /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 5091D3242519D56D0049FD9B /* Brief.framework in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 5099A069240242BA0062B6F2 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -361,6 +381,7 @@ 504BA92D243171F20064740E /* Types */ = { isa = PBXGroup; children = ( + 507CE4F32420A8C10029F750 /* SigningRequestProvenance.swift */, 50617DCA23FCECA10099B055 /* Secret.swift */, 50617DC623FCE4EA0099B055 /* SecretStore.swift */, ); @@ -379,6 +400,7 @@ 5099A07A240242BA0062B6F2 /* SecretAgentKitTests */, 508A58AF241E144C0069DC07 /* Config */, 506772FC2426F3F400034DED /* Brief */, + 5091D3202519D56D0049FD9B /* BriefTests */, 50617D8023FCE48E0099B055 /* Products */, 5099A08B240243730062B6F2 /* Frameworks */, ); @@ -395,6 +417,7 @@ 5099A074240242BA0062B6F2 /* SecretAgentKitTests.xctest */, 50A3B78A24026B7500D209EA /* SecretAgent.app */, 506772FB2426F3F400034DED /* Brief.framework */, + 5091D31F2519D56D0049FD9B /* BriefTests.xctest */, ); name = Products; sourceTree = ""; @@ -534,6 +557,15 @@ path = Controllers; sourceTree = ""; }; + 5091D3202519D56D0049FD9B /* BriefTests */ = { + isa = PBXGroup; + children = ( + 5091D3212519D56D0049FD9B /* BriefTests.swift */, + 5091D3232519D56D0049FD9B /* Info.plist */, + ); + path = BriefTests; + sourceTree = ""; + }; 5099A02523FE34DE0062B6F2 /* SmartCard */ = { isa = PBXGroup; children = ( @@ -562,7 +594,6 @@ 5099A089240242C20062B6F2 /* SSHAgentProtocol.swift */, 50A3B79D24026B9900D209EA /* SocketController.swift */, 507CE4EF2420A4C50029F750 /* SigningWitness.swift */, - 507CE4F32420A8C10029F750 /* SigningRequestProvenance.swift */, 507CE4F52420A96F0029F750 /* SigningRequestTracer.swift */, 50A3B79F24026B9900D209EA /* Agent.swift */, 507EE34124281E12003C4FE3 /* FileHandleProtocols.swift */, @@ -737,6 +768,24 @@ productReference = 506772FB2426F3F400034DED /* Brief.framework */; productType = "com.apple.product-type.framework"; }; + 5091D31E2519D56D0049FD9B /* BriefTests */ = { + isa = PBXNativeTarget; + buildConfigurationList = 5091D32A2519D56D0049FD9B /* Build configuration list for PBXNativeTarget "BriefTests" */; + buildPhases = ( + 5091D31B2519D56D0049FD9B /* Sources */, + 5091D31C2519D56D0049FD9B /* Frameworks */, + 5091D31D2519D56D0049FD9B /* Resources */, + ); + buildRules = ( + ); + dependencies = ( + 5091D3262519D56D0049FD9B /* PBXTargetDependency */, + ); + name = BriefTests; + productName = BriefTests; + productReference = 5091D31F2519D56D0049FD9B /* BriefTests.xctest */; + productType = "com.apple.product-type.bundle.unit-test"; + }; 5099A06B240242BA0062B6F2 /* SecretAgentKit */ = { isa = PBXNativeTarget; buildConfigurationList = 5099A083240242BA0062B6F2 /* Build configuration list for PBXNativeTarget "SecretAgentKit" */; @@ -802,7 +851,7 @@ 50617D7723FCE48D0099B055 /* Project object */ = { isa = PBXProject; attributes = { - LastSwiftUpdateCheck = 1140; + LastSwiftUpdateCheck = 1220; LastUpgradeCheck = 1130; ORGANIZATIONNAME = "Max Goedjen"; TargetAttributes = { @@ -824,6 +873,9 @@ CreatedOnToolsVersion = 11.4; LastSwiftMigration = 1140; }; + 5091D31E2519D56D0049FD9B = { + CreatedOnToolsVersion = 12.2; + }; 5099A06B240242BA0062B6F2 = { CreatedOnToolsVersion = 11.4; LastSwiftMigration = 1140; @@ -857,6 +909,7 @@ 5099A06B240242BA0062B6F2 /* SecretAgentKit */, 5099A073240242BA0062B6F2 /* SecretAgentKitTests */, 506772FA2426F3F400034DED /* Brief */, + 5091D31E2519D56D0049FD9B /* BriefTests */, ); }; /* End PBXProject section */ @@ -900,6 +953,13 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 5091D31D2519D56D0049FD9B /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; 5099A06A240242BA0062B6F2 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -966,6 +1026,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + 501B7AE1251C56F700776EC7 /* SigningRequestProvenance.swift in Sources */, 50617DC723FCE4EA0099B055 /* SecretStore.swift in Sources */, 5099A02723FE34FA0062B6F2 /* SmartCard.swift in Sources */, 50617DCB23FCECA10099B055 /* Secret.swift in Sources */, @@ -1000,6 +1061,14 @@ ); runOnlyForDeploymentPostprocessing = 0; }; + 5091D31B2519D56D0049FD9B /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + 5091D3222519D56D0049FD9B /* BriefTests.swift in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; 5099A068240242BA0062B6F2 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -1010,7 +1079,6 @@ 507CE4ED2420A3C70029F750 /* Agent.swift in Sources */, 507CE4F02420A4C50029F750 /* SigningWitness.swift in Sources */, 507CE4F62420A96F0029F750 /* SigningRequestTracer.swift in Sources */, - 507CE4F42420A8C10029F750 /* SigningRequestProvenance.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -1078,6 +1146,11 @@ target = 50617DA723FCE4AB0099B055 /* SecretKit */; targetProxy = 507CE4F12420A6B50029F750 /* PBXContainerItemProxy */; }; + 5091D3262519D56D0049FD9B /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + target = 506772FA2426F3F400034DED /* Brief */; + targetProxy = 5091D3252519D56D0049FD9B /* PBXContainerItemProxy */; + }; 5099A077240242BA0062B6F2 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 5099A06B240242BA0062B6F2 /* SecretAgentKit */; @@ -1729,6 +1802,64 @@ }; name = Test; }; + 5091D3272519D56D0049FD9B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = Z72PRUAWF6; + INFOPLIST_FILE = BriefTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/../Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.maxgoedjen.BriefTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + }; + name = Debug; + }; + 5091D3282519D56D0049FD9B /* Test */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CODE_SIGN_STYLE = Manual; + COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = ""; + INFOPLIST_FILE = BriefTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/../Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.maxgoedjen.BriefTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + PROVISIONING_PROFILE_SPECIFIER = ""; + SWIFT_VERSION = 5.0; + }; + name = Test; + }; + 5091D3292519D56D0049FD9B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; + CODE_SIGN_STYLE = Automatic; + COMBINE_HIDPI_IMAGES = YES; + DEVELOPMENT_TEAM = Z72PRUAWF6; + INFOPLIST_FILE = BriefTests/Info.plist; + LD_RUNPATH_SEARCH_PATHS = ( + "$(inherited)", + "@executable_path/../Frameworks", + "@loader_path/../Frameworks", + ); + PRODUCT_BUNDLE_IDENTIFIER = com.maxgoedjen.BriefTests; + PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 5.0; + }; + name = Release; + }; 5099A084240242BA0062B6F2 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { @@ -1941,6 +2072,16 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; + 5091D32A2519D56D0049FD9B /* Build configuration list for PBXNativeTarget "BriefTests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 5091D3272519D56D0049FD9B /* Debug */, + 5091D3282519D56D0049FD9B /* Test */, + 5091D3292519D56D0049FD9B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; 5099A083240242BA0062B6F2 /* Build configuration list for PBXNativeTarget "SecretAgentKit" */ = { isa = XCConfigurationList; buildConfigurations = ( diff --git a/Secretive/Credits.rtf b/Secretive/Credits.rtf index c7aec0a..170fa74 100644 --- a/Secretive/Credits.rtf +++ b/Secretive/Credits.rtf @@ -20,4 +20,5 @@ Special Thanks To:\ {\field{\*\fldinst{HYPERLINK "https://github.com/marksands"}}{\fldrslt Mark Sands}}\ {\field{\*\fldinst{HYPERLINK "https://github.com/mergesort"}}{\fldrslt Joe Fabisevich}}\ {\field{\*\fldinst{HYPERLINK "https://github.com/phillco"}}{\fldrslt Phil Cohen}}\ -{\field{\*\fldinst{HYPERLINK "https://github.com/zackdotcomputer"}}{\fldrslt Zack Sheppard}}} \ No newline at end of file +{\field{\*\fldinst{HYPERLINK "https://github.com/zackdotcomputer"}}{\fldrslt Zack Sheppard}}} +{\field{\*\fldinst{HYPERLINK "https://github.com/zacwest"}}{\fldrslt Zac West}}} diff --git a/Secretive/Preview Content/PreviewStore.swift b/Secretive/Preview Content/PreviewStore.swift index 892eaaa..40b79b9 100644 --- a/Secretive/Preview Content/PreviewStore.swift +++ b/Secretive/Preview Content/PreviewStore.swift @@ -35,7 +35,7 @@ extension Preview { self.secrets.append(contentsOf: new) } - func sign(data: Data, with secret: Preview.Secret) throws -> Data { + func sign(data: Data, with secret: Preview.Secret, for provenance: SigningRequestProvenance) throws -> Data { return data }