Static vars for keytypes (#639)

* Static inits for keytype.

* Missed
This commit is contained in:
Max Goedjen 2025-08-26 22:41:01 -07:00 committed by GitHub
parent c37d0c0cba
commit 8f4d0b8eda
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 50 additions and 37 deletions

View File

@ -53,12 +53,12 @@ public extension SecretStore {
/// - secret: The secret which will be used for signing. /// - secret: The secret which will be used for signing.
/// - Returns: The appropriate algorithm. /// - Returns: The appropriate algorithm.
func signatureAlgorithm(for secret: SecretType) -> SecKeyAlgorithm? { func signatureAlgorithm(for secret: SecretType) -> SecKeyAlgorithm? {
switch (secret.keyType.algorithm, secret.keyType.size) { switch secret.keyType {
case (.ecdsa, 256): case .ecdsa256:
.ecdsaSignatureMessageX962SHA256 .ecdsaSignatureMessageX962SHA256
case (.ecdsa, 384): case .ecdsa384:
.ecdsaSignatureMessageX962SHA384 .ecdsaSignatureMessageX962SHA384
case (.rsa, 2048): case .rsa2048:
.rsaSignatureMessagePKCS1v15SHA512 .rsaSignatureMessagePKCS1v15SHA512
default: default:
nil nil

View File

@ -75,16 +75,16 @@ extension OpenSSHPublicKeyWriter {
/// - length: The key length of the algorithm. /// - length: The key length of the algorithm.
/// - Returns: The OpenSSH identifier for the algorithm. /// - Returns: The OpenSSH identifier for the algorithm.
public func openSSHIdentifier(for keyType: KeyType) -> String { public func openSSHIdentifier(for keyType: KeyType) -> String {
switch (keyType.algorithm, keyType.size) { switch keyType {
case (.ecdsa, 256): case .ecdsa256:
"ecdsa-sha2-nistp256" "ecdsa-sha2-nistp256"
case (.ecdsa, 384): case .ecdsa384:
"ecdsa-sha2-nistp384" "ecdsa-sha2-nistp384"
case (.mldsa, 65): case .mldsa65:
"ssh-mldsa-65" "ssh-mldsa-65"
case (.mldsa, 87): case .mldsa87:
"ssh-mldsa-87" "ssh-mldsa-87"
case (.rsa, _): case .rsa2048:
"ssh-rsa" "ssh-rsa"
default: default:
"unknown" "unknown"
@ -101,8 +101,7 @@ extension OpenSSHPublicKeyWriter {
// [4 byte prefix][2 byte prefix][n][2 byte prefix][e] // [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 // 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. // we only support one key type, and the keychain always gives it in a specific format.
let keySize = secret.keyType.size guard secret.keyType == .rsa2048 else { fatalError() }
guard secret.keyType.algorithm == .rsa && keySize == 2048 else { fatalError() }
let length = secret.keyType.size/8 let length = secret.keyType.size/8
let data = secret.publicKey let data = secret.publicKey
let n = Data(data[8..<(9+length)]) let n = Data(data[8..<(9+length)])

View File

@ -33,6 +33,12 @@ public extension Secret {
/// The type of algorithm the Secret uses. /// The type of algorithm the Secret uses.
public struct KeyType: Hashable, Sendable, Codable, CustomStringConvertible { 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 { public enum Algorithm: Hashable, Sendable, Codable {
case ecdsa case ecdsa
case mldsa case mldsa

View File

@ -66,15 +66,15 @@ extension SecureEnclave {
} }
let attributes = try JSONDecoder().decode(Attributes.self, from: attributesData) let attributes = try JSONDecoder().decode(Attributes.self, from: attributesData)
switch (attributes.keyType.algorithm, attributes.keyType.size) { switch attributes.keyType {
case (.ecdsa, 256): case .ecdsa256:
let key = try CryptoKit.SecureEnclave.P256.Signing.PrivateKey(dataRepresentation: keyData, authenticationContext: context) let key = try CryptoKit.SecureEnclave.P256.Signing.PrivateKey(dataRepresentation: keyData, authenticationContext: context)
return try key.signature(for: data).rawRepresentation return try key.signature(for: data).rawRepresentation
case (.mldsa, 65): case .mldsa65:
guard #available(macOS 26.0, *) else { throw UnsupportedAlgorithmError() } guard #available(macOS 26.0, *) else { throw UnsupportedAlgorithmError() }
let key = try CryptoKit.SecureEnclave.MLDSA65.PrivateKey(dataRepresentation: keyData) let key = try CryptoKit.SecureEnclave.MLDSA65.PrivateKey(dataRepresentation: keyData)
return try key.signature(for: data) return try key.signature(for: data)
case (.mldsa, 87): case .mldsa87:
guard #available(macOS 26.0, *) else { throw UnsupportedAlgorithmError() } guard #available(macOS 26.0, *) else { throw UnsupportedAlgorithmError() }
let key = try CryptoKit.SecureEnclave.MLDSA87.PrivateKey(dataRepresentation: keyData) let key = try CryptoKit.SecureEnclave.MLDSA87.PrivateKey(dataRepresentation: keyData)
return try key.signature(for: data) return try key.signature(for: data)
@ -119,15 +119,15 @@ extension SecureEnclave {
throw error.takeRetainedValue() as Error throw error.takeRetainedValue() as Error
} }
let dataRep: Data let dataRep: Data
switch (attributes.keyType.algorithm, attributes.keyType.size) { switch attributes.keyType {
case (.ecdsa, 256): case .ecdsa256:
let created = try CryptoKit.SecureEnclave.P256.Signing.PrivateKey(accessControl: access!) let created = try CryptoKit.SecureEnclave.P256.Signing.PrivateKey(accessControl: access!)
dataRep = created.dataRepresentation dataRep = created.dataRepresentation
case (.mldsa, 65): case .mldsa65:
guard #available(macOS 26.0, *) else { throw Attributes.UnsupportedOptionError() } guard #available(macOS 26.0, *) else { throw Attributes.UnsupportedOptionError() }
let created = try CryptoKit.SecureEnclave.MLDSA65.PrivateKey(accessControl: access!) let created = try CryptoKit.SecureEnclave.MLDSA65.PrivateKey(accessControl: access!)
dataRep = created.dataRepresentation dataRep = created.dataRepresentation
case (.mldsa, 87): case .mldsa87:
guard #available(macOS 26.0, *) else { throw Attributes.UnsupportedOptionError() } guard #available(macOS 26.0, *) else { throw Attributes.UnsupportedOptionError() }
let created = try CryptoKit.SecureEnclave.MLDSA87.PrivateKey(accessControl: access!) let created = try CryptoKit.SecureEnclave.MLDSA87.PrivateKey(accessControl: access!)
dataRep = created.dataRepresentation dataRep = created.dataRepresentation
@ -172,11 +172,15 @@ extension SecureEnclave {
} }
public var supportedKeyTypes: [KeyType] { public var supportedKeyTypes: [KeyType] {
if #available(macOS 26, *) {
[ [
.init(algorithm: .ecdsa, size: 256), .ecdsa256,
.init(algorithm: .mldsa, size: 65), .mldsa65,
.init(algorithm: .mldsa, size: 87), .mldsa87,
] ]
} else {
[.ecdsa256]
}
} }
} }
@ -220,15 +224,15 @@ extension SecureEnclave.Store {
let attributes = try JSONDecoder().decode(Attributes.self, from: attributesData) let attributes = try JSONDecoder().decode(Attributes.self, from: attributesData)
let keyData = $0[kSecValueData] as! Data let keyData = $0[kSecValueData] as! Data
let publicKey: Data let publicKey: Data
switch (attributes.keyType.algorithm, attributes.keyType.size) { switch attributes.keyType {
case (.ecdsa, 256): case .ecdsa256:
let key = try CryptoKit.SecureEnclave.P256.Signing.PrivateKey(dataRepresentation: keyData) let key = try CryptoKit.SecureEnclave.P256.Signing.PrivateKey(dataRepresentation: keyData)
publicKey = key.publicKey.x963Representation publicKey = key.publicKey.x963Representation
case (.mldsa, 65): case .mldsa65:
guard #available(macOS 26.0, *) else { throw UnsupportedAlgorithmError() } guard #available(macOS 26.0, *) else { throw UnsupportedAlgorithmError() }
let key = try CryptoKit.SecureEnclave.MLDSA65.PrivateKey(dataRepresentation: keyData) let key = try CryptoKit.SecureEnclave.MLDSA65.PrivateKey(dataRepresentation: keyData)
publicKey = key.publicKey.rawRepresentation publicKey = key.publicKey.rawRepresentation
case (.mldsa, 87): case .mldsa87:
guard #available(macOS 26.0, *) else { throw UnsupportedAlgorithmError() } guard #available(macOS 26.0, *) else { throw UnsupportedAlgorithmError() }
let key = try CryptoKit.SecureEnclave.MLDSA87.PrivateKey(dataRepresentation: keyData) let key = try CryptoKit.SecureEnclave.MLDSA87.PrivateKey(dataRepresentation: keyData)
publicKey = key.publicKey.rawRepresentation publicKey = key.publicKey.rawRepresentation

View File

@ -61,11 +61,15 @@ extension Preview {
var name: String { "Modifiable Preview Store" } var name: String { "Modifiable Preview Store" }
let secrets: [Secret] let secrets: [Secret]
var supportedKeyTypes: [KeyType] { var supportedKeyTypes: [KeyType] {
if #available(macOS 26, *) {
[ [
.init(algorithm: .ecdsa, size: 256), .ecdsa256,
.init(algorithm: .mldsa, size: 65), .mldsa65,
.init(algorithm: .mldsa, size: 87), .mldsa87,
] ]
} else {
[.ecdsa256]
}
} }
init(secrets: [Secret]) { init(secrets: [Secret]) {