From 8f4d0b8eda0e531b7bc83435b9bcb0b7c979e0b3 Mon Sep 17 00:00:00 2001 From: Max Goedjen Date: Tue, 26 Aug 2025 22:41:01 -0700 Subject: [PATCH] Static vars for keytypes (#639) * Static inits for keytype. * Missed --- .../Sources/SecretKit/KeychainTypes.swift | 8 ++-- .../OpenSSH/OpenSSHPublicKeyWriter.swift | 15 ++++---- .../Sources/SecretKit/Types/Secret.swift | 10 ++++- .../SecureEnclaveStore.swift | 38 ++++++++++--------- .../Preview Content/PreviewStore.swift | 16 +++++--- 5 files changed, 50 insertions(+), 37 deletions(-) diff --git a/Sources/Packages/Sources/SecretKit/KeychainTypes.swift b/Sources/Packages/Sources/SecretKit/KeychainTypes.swift index debb2e1..9d08c65 100644 --- a/Sources/Packages/Sources/SecretKit/KeychainTypes.swift +++ b/Sources/Packages/Sources/SecretKit/KeychainTypes.swift @@ -53,12 +53,12 @@ public extension SecretStore { /// - secret: The secret which will be used for signing. /// - Returns: The appropriate algorithm. func signatureAlgorithm(for secret: SecretType) -> SecKeyAlgorithm? { - switch (secret.keyType.algorithm, secret.keyType.size) { - case (.ecdsa, 256): + switch secret.keyType { + case .ecdsa256: .ecdsaSignatureMessageX962SHA256 - case (.ecdsa, 384): + case .ecdsa384: .ecdsaSignatureMessageX962SHA384 - case (.rsa, 2048): + case .rsa2048: .rsaSignatureMessagePKCS1v15SHA512 default: nil diff --git a/Sources/Packages/Sources/SecretKit/OpenSSH/OpenSSHPublicKeyWriter.swift b/Sources/Packages/Sources/SecretKit/OpenSSH/OpenSSHPublicKeyWriter.swift index d809755..2c7f446 100644 --- a/Sources/Packages/Sources/SecretKit/OpenSSH/OpenSSHPublicKeyWriter.swift +++ b/Sources/Packages/Sources/SecretKit/OpenSSH/OpenSSHPublicKeyWriter.swift @@ -75,16 +75,16 @@ extension OpenSSHPublicKeyWriter { /// - length: The key length of the algorithm. /// - Returns: The OpenSSH identifier for the algorithm. public func openSSHIdentifier(for keyType: KeyType) -> String { - switch (keyType.algorithm, keyType.size) { - case (.ecdsa, 256): + switch keyType { + case .ecdsa256: "ecdsa-sha2-nistp256" - case (.ecdsa, 384): + case .ecdsa384: "ecdsa-sha2-nistp384" - case (.mldsa, 65): + case .mldsa65: "ssh-mldsa-65" - case (.mldsa, 87): + case .mldsa87: "ssh-mldsa-87" - case (.rsa, _): + case .rsa2048: "ssh-rsa" default: "unknown" @@ -101,8 +101,7 @@ extension OpenSSHPublicKeyWriter { // [4 byte prefix][2 byte prefix][n][2 byte prefix][e] // Rather than parse out the whole ASN.1 blob, we'll cheat and pull values directly since // we only support one key type, and the keychain always gives it in a specific format. - let keySize = secret.keyType.size - guard secret.keyType.algorithm == .rsa && keySize == 2048 else { fatalError() } + guard secret.keyType == .rsa2048 else { fatalError() } let length = secret.keyType.size/8 let data = secret.publicKey let n = Data(data[8..<(9+length)]) diff --git a/Sources/Packages/Sources/SecretKit/Types/Secret.swift b/Sources/Packages/Sources/SecretKit/Types/Secret.swift index 0f74b48..6b952f6 100644 --- a/Sources/Packages/Sources/SecretKit/Types/Secret.swift +++ b/Sources/Packages/Sources/SecretKit/Types/Secret.swift @@ -32,7 +32,13 @@ public extension Secret { /// The type of algorithm the Secret uses. public struct KeyType: Hashable, Sendable, Codable, CustomStringConvertible { - + + public static let ecdsa256 = KeyType(algorithm: .ecdsa, size: 256) + public static let ecdsa384 = KeyType(algorithm: .ecdsa, size: 384) + public static let mldsa65 = KeyType(algorithm: .mldsa, size: 65) + public static let mldsa87 = KeyType(algorithm: .mldsa, size: 87) + public static let rsa2048 = KeyType(algorithm: .rsa, size: 2048) + public enum Algorithm: Hashable, Sendable, Codable { case ecdsa case mldsa @@ -41,7 +47,7 @@ public struct KeyType: Hashable, Sendable, Codable, CustomStringConvertible { public var algorithm: Algorithm public var size: Int - + public init(algorithm: Algorithm, size: Int) { self.algorithm = algorithm self.size = size diff --git a/Sources/Packages/Sources/SecureEnclaveSecretKit/SecureEnclaveStore.swift b/Sources/Packages/Sources/SecureEnclaveSecretKit/SecureEnclaveStore.swift index 725ad87..1296189 100644 --- a/Sources/Packages/Sources/SecureEnclaveSecretKit/SecureEnclaveStore.swift +++ b/Sources/Packages/Sources/SecureEnclaveSecretKit/SecureEnclaveStore.swift @@ -66,15 +66,15 @@ extension SecureEnclave { } let attributes = try JSONDecoder().decode(Attributes.self, from: attributesData) - switch (attributes.keyType.algorithm, attributes.keyType.size) { - case (.ecdsa, 256): + switch attributes.keyType { + case .ecdsa256: let key = try CryptoKit.SecureEnclave.P256.Signing.PrivateKey(dataRepresentation: keyData, authenticationContext: context) return try key.signature(for: data).rawRepresentation - case (.mldsa, 65): + case .mldsa65: guard #available(macOS 26.0, *) else { throw UnsupportedAlgorithmError() } let key = try CryptoKit.SecureEnclave.MLDSA65.PrivateKey(dataRepresentation: keyData) return try key.signature(for: data) - case (.mldsa, 87): + case .mldsa87: guard #available(macOS 26.0, *) else { throw UnsupportedAlgorithmError() } let key = try CryptoKit.SecureEnclave.MLDSA87.PrivateKey(dataRepresentation: keyData) return try key.signature(for: data) @@ -119,15 +119,15 @@ extension SecureEnclave { throw error.takeRetainedValue() as Error } let dataRep: Data - switch (attributes.keyType.algorithm, attributes.keyType.size) { - case (.ecdsa, 256): + switch attributes.keyType { + case .ecdsa256: let created = try CryptoKit.SecureEnclave.P256.Signing.PrivateKey(accessControl: access!) dataRep = created.dataRepresentation - case (.mldsa, 65): + case .mldsa65: guard #available(macOS 26.0, *) else { throw Attributes.UnsupportedOptionError() } let created = try CryptoKit.SecureEnclave.MLDSA65.PrivateKey(accessControl: access!) dataRep = created.dataRepresentation - case (.mldsa, 87): + case .mldsa87: guard #available(macOS 26.0, *) else { throw Attributes.UnsupportedOptionError() } let created = try CryptoKit.SecureEnclave.MLDSA87.PrivateKey(accessControl: access!) dataRep = created.dataRepresentation @@ -172,11 +172,15 @@ extension SecureEnclave { } public var supportedKeyTypes: [KeyType] { - [ - .init(algorithm: .ecdsa, size: 256), - .init(algorithm: .mldsa, size: 65), - .init(algorithm: .mldsa, size: 87), - ] + if #available(macOS 26, *) { + [ + .ecdsa256, + .mldsa65, + .mldsa87, + ] + } else { + [.ecdsa256] + } } } @@ -220,15 +224,15 @@ extension SecureEnclave.Store { let attributes = try JSONDecoder().decode(Attributes.self, from: attributesData) let keyData = $0[kSecValueData] as! Data let publicKey: Data - switch (attributes.keyType.algorithm, attributes.keyType.size) { - case (.ecdsa, 256): + switch attributes.keyType { + case .ecdsa256: let key = try CryptoKit.SecureEnclave.P256.Signing.PrivateKey(dataRepresentation: keyData) publicKey = key.publicKey.x963Representation - case (.mldsa, 65): + case .mldsa65: guard #available(macOS 26.0, *) else { throw UnsupportedAlgorithmError() } let key = try CryptoKit.SecureEnclave.MLDSA65.PrivateKey(dataRepresentation: keyData) publicKey = key.publicKey.rawRepresentation - case (.mldsa, 87): + case .mldsa87: guard #available(macOS 26.0, *) else { throw UnsupportedAlgorithmError() } let key = try CryptoKit.SecureEnclave.MLDSA87.PrivateKey(dataRepresentation: keyData) publicKey = key.publicKey.rawRepresentation diff --git a/Sources/Secretive/Preview Content/PreviewStore.swift b/Sources/Secretive/Preview Content/PreviewStore.swift index ff8f8da..8897023 100644 --- a/Sources/Secretive/Preview Content/PreviewStore.swift +++ b/Sources/Secretive/Preview Content/PreviewStore.swift @@ -61,13 +61,17 @@ extension Preview { var name: String { "Modifiable Preview Store" } let secrets: [Secret] var supportedKeyTypes: [KeyType] { - [ - .init(algorithm: .ecdsa, size: 256), - .init(algorithm: .mldsa, size: 65), - .init(algorithm: .mldsa, size: 87), - ] + if #available(macOS 26, *) { + [ + .ecdsa256, + .mldsa65, + .mldsa87, + ] + } else { + [.ecdsa256] + } } - + init(secrets: [Secret]) { self.secrets = secrets }