Return created key (#638)

* Return created key.

* Fix
This commit is contained in:
Max Goedjen 2025-08-26 22:43:08 -07:00 committed by GitHub
parent 8f4d0b8eda
commit c52728a050
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 19 additions and 9 deletions

View File

@ -61,20 +61,21 @@ open class AnySecretStore: SecretStore, @unchecked Sendable {
public final class AnySecretStoreModifiable: AnySecretStore, SecretStoreModifiable, @unchecked Sendable {
private let _create: @Sendable (String, Attributes) async throws -> Void
private let _create: @Sendable (String, Attributes) async throws -> SecretType
private let _delete: @Sendable (AnySecret) async throws -> Void
private let _update: @Sendable (AnySecret, String, Attributes) async throws -> Void
private let _supportedKeyTypes: @Sendable () -> [KeyType]
public init<SecretStoreType>(_ secretStore: SecretStoreType) where SecretStoreType: SecretStoreModifiable {
_create = { try await secretStore.create(name: $0, attributes: $1) }
_create = { try await secretStore.create(name: $0, attributes: $1) as! SecretType }
_delete = { try await secretStore.delete(secret: $0.base as! SecretStoreType.SecretType) }
_update = { try await secretStore.update(secret: $0.base as! SecretStoreType.SecretType, name: $1, attributes: $2) }
_supportedKeyTypes = { secretStore.supportedKeyTypes }
super.init(secretStore)
}
public func create(name: String, attributes: Attributes) async throws {
@discardableResult
public func create(name: String, attributes: Attributes) async throws -> SecretType {
try await _create(name, attributes)
}

View File

@ -46,8 +46,9 @@ public protocol SecretStoreModifiable<SecretType>: SecretStore {
/// Creates a new ``Secret`` in the store.
/// - Parameters:
/// - name: The user-facing name for the ``Secret``.
/// - attributes: A struct describing the options for creating the key.
func create(name: String, attributes: Attributes) async throws
/// - attributes: A struct describing the options for creating the key.'
@discardableResult
func create(name: String, attributes: Attributes) async throws -> SecretType
/// Deletes a Secret in the store.
/// - Parameters:

View File

@ -98,7 +98,7 @@ extension SecureEnclave {
// MARK: SecretStoreModifiable
public func create(name: String, attributes: Attributes) async throws {
public func create(name: String, attributes: Attributes) async throws -> Secret {
var accessError: SecurityError?
let flags: SecAccessControlCreateFlags = switch attributes.authentication {
case .notRequired:
@ -119,23 +119,28 @@ extension SecureEnclave {
throw error.takeRetainedValue() as Error
}
let dataRep: Data
let publicKey: Data
switch attributes.keyType {
case .ecdsa256:
let created = try CryptoKit.SecureEnclave.P256.Signing.PrivateKey(accessControl: access!)
dataRep = created.dataRepresentation
publicKey = created.publicKey.x963Representation
case .mldsa65:
guard #available(macOS 26.0, *) else { throw Attributes.UnsupportedOptionError() }
let created = try CryptoKit.SecureEnclave.MLDSA65.PrivateKey(accessControl: access!)
dataRep = created.dataRepresentation
publicKey = created.publicKey.rawRepresentation
case .mldsa87:
guard #available(macOS 26.0, *) else { throw Attributes.UnsupportedOptionError() }
let created = try CryptoKit.SecureEnclave.MLDSA87.PrivateKey(accessControl: access!)
dataRep = created.dataRepresentation
publicKey = created.publicKey.rawRepresentation
default:
throw Attributes.UnsupportedOptionError()
}
try saveKey(dataRep, name: name, attributes: attributes)
let id = try saveKey(dataRep, name: name, attributes: attributes)
await reloadSecrets()
return Secret(id: id, name: name, publicKey: publicKey, attributes: attributes)
}
public func delete(secret: Secret) async throws {
@ -253,14 +258,16 @@ extension SecureEnclave.Store {
/// - name: A user-facing name for the key.
/// - attributes: Attributes of the key.
/// - Note: Despite the name, the "Data" of the key is _not_ actual key material. This is an opaque data representation that the SEP can manipulate.
func saveKey(_ key: Data, name: String, attributes: Attributes) throws {
@discardableResult
func saveKey(_ key: Data, name: String, attributes: Attributes) throws -> String {
let attributes = try JSONEncoder().encode(attributes)
let id = UUID().uuidString
let keychainAttributes = KeychainDictionary([
kSecClass: Constants.keyClass,
kSecAttrService: Constants.keyTag,
kSecUseDataProtectionKeychain: true,
kSecAttrAccessible: kSecAttrAccessibleWhenUnlockedThisDeviceOnly,
kSecAttrAccount: UUID().uuidString,
kSecAttrAccount: id,
kSecValueData: key,
kSecAttrLabel: name,
kSecAttrGeneric: attributes
@ -269,6 +276,7 @@ extension SecureEnclave.Store {
if status != errSecSuccess {
throw KeychainError(statusCode: status)
}
return id
}
}