This commit is contained in:
Max Goedjen
2025-09-26 00:19:32 -07:00
parent 267fe4bf27
commit fd95771fed
7 changed files with 103 additions and 286 deletions

View File

@@ -75,14 +75,14 @@ extension Updater {
.reversed()
.filter({ !$0.prerelease })
.first(where: { $0.minimumOSVersion <= osVersion }) else { return }
guard !userIgnored(release: release) else { return }
guard !release.prerelease else { return }
let latestVersion = SemVer(release.name)
if latestVersion > currentVersion {
// guard !userIgnored(release: release) else { return }
// guard !release.prerelease else { return }
// let latestVersion = SemVer(release.name)
// if latestVersion > currentVersion {
await MainActor.run {
state.update = release
}
}
// }
}
/// Checks whether the user has ignored a release.

View File

@@ -0,0 +1,91 @@
import Foundation
import Security
import CryptoTokenKit
import CryptoKit
import os
import SSHProtocolKit
public struct CertificateKitMigrator {
private let logger = Logger(subsystem: "com.maxgoedjen.secretive.migration", category: "CertificateKitMigrator")
let directory: URL
/// Initializes a PublicKeyFileStoreController.
public init(homeDirectory: URL) {
directory = homeDirectory.appending(component: "PublicKeys")
}
@MainActor public func migrate() throws {
let fileCerts = try FileManager.default
.contentsOfDirectory(atPath: directory.path())
.filter { $0.hasSuffix("-cert.pub") }
Task {
for path in fileCerts {
let url = directory.appending(component: path)
let data = try! Data(contentsOf: url)
// let parser = try! await XPCCertificateParser()
let parser = OpenSSHCertificateParser()
let cert = try! await parser.parse(data: data)
print(cert)
// let secret = storeList.allSecrets.first { secret in
// secret.name == cert.name
// }
// guard let secret = secret ?? storeList.allSecrets.first else { return }
// print(cert.data.formatted(.hex()))
// certificateStore.saveCertificate(cert.data, for: secret)
print(cert)
}
}
// let privateAttributes = KeychainDictionary([
// kSecClass: kSecClassKey,
// kSecAttrKeyType: Constants.oldKeyType,
// kSecAttrApplicationTag: SecureEnclave.Store.Constants.keyTag,
// kSecAttrKeyClass: kSecAttrKeyClassPrivate,
// kSecReturnRef: true,
// kSecMatchLimit: kSecMatchLimitAll,
// kSecReturnAttributes: true
// ])
// var privateUntyped: CFTypeRef?
// unsafe SecItemCopyMatching(privateAttributes, &privateUntyped)
// guard let privateTyped = privateUntyped as? [[CFString: Any]] else { return }
// let migratedPublicKeys = Set(store.secrets.map(\.publicKey))
// var migratedAny = false
// for key in privateTyped {
// let name = key[kSecAttrLabel] as? String ?? String(localized: .unnamedSecret)
// let id = key[kSecAttrApplicationLabel] as! Data
// guard !id.contains(Constants.migrationMagicNumber) else {
// logger.log("Skipping \(name), already migrated.")
// continue
// }
// let ref = key[kSecValueRef] as! SecKey
// let attributes = SecKeyCopyAttributes(ref) as! [CFString: Any]
// let tokenObjectID = unsafe attributes[Constants.tokenObjectID] as! Data
// let accessControl = attributes[kSecAttrAccessControl] as! SecAccessControl
// // Best guess.
// let auth: AuthenticationRequirement = String(describing: accessControl)
// .contains("DeviceOwnerAuthentication") ? .presenceRequired : .unknown
// do {
// let parsed = try CryptoKit.SecureEnclave.P256.Signing.PrivateKey(dataRepresentation: tokenObjectID)
// let secret = Secret(id: UUID().uuidString, name: name, publicKey: parsed.publicKey.x963Representation, attributes: Attributes(keyType: .init(algorithm: .ecdsa, size: 256), authentication: auth))
// guard !migratedPublicKeys.contains(parsed.publicKey.x963Representation) else {
// logger.log("Skipping \(name), public key already present. Marking as migrated.")
// markMigrated(secret: secret, oldID: id)
// continue
// }
// logger.log("Migrating \(name).")
// try store.saveKey(tokenObjectID, name: name, attributes: secret.attributes)
// logger.log("Migrated \(name).")
// markMigrated(secret: secret, oldID: id)
// migratedAny = true
// } catch {
// logger.error("Failed to migrate \(name): \(error.localizedDescription).")
// }
// }
// if migratedAny {
// store.reloadSecrets()
// }
}
}

View File

@@ -77,16 +77,7 @@ public struct OpenSSHCertificateParser: OpenSSHCertificateParserProtocol, Sendab
}
let validAfter = try dataParser.readNextBytes(as: UInt64.self, convertEndianness: true)
let validBefore = try dataParser.readNextBytes(as: UInt64.self, convertEndianness: true)
let validityRange = Date(timeIntervalSince1970: TimeInterval(validAfter))..<Date(timeIntervalSince1970: TimeInterval(validBefore
))
let criticalOptionsReader = try dataParser.readNextChunkAsSubReader()
let extensionsReader = try dataParser.readNextChunkAsSubReader()
_ = try dataParser.readNextChunk() // reserved
let signatureKey = try dataParser.readNextChunk()
let signature = try dataParser.readNextChunk()
print(pkw(data: signatureKey), pkw(data: publicKey), pkw(data: signature))
let validityRange = Date(timeIntervalSince1970: TimeInterval(validAfter))..<Date(timeIntervalSince1970: TimeInterval(validBefore))
return OpenSSHCertificate(
type: type,
@@ -103,13 +94,6 @@ public struct OpenSSHCertificateParser: OpenSSHCertificateParserProtocol, Sendab
}
}
func pkw(data: Data) -> String {
let base64 = Data(SHA256.hash(data: data)).base64EncodedString()
let paddingRange = base64.index(base64.endIndex, offsetBy: -2)..<base64.endIndex
let cleaned = base64.replacingOccurrences(of: "=", with: "", range: paddingRange)
return "SHA256:\(cleaned)"
}
}
public enum OpenSSHCertificateError: Error, Codable {