123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329 |
- //
- // YYKeychain.h
- // YYKit <https://github.com/ibireme/YYKit>
- //
- // Created by ibireme on 14/10/15.
- // Copyright (c) 2015 ibireme.
- //
- // This source code is licensed under the MIT-style license found in the
- // LICENSE file in the root directory of this source tree.
- //
- #import <Foundation/Foundation.h>
- @class YYKeychainItem;
- NS_ASSUME_NONNULL_BEGIN
- /**
- A wrapper for system keychain API.
-
- Inspired by [SSKeychain](https://github.com/soffes/sskeychain) 😜
- */
- @interface YYKeychain : NSObject
- #pragma mark - Convenience method for keychain
- ///=============================================================================
- /// @name Convenience method for keychain
- ///=============================================================================
- /**
- Returns the password for a given account and service, or `nil` if not found or
- an error occurs.
-
- @param serviceName The service for which to return the corresponding password.
- This value must not be nil.
-
- @param account The account for which to return the corresponding password.
- This value must not be nil.
-
- @param error On input, a pointer to an error object. If an error occurs,
- this pointer is set to an actual error object containing the error information.
- You may specify nil for this parameter if you do not want the error information.
- See `YYKeychainErrorCode`.
-
- @return Password string, or nil when not found or error occurs.
- */
- + (nullable NSString *)getPasswordForService:(NSString *)serviceName
- account:(NSString *)account
- error:(NSError **)error;
- + (nullable NSString *)getPasswordForService:(NSString *)serviceName
- account:(NSString *)account;
- /**
- Deletes a password from the Keychain.
-
- @param serviceName The service for which to return the corresponding password.
- This value must not be nil.
-
- @param account The account for which to return the corresponding password.
- This value must not be nil.
-
- @param error On input, a pointer to an error object. If an error occurs,
- this pointer is set to an actual error object containing the error information.
- You may specify nil for this parameter if you do not want the error information.
- See `YYKeychainErrorCode`.
-
- @return Whether succeed.
- */
- + (BOOL)deletePasswordForService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error;
- + (BOOL)deletePasswordForService:(NSString *)serviceName account:(NSString *)account;
- /**
- Insert or update the password for a given account and service.
-
- @param password The new password.
-
- @param serviceName The service for which to return the corresponding password.
- This value must not be nil.
-
- @param account The account for which to return the corresponding password.
- This value must not be nil.
-
- @param error On input, a pointer to an error object. If an error occurs,
- this pointer is set to an actual error object containing the error information.
- You may specify nil for this parameter if you do not want the error information.
- See `YYKeychainErrorCode`.
-
- @return Whether succeed.
- */
- + (BOOL)setPassword:(NSString *)password
- forService:(NSString *)serviceName
- account:(NSString *)account
- error:(NSError **)error;
- + (BOOL)setPassword:(NSString *)password
- forService:(NSString *)serviceName
- account:(NSString *)account;
- #pragma mark - Full query for keychain (SQL-like)
- ///=============================================================================
- /// @name Full query for keychain (SQL-like)
- ///=============================================================================
- /**
- Insert an item into keychain.
-
- @discussion The service,account,password is required. If there's item exist
- already, an error occurs and insert fail.
-
- @param item The item to insert.
-
- @param error On input, a pointer to an error object. If an error occurs,
- this pointer is set to an actual error object containing the error information.
- You may specify nil for this parameter if you do not want the error information.
- See `YYKeychainErrorCode`.
-
- @return Whether succeed.
- */
- + (BOOL)insertItem:(YYKeychainItem *)item error:(NSError **)error;
- + (BOOL)insertItem:(YYKeychainItem *)item;
- /**
- Update item in keychain.
-
- @discussion The service,account,password is required. If there's no item exist
- already, an error occurs and insert fail.
-
- @param item The item to insert.
-
- @param error On input, a pointer to an error object. If an error occurs,
- this pointer is set to an actual error object containing the error information.
- You may specify nil for this parameter if you do not want the error information.
- See `YYKeychainErrorCode`.
-
- @return Whether succeed.
- */
- + (BOOL)updateItem:(YYKeychainItem *)item error:(NSError **)error;
- + (BOOL)updateItem:(YYKeychainItem *)item;
- /**
- Delete items from keychain.
-
- @discussion The service,account,password is required. If there's item exist
- already, an error occurs and insert fail.
-
- @param item The item to update.
-
- @param error On input, a pointer to an error object. If an error occurs,
- this pointer is set to an actual error object containing the error information.
- You may specify nil for this parameter if you do not want the error information.
- See `YYKeychainErrorCode`.
-
- @return Whether succeed.
- */
- + (BOOL)deleteItem:(YYKeychainItem *)item error:(NSError **)error;
- + (BOOL)deleteItem:(YYKeychainItem *)item;
- /**
- Find an item from keychain.
-
- @discussion The service,account is optinal. It returns only one item if there
- exist multi.
-
- @param item The item for query.
-
- @param error On input, a pointer to an error object. If an error occurs,
- this pointer is set to an actual error object containing the error information.
- You may specify nil for this parameter if you do not want the error information.
- See `YYKeychainErrorCode`.
-
- @return An item or nil.
- */
- + (nullable YYKeychainItem *)selectOneItem:(YYKeychainItem *)item error:(NSError **)error;
- + (nullable YYKeychainItem *)selectOneItem:(YYKeychainItem *)item;
- /**
- Find all items matches the query.
-
- @discussion The service,account is optinal. It returns all item matches by the
- query.
-
- @param item The item for query.
-
- @param error On input, a pointer to an error object. If an error occurs,
- this pointer is set to an actual error object containing the error information.
- You may specify nil for this parameter if you do not want the error information.
- See `YYKeychainErrorCode`.
-
- @return An array of YYKeychainItem.
- */
- + (nullable NSArray<YYKeychainItem *> *)selectItems:(YYKeychainItem *)item error:(NSError **)error;
- + (nullable NSArray<YYKeychainItem *> *)selectItems:(YYKeychainItem *)item;
- @end
- #pragma mark - Const
- /**
- Error code in YYKeychain API.
- */
- typedef NS_ENUM (NSUInteger, YYKeychainErrorCode) {
- YYKeychainErrorUnimplemented = 1, ///< Function or operation not implemented.
- YYKeychainErrorIO, ///< I/O error (bummers)
- YYKeychainErrorOpWr, ///< File already open with with write permission.
- YYKeychainErrorParam, ///< One or more parameters passed to a function where not valid.
- YYKeychainErrorAllocate, ///< Failed to allocate memory.
- YYKeychainErrorUserCancelled, ///< User cancelled the operation.
- YYKeychainErrorBadReq, ///< Bad parameter or invalid state for operation.
- YYKeychainErrorInternalComponent, ///< Internal...
- YYKeychainErrorNotAvailable, ///< No keychain is available. You may need to restart your computer.
- YYKeychainErrorDuplicateItem, ///< The specified item already exists in the keychain.
- YYKeychainErrorItemNotFound, ///< The specified item could not be found in the keychain.
- YYKeychainErrorInteractionNotAllowed, ///< User interaction is not allowed.
- YYKeychainErrorDecode, ///< Unable to decode the provided data.
- YYKeychainErrorAuthFailed, ///< The user name or passphrase you entered is not.
- };
- /**
- When query to return the item's data, the error
- errSecInteractionNotAllowed will be returned if the item's data is not
- available until a device unlock occurs.
- */
- typedef NS_ENUM (NSUInteger, YYKeychainAccessible) {
- YYKeychainAccessibleNone = 0, ///< no value
-
- /** Item data can only be accessed
- while the device is unlocked. This is recommended for items that only
- need be accesible while the application is in the foreground. Items
- with this attribute will migrate to a new device when using encrypted
- backups. */
- YYKeychainAccessibleWhenUnlocked,
-
- /** Item data can only be
- accessed once the device has been unlocked after a restart. This is
- recommended for items that need to be accesible by background
- applications. Items with this attribute will migrate to a new device
- when using encrypted backups.*/
- YYKeychainAccessibleAfterFirstUnlock,
-
- /** Item data can always be accessed
- regardless of the lock state of the device. This is not recommended
- for anything except system use. Items with this attribute will migrate
- to a new device when using encrypted backups.*/
- YYKeychainAccessibleAlways,
-
- /** Item data can
- only be accessed while the device is unlocked. This class is only
- available if a passcode is set on the device. This is recommended for
- items that only need to be accessible while the application is in the
- foreground. Items with this attribute will never migrate to a new
- device, so after a backup is restored to a new device, these items
- will be missing. No items can be stored in this class on devices
- without a passcode. Disabling the device passcode will cause all
- items in this class to be deleted.*/
- YYKeychainAccessibleWhenPasscodeSetThisDeviceOnly,
-
- /** Item data can only
- be accessed while the device is unlocked. This is recommended for items
- that only need be accesible while the application is in the foreground.
- Items with this attribute will never migrate to a new device, so after
- a backup is restored to a new device, these items will be missing. */
- YYKeychainAccessibleWhenUnlockedThisDeviceOnly,
-
- /** Item data can
- only be accessed once the device has been unlocked after a restart.
- This is recommended for items that need to be accessible by background
- applications. Items with this attribute will never migrate to a new
- device, so after a backup is restored to a new device these items will
- be missing.*/
- YYKeychainAccessibleAfterFirstUnlockThisDeviceOnly,
-
- /** Item data can always
- be accessed regardless of the lock state of the device. This option
- is not recommended for anything except system use. Items with this
- attribute will never migrate to a new device, so after a backup is
- restored to a new device, these items will be missing.*/
- YYKeychainAccessibleAlwaysThisDeviceOnly,
- };
- /**
- Whether the item in question can be synchronized.
- */
- typedef NS_ENUM (NSUInteger, YYKeychainQuerySynchronizationMode) {
-
- /** Default, Don't care for synchronization */
- YYKeychainQuerySynchronizationModeAny = 0,
-
- /** Is not synchronized */
- YYKeychainQuerySynchronizationModeNo,
-
- /** To add a new item which can be synced to other devices, or to obtain
- synchronized results from a query*/
- YYKeychainQuerySynchronizationModeYes,
- } NS_AVAILABLE_IOS (7_0);
- #pragma mark - Item
- /**
- Wrapper for keychain item/query.
- */
- @interface YYKeychainItem : NSObject <NSCopying>
- @property (nullable, nonatomic, copy) NSString *service; ///< kSecAttrService
- @property (nullable, nonatomic, copy) NSString *account; ///< kSecAttrAccount
- @property (nullable, nonatomic, copy) NSData *passwordData; ///< kSecValueData
- @property (nullable, nonatomic, copy) NSString *password; ///< shortcut for `passwordData`
- @property (nullable, nonatomic, copy) id <NSCoding> passwordObject; ///< shortcut for `passwordData`
- @property (nullable, nonatomic, copy) NSString *label; ///< kSecAttrLabel
- @property (nullable, nonatomic, copy) NSNumber *type; ///< kSecAttrType (FourCC)
- @property (nullable, nonatomic, copy) NSNumber *creater; ///< kSecAttrCreator (FourCC)
- @property (nullable, nonatomic, copy) NSString *comment; ///< kSecAttrComment
- @property (nullable, nonatomic, copy) NSString *descr; ///< kSecAttrDescription
- @property (nullable, nonatomic, readonly, strong) NSDate *modificationDate; ///< kSecAttrModificationDate
- @property (nullable, nonatomic, readonly, strong) NSDate *creationDate; ///< kSecAttrCreationDate
- @property (nullable, nonatomic, copy) NSString *accessGroup; ///< kSecAttrAccessGroup
- @property (nonatomic) YYKeychainAccessible accessible; ///< kSecAttrAccessible
- @property (nonatomic) YYKeychainQuerySynchronizationMode synchronizable NS_AVAILABLE_IOS(7_0); ///< kSecAttrSynchronizable
- @end
- NS_ASSUME_NONNULL_END
|