Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 76 additions & 11 deletions Sources/Valet/SecureEnclaveValet.swift
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,6 @@ public final class SecureEnclaveValet: NSObject, Sendable {
/// - key: A key that can be used to retrieve the `object` from the keychain.
/// - Throws: An error of type `KeychainError`.
/// - Important: Inserted data should be no larger than 4kb.
@objc
public func setObject(_ object: Data, forKey key: String) throws(KeychainError) {
lock.lock()
defer {
Expand All @@ -130,32 +129,61 @@ public final class SecureEnclaveValet: NSObject, Sendable {
return try SecureEnclave.setObject(object, forKey: key, options: baseKeychainQuery)
}

/// - Parameters:
/// - object: A Data value to be inserted into the keychain.
/// - key: A key that can be used to retrieve the `object` from the keychain.
/// - Throws: An error of type `KeychainError`.
/// - Important: Inserted data should be no larger than 4kb.
@available(swift, obsoleted: 1.0)
@objc(setObject:forKey:error:)
public func objc_setObject(_ object: Data, forKey key: String) throws {
try setObject(object, forKey: key)
}

#if !os(tvOS) && !os(watchOS) && canImport(LocalAuthentication)
/// - Parameters:
/// - key: A key used to retrieve the desired object from the keychain.
/// - userPrompt: The prompt displayed to the user in Apple's Face ID, Touch ID, or passcode entry UI.
/// - Returns: The data currently stored in the keychain for the provided key.
/// - Throws: An error of type `KeychainError`.
@objc
public func object(forKey key: String, withPrompt userPrompt: String) throws(KeychainError) -> Data {
lock.lock()
defer {
lock.unlock()
}
return try SecureEnclave.object(forKey: key, withPrompt: userPrompt, context: nil, options: baseKeychainQuery)
}

/// - Parameters:
/// - key: A key used to retrieve the desired object from the keychain.
/// - userPrompt: The prompt displayed to the user in Apple's Face ID, Touch ID, or passcode entry UI.
/// - Returns: The data currently stored in the keychain for the provided key.
/// - Throws: An error of type `KeychainError`.
@available(swift, obsoleted: 1.0)
@objc(objectForKey:withPrompt:error:)
public func objc_object(forKey key: String, withPrompt userPrompt: String) throws -> Data {
try object(forKey: key, withPrompt: userPrompt)
}
#else
/// - Parameter key: A key used to retrieve the desired object from the keychain.
/// - Returns: The data currently stored in the keychain for the provided key.
/// - Throws: An error of type `KeychainError`.
@objc
public func object(forKey key: String) throws(KeychainError) -> Data {
lock.lock()
defer {
lock.unlock()
}
return try SecureEnclave.object(forKey: key, options: baseKeychainQuery)
}

/// - Parameter key: A key used to retrieve the desired object from the keychain.
/// - Returns: The data currently stored in the keychain for the provided key.
/// - Throws: An error of type `KeychainError`.
@available(swift, obsoleted: 1.0)
@objc(objectForKey:error:)
public func objc_object(forKey key: String) throws -> Data {
try object(forKey: key)
}
#endif

#if !os(tvOS) && canImport(LocalAuthentication)
Expand All @@ -177,7 +205,6 @@ public final class SecureEnclaveValet: NSObject, Sendable {
/// - key: A key that can be used to retrieve the `string` from the keychain.
/// - Throws: An error of type `KeychainError`.
/// - Important: Inserted data should be no larger than 4kb.
@objc
public func setString(_ string: String, forKey key: String) throws(KeychainError) {
lock.lock()
defer {
Expand All @@ -186,57 +213,95 @@ public final class SecureEnclaveValet: NSObject, Sendable {
return try SecureEnclave.setString(string, forKey: key, options: baseKeychainQuery)
}

/// - Parameters:
/// - string: A String value to be inserted into the keychain.
/// - key: A key that can be used to retrieve the `string` from the keychain.
/// - Throws: An error of type `KeychainError`.
/// - Important: Inserted data should be no larger than 4kb.
@available(swift, obsoleted: 1.0)
@objc(setString:forKey:error:)
public func objc_setString(_ string: String, forKey key: String) throws {
try setString(string, forKey: key)
}
#if !os(tvOS) && !os(watchOS) && canImport(LocalAuthentication)
/// - Parameters:
/// - key: A key used to retrieve the desired object from the keychain.
/// - userPrompt: The prompt displayed to the user in Apple's Face ID, Touch ID, or passcode entry UI.
/// - Returns: The string currently stored in the keychain for the provided key.
/// - Throws: An error of type `KeychainError`.
@objc
public func string(forKey key: String, withPrompt userPrompt: String) throws(KeychainError) -> String {
lock.lock()
defer {
lock.unlock()
}
return try SecureEnclave.string(forKey: key, withPrompt: userPrompt, context: nil, options: baseKeychainQuery)
}

@available(swift, obsoleted: 1.0)
@objc(stringForKey:withPrompt:error:)
public func objc_string(forKey key: String, withPrompt userPrompt: String) throws -> String {
try string(forKey: key, withPrompt: userPrompt)
}
#else
/// - Parameter key: A key used to retrieve the desired object from the keychain.
/// - Returns: The string currently stored in the keychain for the provided key.
/// - Throws: An error of type `KeychainError`.
@objc
public func string(forKey key: String) throws(KeychainError) -> String {
lock.lock()
defer {
lock.unlock()
}
return try SecureEnclave.string(forKey: key, options: baseKeychainQuery)
}

/// - Parameter key: A key used to retrieve the desired object from the keychain.
/// - Returns: The string currently stored in the keychain for the provided key.
/// - Throws: An error of type `KeychainError`.
@available(swift, obsoleted: 1.0)
@objc(stringForKey:error:)
public func objc_string(forKey key: String) throws -> String {
try string(forKey: key)
}
#endif

/// Removes a key/object pair from the keychain.
/// - Parameter key: A key used to remove the desired object from the keychain.
/// - Throws: An error of type `KeychainError`.
@objc
public func removeObject(forKey key: String) throws(KeychainError) {
lock.lock()
defer {
lock.unlock()
}
return try Keychain.removeObject(forKey: key, options: baseKeychainQuery)
}


/// Removes a key/object pair from the keychain.
/// - Parameter key: A key used to remove the desired object from the keychain.
/// - Throws: An error of type `KeychainError`.
@available(swift, obsoleted: 1.0)
@objc(removeObjectForKey:error:)
public func objc_removeObject(forKey key: String) throws {
try removeObject(forKey: key)
}

/// Removes all key/object pairs accessible by this Valet instance from the keychain.
/// - Throws: An error of type `KeychainError`.
@objc
public func removeAllObjects() throws(KeychainError) {
lock.lock()
defer {
lock.unlock()
}
return try Keychain.removeAllObjects(matching: baseKeychainQuery)
}


/// Removes all key/object pairs accessible by this Valet instance from the keychain.
/// - Throws: An error of type `KeychainError`.
@available(swift, obsoleted: 1.0)
@objc(removeAllObjectsAndReturnError:)
public func objc_removeAllObjects() throws {
try removeAllObjects()
}

/// Migrates objects matching the input query into the receiving SecureEnclaveValet instance.
/// - Parameters:
/// - query: The query with which to retrieve existing keychain data via a call to SecItemCopyMatching.
Expand All @@ -249,7 +314,7 @@ public final class SecureEnclaveValet: NSObject, Sendable {
try Keychain.migrateObjects(matching: query, into: baseKeychainQuery, removeOnCompletion: removeOnCompletion)
}
}

/// Migrates objects matching the vended keychain query into the receiving SecureEnclaveValet instance.
/// - Parameters:
/// - valet: A Valet whose vended keychain query is used to retrieve existing keychain data via a call to SecItemCopyMatching.
Expand Down
74 changes: 66 additions & 8 deletions Sources/Valet/Valet.swift
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,6 @@ public final class Valet: NSObject, Sendable {
/// - key: A key that can be used to retrieve the `object` from the keychain.
/// - Throws: An error of type `KeychainError`.
/// - Important: Inserted data should be no larger than 4kb.
@objc
public func setObject(_ object: Data, forKey key: String) throws(KeychainError) {
lock.lock()
defer {
Expand All @@ -260,10 +259,20 @@ public final class Valet: NSObject, Sendable {
return try Keychain.setObject(object, forKey: key, options: baseKeychainQuery)
}

/// - Parameters:
/// - object: A Data value to be inserted into the keychain.
/// - key: A key that can be used to retrieve the `object` from the keychain.
/// - Throws: An error of type `KeychainError`.
/// - Important: Inserted data should be no larger than 4kb.
@available(swift, obsoleted: 1.0)
@objc(setObject:forKey:error:)
public func objc_setObject(_ object: Data, forKey key: String) throws {
try setObject(object, forKey: key)
}

/// - Parameter key: A key used to retrieve the desired object from the keychain.
/// - Returns: The data currently stored in the keychain for the provided key.
/// - Throws: An error of type `KeychainError`.
@objc
public func object(forKey key: String) throws(KeychainError) -> Data {
lock.lock()
defer {
Expand All @@ -272,6 +281,15 @@ public final class Valet: NSObject, Sendable {
return try Keychain.object(forKey: key, options: baseKeychainQuery)
}

/// - Parameter key: A key used to retrieve the desired object from the keychain.
/// - Returns: The data currently stored in the keychain for the provided key.
/// - Throws: An error of type `KeychainError`.
@available(swift, obsoleted: 1.0)
@objc(objectForKey:error:)
public func objc_object(forKey key: String) throws -> Data {
try object(forKey: key)
}

/// - Parameter key: The key to look up in the keychain.
/// - Returns: `true` if a value has been set for the given key, `false` otherwise.
/// - Throws: An error of type `KeychainError`.
Expand All @@ -296,7 +314,6 @@ public final class Valet: NSObject, Sendable {
/// - key: A key that can be used to retrieve the `string` from the keychain.
/// - Throws: An error of type `KeychainError`.
/// - Important: Inserted data should be no larger than 4kb.
@objc
public func setString(_ string: String, forKey key: String) throws(KeychainError) {
lock.lock()
defer {
Expand All @@ -305,45 +322,78 @@ public final class Valet: NSObject, Sendable {
return try Keychain.setString(string, forKey: key, options: baseKeychainQuery)
}

/// - Parameters:
/// - string: A String value to be inserted into the keychain.
/// - key: A key that can be used to retrieve the `string` from the keychain.
/// - Throws: An error of type `KeychainError`.
/// - Important: Inserted data should be no larger than 4kb.
@available(swift, obsoleted: 1.0)
@objc(setString:forKey:error:)
public func objc_setString(_ string: String, forKey key: String) throws {
try setString(string, forKey: key)
}

/// - Parameter key: A key used to retrieve the desired object from the keychain.
/// - Returns: The string currently stored in the keychain for the provided key.
/// - Throws: An error of type `KeychainError`.
@objc
public func string(forKey key: String) throws(KeychainError) -> String {
lock.lock()
defer {
lock.unlock()
}
return try Keychain.string(forKey: key, options: baseKeychainQuery)
}

/// - Parameter key: A key used to retrieve the desired object from the keychain.
/// - Returns: The string currently stored in the keychain for the provided key.
/// - Throws: An error of type `KeychainError`.
@objc(stringForKey:error:)
public func objc_string(forKey key: String) throws -> String {
try string(forKey: key)
}

/// - Returns: The set of all (String) keys currently stored in this Valet instance. If no items are found, will return an empty set.
/// - Throws: An error of type `KeychainError`.
@objc
public func allKeys() throws(KeychainError) -> Set<String> {
lock.lock()
defer {
lock.unlock()
}
return try Keychain.allKeys(options: baseKeychainQuery)
}


/// - Returns: The set of all (String) keys currently stored in this Valet instance. If no items are found, will return an empty set.
/// - Throws: An error of type `KeychainError`.
@available(swift, obsoleted: 1.0)
@objc(allKeysWithError:)
public func objc_allKeys() throws -> Set<String> {
try allKeys()
}

/// Removes a key/object pair from the keychain.
/// - Parameter key: A key used to remove the desired object from the keychain.
/// - Throws: An error of type `KeychainError`.
/// - Note: No error is thrown if the `key` is not found in the keychain.
@objc
public func removeObject(forKey key: String) throws(KeychainError) {
lock.lock()
defer {
lock.unlock()
}
return try Keychain.removeObject(forKey: key, options: baseKeychainQuery)
}

/// Removes a key/object pair from the keychain.
/// - Parameter key: A key used to remove the desired object from the keychain.
/// - Throws: An error of type `KeychainError`.
/// - Note: No error is thrown if the `key` is not found in the keychain.
@available(swift, obsoleted: 1.0)
@objc(removeObjectForKey:error:)
public func objc_removeObject(forKey key: String) throws {
try removeObject(forKey: key)
}

/// Removes all key/object pairs accessible by this Valet instance from the keychain.
/// - Throws: An error of type `KeychainError`.
@objc
public func removeAllObjects() throws(KeychainError) {
lock.lock()
defer {
Expand All @@ -352,6 +402,14 @@ public final class Valet: NSObject, Sendable {
return try Keychain.removeAllObjects(matching: baseKeychainQuery)
}

/// Removes all key/object pairs accessible by this Valet instance from the keychain.
/// - Throws: An error of type `KeychainError`.
@available(swift, obsoleted: 1.0)
@objc(removeAllObjectsAndReturnError:)
public func objc_removeAllObjects() throws {
try removeAllObjects()
}

/// Migrates objects matching the input query into the receiving Valet instance.
/// - Parameters:
/// - query: The query with which to retrieve existing keychain data via a call to SecItemCopyMatching.
Expand Down
2 changes: 1 addition & 1 deletion Valet.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'Valet'
s.version = '5.0.0'
s.version = '5.0.1'
s.license = 'Apache License, Version 2.0'
s.summary = 'Securely store data on iOS, tvOS, watchOS, or macOS without knowing a thing about how the Keychain works. It\'s easy. We promise.'
s.homepage = 'https://github.com/square/Valet'
Expand Down