美文网首页
JTKeychain

JTKeychain

作者: WLAnswer | 来源:发表于2022-01-19 15:37 被阅读0次

    //
    // SSKeychain.h
    // SSToolkit
    //
    // Created by Sam Soffes on 5/19/10.
    // Copyright (c) 2009-2011 Sam Soffes. All rights reserved.
    //

    import <Foundation/Foundation.h>

    import <Security/Security.h>

    /** Error codes that can be returned in NSError objects. /
    typedef enum {
    /
    * No error. */
    SSKeychainErrorNone = noErr,

    /** Some of the arguments were invalid. */
    SSKeychainErrorBadArguments = -1001,
    
    /** There was no password. */
    SSKeychainErrorNoPassword = -1002,
    
    /** One or more parameters passed internally were not valid. */
    SSKeychainErrorInvalidParameter = errSecParam,
    
    /** Failed to allocate memory. */
    SSKeychainErrorFailedToAllocated = errSecAllocate,
    
    /** No trust results are available. */
    SSKeychainErrorNotAvailable = errSecNotAvailable,
    
    /** Authorization/Authentication failed. */
    SSKeychainErrorAuthorizationFailed = errSecAuthFailed,
    
    /** The item already exists. */
    SSKeychainErrorDuplicatedItem = errSecDuplicateItem,
    
    /** The item cannot be found.*/
    SSKeychainErrorNotFound = errSecItemNotFound,
    
    /** Interaction with the Security Server is not allowed. */
    SSKeychainErrorInteractionNotAllowed = errSecInteractionNotAllowed,
    
    /** Unable to decode the provided data. */
    SSKeychainErrorFailedToDecode = errSecDecode
    

    } SSKeychainErrorCode;

    extern NSString *const kSSKeychainErrorDomain;

    /** Account name. */
    extern NSString *const kSSKeychainAccountKey;

    /**
    Time the item was created.

    The value will be a string.
    */
    extern NSString *const kSSKeychainCreatedAtKey;

    /** Item class. */
    extern NSString *const kSSKeychainClassKey;

    /** Item description. */
    extern NSString *const kSSKeychainDescriptionKey;

    /** Item label. */
    extern NSString *const kSSKeychainLabelKey;

    /** Time the item was last modified.

    The value will be a string.
    */
    extern NSString *const kSSKeychainLastModifiedKey;

    /** Where the item was created. */
    extern NSString *const kSSKeychainWhereKey;

    /**
    Simple wrapper for accessing accounts, getting passwords, setting passwords, and deleting passwords using the system
    Keychain on Mac OS X and iOS.

    This was originally inspired by EMKeychain and SDKeychain (both of which are now gone). Thanks to the authors.
    SSKeychain has since switched to a simpler implementation that was abstracted from SSToolkit.
    */
    @interface JTKeychain : NSObject

    ///-----------------------
    /// @name Getting Accounts
    ///-----------------------

    /**
    Returns an array containing the Keychain's accounts, or nil if the Keychain has no accounts.

    See the NSString constants declared in SSKeychain.h for a list of keys that can be used when accessing the
    dictionaries returned by this method.

    @return An array of dictionaries containing the Keychain's accounts, or nil if the Keychain doesn't have any
    accounts. The order of the objects in the array isn't defined.

    @see allAccounts:
    */

    • (NSArray *)allAccounts;

    /**
    Returns an array containing the Keychain's accounts, or nil if the Keychain doesn't have any
    accounts.

    See the NSString constants declared in SSKeychain.h for a list of keys that can be used when accessing the
    dictionaries returned by this method.

    @param error If accessing the accounts fails, upon return contains an error that describes the problem.

    @return An array of dictionaries containing the Keychain's accounts, or nil if the Keychain doesn't have any
    accounts. The order of the objects in the array isn't defined.

    @see allAccounts
    */

    • (NSArray *)allAccounts:(NSError **)error;

    /**
    Returns an array containing the Keychain's accounts for a given service, or nil if the Keychain doesn't have any
    accounts for the given service.

    See the NSString constants declared in SSKeychain.h for a list of keys that can be used when accessing the
    dictionaries returned by this method.

    @param serviceName The service for which to return the corresponding accounts.

    @return An array of dictionaries containing the Keychain's accountsfor a given serviceName, or nil if the Keychain
    doesn't have any accounts for the given serviceName. The order of the objects in the array isn't defined.

    @see accountsForService:error:
    */

    • (NSArray *)accountsForService:(NSString *)serviceName;

    /**
    Returns an array containing the Keychain's accounts for a given service, or nil if the Keychain doesn't have any
    accounts for the given service.

    @param serviceName The service for which to return the corresponding accounts.

    @param error If accessing the accounts fails, upon return contains an error that describes the problem.

    @return An array of dictionaries containing the Keychain's accountsfor a given serviceName, or nil if the Keychain
    doesn't have any accounts for the given serviceName. The order of the objects in the array isn't defined.

    @see accountsForService:
    */

    • (NSArray *)accountsForService:(NSString *)serviceName error:(NSError **)error;

    ///------------------------
    /// @name Getting Passwords
    ///------------------------

    /**
    Returns a string containing the password for a given account and service, or nil if the Keychain doesn't have a
    password for the given parameters.

    @param serviceName The service for which to return the corresponding password.

    @param account The account for which to return the corresponding password.

    @return Returns a string containing the password for a given account and service, or nil if the Keychain doesn't
    have a password for the given parameters.

    @see passwordForService:account:error:
    */

    • (NSString *)passwordForService:(NSString *)serviceName account:(NSString *)account;

    /**
    Returns a string containing the password for a given account and service, or nil if the Keychain doesn't have a
    password for the given parameters.

    @param serviceName The service for which to return the corresponding password.

    @param account The account for which to return the corresponding password.

    @param error If accessing the password fails, upon return contains an error that describes the problem.

    @return Returns a string containing the password for a given account and service, or nil if the Keychain doesn't
    have a password for the given parameters.

    @see passwordForService:account:
    */

    • (NSString *)passwordForService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error;

    /**
    Returns the password data for a given account and service, or nil if the Keychain doesn't have data
    for the given parameters.

    @param serviceName The service for which to return the corresponding password.

    @param account The account for which to return the corresponding password.

    @param error If accessing the password fails, upon return contains an error that describes the problem.

    @return Returns a the password data for the given account and service, or nil if the Keychain doesn't
    have data for the given parameters.

    @see passwordDataForService:account:error:
    */

    • (NSData *)passwordDataForService:(NSString *)serviceName account:(NSString *)account;

    /**
    Returns the password data for a given account and service, or nil if the Keychain doesn't have data
    for the given parameters.

    @param serviceName The service for which to return the corresponding password.

    @param account The account for which to return the corresponding password.

    @param error If accessing the password fails, upon return contains an error that describes the problem.

    @return Returns a the password data for the given account and service, or nil if the Keychain doesn't
    have a password for the given parameters.

    @see passwordDataForService:account:
    */

    • (NSData *)passwordDataForService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error;

    ///-------------------------
    /// @name Deleting Passwords
    ///-------------------------

    /**
    Deletes a password from the Keychain.

    @param serviceName The service for which to delete the corresponding password.

    @param account The account for which to delete the corresponding password.

    @return Returns YES on success, or NO on failure.

    @see deletePasswordForService:account:error:
    */

    • (BOOL)deletePasswordForService:(NSString *)serviceName account:(NSString *)account;

    /**
    Deletes a password from the Keychain.

    @param serviceName The service for which to delete the corresponding password.

    @param account The account for which to delete the corresponding password.

    @param error If deleting the password fails, upon return contains an error that describes the problem.

    @return Returns YES on success, or NO on failure.

    @see deletePasswordForService:account:
    */

    • (BOOL)deletePasswordForService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error;

    ///------------------------
    /// @name Setting Passwords
    ///------------------------

    /**
    Sets a password in the Keychain.

    @param password The password to store in the Keychain.

    @param serviceName The service for which to set the corresponding password.

    @param account The account for which to set the corresponding password.

    @return Returns YES on success, or NO on failure.

    @see setPassword:forService:account:error:
    */

    • (BOOL)setPassword:(NSString *)password forService:(NSString *)serviceName account:(NSString *)account;

    /**
    Sets a password in the Keychain.

    @param password The password to store in the Keychain.

    @param serviceName The service for which to set the corresponding password.

    @param account The account for which to set the corresponding password.

    @param error If setting the password fails, upon return contains an error that describes the problem.

    @return Returns YES on success, or NO on failure.

    @see setPassword:forService:account:
    */

    • (BOOL)setPassword:(NSString *)password forService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error;

    /**
    Sets arbirary data in the Keychain.

    @param password The data to store in the Keychain.

    @param serviceName The service for which to set the corresponding password.

    @param account The account for which to set the corresponding password.

    @param error If setting the password fails, upon return contains an error that describes the problem.

    @return Returns YES on success, or NO on failure.

    @see setPasswordData:forService:account:error:
    */

    • (BOOL)setPasswordData:(NSData *)password forService:(NSString *)serviceName account:(NSString *)account;

    /**
    Sets arbirary data in the Keychain.

    @param password The data to store in the Keychain.

    @param serviceName The service for which to set the corresponding password.

    @param account The account for which to set the corresponding password.

    @param error If setting the password fails, upon return contains an error that describes the problem.

    @return Returns YES on success, or NO on failure.

    @see setPasswordData:forService:account:
    */

    • (BOOL)setPasswordData:(NSData *)password forService:(NSString *)serviceName account:(NSString *)account error:(NSError **)error;

    ///--------------------
    /// @name Configuration
    ///--------------------

    if __IPHONE_4_0 && TARGET_OS_IPHONE

    /**
    Returns the accessibility type for all future passwords saved to the Keychain.

    @return Returns the accessibility type.

    The return value will be NULL or one of the "Keychain Item Accessibility Constants" used for determining when a
    keychain item should be readable.

    @see accessibilityType
    */

    • (CFTypeRef)accessibilityType;

    /**
    Sets the accessibility type for all future passwords saved to the Keychain.

    @param accessibilityType One of the "Keychain Item Accessibility Constants" used for determining when a keychain item
    should be readable.

    If the value is NULL (the default), the Keychain default will be used.

    @see accessibilityType
    */

    • (void)setAccessibilityType:(CFTypeRef)accessibilityType;

    endif

    @end

    //
    // SSKeychain.m
    // SSToolkit
    //
    // Created by Sam Soffes on 5/19/10.
    // Copyright (c) 2009-2011 Sam Soffes. All rights reserved.
    //

    import "JTKeychain.h"

    NSString *const kSSKeychainErrorDomain = @"com.samsoffes.sskeychain";

    NSString *const kSSKeychainAccountKey = @"acct";
    NSString *const kSSKeychainCreatedAtKey = @"cdat";
    NSString *const kSSKeychainClassKey = @"labl";
    NSString *const kSSKeychainDescriptionKey = @"desc";
    NSString *const kSSKeychainLabelKey = @"labl";
    NSString *const kSSKeychainLastModifiedKey = @"mdat";
    NSString *const kSSKeychainWhereKey = @"svce";

    if __IPHONE_4_0 && TARGET_OS_IPHONE

    CFTypeRef SSKeychainAccessibilityType = NULL;

    endif

    @interface JTKeychain ()

    • (NSMutableDictionary *)_queryForService:(NSString *)service account:(NSString *)account;
      @end

    @implementation JTKeychain

    pragma mark - Getting Accounts

    • (NSArray *)allAccounts {
      return [self accountsForService:nil error:nil];
      }
    • (NSArray *)allAccounts:(NSError **)error {
      return [self accountsForService:nil error:error];
      }
    • (NSArray *)accountsForService:(NSString *)service {
      return [self accountsForService:service error:nil];
      }
    • (NSArray *)accountsForService:(NSString *)service error:(NSError **)error {
      OSStatus status = SSKeychainErrorBadArguments;
      NSMutableDictionary *query = [self _queryForService:service account:nil];

    if __has_feature(objc_arc)

    [query setObject:(__bridge id)kCFBooleanTrue forKey:(__bridge id)kSecReturnAttributes];
    [query setObject:(__bridge id)kSecMatchLimitAll forKey:(__bridge id)kSecMatchLimit];
    

    else

    [query setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnAttributes];
    [query setObject:(id)kSecMatchLimitAll forKey:(id)kSecMatchLimit];
    

    endif

    CFTypeRef result = NULL;
    

    if __has_feature(objc_arc)

    status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &result);
    

    else

    status = SecItemCopyMatching((CFDictionaryRef)query, &result);
    

    endif

    if (status != noErr && error != NULL) {
        *error = [NSError errorWithDomain:kSSKeychainErrorDomain code:status userInfo:nil];
        return nil;
    }
    

    if __has_feature(objc_arc)

    return (__bridge_transfer NSArray *)result;
    

    else

    return [(NSArray *)result autorelease];
    

    endif

    }

    pragma mark - Getting Passwords

    • (NSString *)passwordForService:(NSString *)service account:(NSString *)account {
      return [self passwordForService:service account:account error:nil];
      }
    • (NSString *)passwordForService:(NSString *)service account:(NSString *)account error:(NSError **)error {
      NSData *data = [self passwordDataForService:service account:account error:error];
      if (data.length > 0) {
      NSString *string = [[NSString alloc] initWithData:(NSData *)data encoding:NSUTF8StringEncoding];

    if !__has_feature(objc_arc)

        [string autorelease];
    

    endif

        return string;
    }
    
    return nil;
    

    }

    • (NSData *)passwordDataForService:(NSString *)service account:(NSString *)account {
      return [self passwordDataForService:service account:account error:nil];
      }
    • (NSData *)passwordDataForService:(NSString *)service account:(NSString *)account error:(NSError **)error {
      OSStatus status = SSKeychainErrorBadArguments;
      if (!service || !account) {
      if (error) {
      *error = [NSError errorWithDomain:kSSKeychainErrorDomain code:status userInfo:nil];
      }
      return nil;
      }

      CFTypeRef result = NULL;
      NSMutableDictionary *query = [self _queryForService:service account:account];

    if __has_feature(objc_arc)

    [query setObject:(__bridge id)kCFBooleanTrue forKey:(__bridge id)kSecReturnData];
    [query setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit];
    status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &result);
    

    else

    [query setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData];
    [query setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit];
    status = SecItemCopyMatching((CFDictionaryRef)query, &result);
    

    endif

    if (status != noErr && error != NULL) {
        *error = [NSError errorWithDomain:kSSKeychainErrorDomain code:status userInfo:nil];
        return nil;
    }
    

    if __has_feature(objc_arc)

    return (__bridge_transfer NSData *)result;
    

    else

    return [(NSData *)result autorelease];
    

    endif

    }

    pragma mark - Deleting Passwords

    • (BOOL)deletePasswordForService:(NSString *)service account:(NSString *)account {
      return [self deletePasswordForService:service account:account error:nil];
      }
    • (BOOL)deletePasswordForService:(NSString *)service account:(NSString *)account error:(NSError **)error {
      OSStatus status = SSKeychainErrorBadArguments;
      if (service && account) {
      NSMutableDictionary *query = [self _queryForService:service account:account];

    if __has_feature(objc_arc)

        status = SecItemDelete((__bridge CFDictionaryRef)query);
    

    else

        status = SecItemDelete((CFDictionaryRef)query);
    

    endif

    }
    if (status != noErr && error != NULL) {
        *error = [NSError errorWithDomain:kSSKeychainErrorDomain code:status userInfo:nil];
    }
    return (status == noErr);
    

    }

    pragma mark - Setting Passwords

    • (BOOL)setPassword:(NSString *)password forService:(NSString *)service account:(NSString *)account {
      return [self setPassword:password forService:service account:account error:nil];
      }
    • (BOOL)setPassword:(NSString *)password forService:(NSString *)service account:(NSString *)account error:(NSError **)error {
      NSData *data = [password dataUsingEncoding:NSUTF8StringEncoding];
      return [self setPasswordData:data forService:service account:account error:error];
      }
    • (BOOL)setPasswordData:(NSData *)password forService:(NSString *)service account:(NSString *)account {
      return [self setPasswordData:password forService:service account:account error:nil];
      }
    • (BOOL)setPasswordData:(NSData *)password forService:(NSString *)service account:(NSString *)account error:(NSError **)error {
      OSStatus status = SSKeychainErrorBadArguments;
      if (password && service && account) {
      [self deletePasswordForService:service account:account];
      NSMutableDictionary *query = [self _queryForService:service account:account];

    if __has_feature(objc_arc)

        [query setObject:password forKey:(__bridge id)kSecValueData];
    

    else

        [query setObject:password forKey:(id)kSecValueData];
    

    endif

    if __IPHONE_4_0 && TARGET_OS_IPHONE

        if (SSKeychainAccessibilityType) {
    

    if __has_feature(objc_arc)

            [query setObject:(id)[self accessibilityType] forKey:(__bridge id)kSecAttrAccessible];
    

    else

            [query setObject:(id)[self accessibilityType] forKey:(id)kSecAttrAccessible];
    

    endif

        }
    

    endif

    if __has_feature(objc_arc)

        status = SecItemAdd((__bridge CFDictionaryRef)query, NULL);
    

    else

        status = SecItemAdd((CFDictionaryRef)query, NULL);
    

    endif

    }
    if (status != noErr && error != NULL) {
        *error = [NSError errorWithDomain:kSSKeychainErrorDomain code:status userInfo:nil];
    }
    return (status == noErr);
    

    }

    pragma mark - Configuration

    if __IPHONE_4_0 && TARGET_OS_IPHONE

    • (CFTypeRef)accessibilityType {
      return SSKeychainAccessibilityType;
      }
    • (void)setAccessibilityType:(CFTypeRef)accessibilityType {
      CFRetain(accessibilityType);
      if (SSKeychainAccessibilityType) {
      CFRelease(SSKeychainAccessibilityType);
      }
      SSKeychainAccessibilityType = accessibilityType;
      }

    endif

    pragma mark - Private

    • (NSMutableDictionary *)_queryForService:(NSString *)service account:(NSString *)account {
      NSMutableDictionary *dictionary = [NSMutableDictionary dictionaryWithCapacity:3];

    if __has_feature(objc_arc)

    [dictionary setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass];
    

    else

    [dictionary setObject:(id)kSecClassGenericPassword forKey:(id)kSecClass];
    

    endif

    if (service) {
    

    if __has_feature(objc_arc)

        [dictionary setObject:service forKey:(__bridge id)kSecAttrService];
    

    else

        [dictionary setObject:service forKey:(id)kSecAttrService];
    

    endif

    }
    
    if (account) {
    

    if __has_feature(objc_arc)

        [dictionary setObject:account forKey:(__bridge id)kSecAttrAccount];
    

    else

        [dictionary setObject:account forKey:(id)kSecAttrAccount];
    

    endif

    }
    
    return dictionary;
    

    }

    @end

    相关文章

      网友评论

          本文标题:JTKeychain

          本文链接:https://www.haomeiwen.com/subject/odvrhrtx.html