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.
/// - 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

View File

@ -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)])

View File

@ -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

View File

@ -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

View File

@ -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
}