zoukankan      html  css  js  c++  java
  • (转)iOS keychain API及其封装

    一. Keychain API

    KeyChain中item的结构为:

    1.增加keychain Item

    OSStatus SecItemAdd (CFDictionaryRef attributes,CFTypeRef *result);
    attributes字典中包括增加items的类型键值对和对应类型的属性键值对。item类型键常量为kSecClass,可能的取值为通用密码(kSecClassGenericPassword),网络密码(kSecClassInternetPassword),证书(kSecClassCertificate),密匙(kSecClassKey),ID(带有密匙的证书kSecClassIdentity)。每种类型的item具有不同的可选属性,具体可见Keychain Item Class Keys and Values

    若增加item成功,result则为新增加item的引用,其具体类型由attributes中的特定键指定。

    • 若kSecReturnData设置为kCFBooleanTrue,则result类型为CFDataRef;
    • 若kSecReturnAttributes设置为kCFBooleanTrue,则result类型为CFDictionaryRef;
    • 若kSecReturnRef设置为kCFBooleanTrue,则result类型为SecKeychainItemRef, SecKeyRef,SecCertificateRef, 或SecIdentityRef,当返回类型没有显式设置时,则默认为此设置。
    • 若kSecReturnPersistentRef设置为kCFBooleanTrue,则result类型为持久存储的CFDataRef,持久存储的CFDataRef可存储在磁盘或在进程之间传递。
    • 若以上多个返回类型被设置,则返回CFDictionaryRef类型。

    2.查询keychain item

    OSStatus SecItemCopyMatching (CFDictionaryRef query,CFTypeRef *result);
    根据query指定的属性查找item,并将结果存储在result中。

    3.删除item

    OSStatus SecItemDelete (CFDictionaryRef query);
    删除query指定的item.

    4.更新item

    OSStatus SecItemUpdate (CFDictionaryRef query,CFDictionaryRef attributesToUpdate);
    将query指定的item中的属性按照attributesToUpdate中的数据更新。

    参考:
    iOS 的keyChain
    Keychain Services Reference

    二.封装方式一:KeychainWrapper

    1. +(NSMutableDictionary *)setupSearchDirectoryForIdentifier:(NSString *)identifier;

    所有以下操作的基础,设置在增加、查找、更新、删除items时的通用属性字典。
    设置内容伪码如下:
    kSecClass = kSecClassGenericPassword;
    kSecAttrService = APP_NAME(应用标示符);
    kSecAttrGeneric = [identifier dataUsingEncoding:NSUTF8StringEncoding];
    kSecAttrAccount = [identifier dataUsingEncoding:NSUTF8StringEncoding];

    2. +(NSData *)searchKeychainCopyMatchingIdentifier:(NSString *)identifier;

    调用SecItemCopyMatching获取与identifier匹配的item内容,返回类型为kSecReturnData。
    使用的查找属性:
    kSecMatchLimit = kSecMatchLimitOne;
    kSecReturnData = kCFBooleanTrue;

    3. +(NSString *)keychainStringFromMatchingIdentifier:(NSString *)identifier;

    将searchKeychainCopyMatchingIdentifier:identifier获取的NSData结果转换为字符串。
    [[NSString alloc] initWithData:valueData encoding:NSUTF8StringEncoding];

    4. +(BOOL)createKeychainValue:(NSString *)value forIdentifier:(NSString *)identifier;

    调用SecItemAdd增加新的item.
    kSecValueData = (NSData*)value;
    kSecAttrAccessible = kSecAttrAccessibleWhenUnlocked;
    或identifier匹配的item已存在,则使用updateKeychainValue:forIdentifier更新item的data。

    5. +(BOOL)updateKeychainValue:(NSString *)value forIdentifier:(NSString *)identifier;

    调用SecItemUpdate将identifier匹配的items的kSecValueData内容修改为(NSData*)value。

    6. +(void)deleteItemFromKeychainWithIdentifier:(NSString *)identifier;

    调用SecItemDelete删除identifier匹配的item。

    SourceCode:
    KeychainWrapper.h
    KeychainWrapper.m

    参考:
    Basic Security in iOS 5 Tutorial Part 1
    Basic Security in iOS 5 Tutorial Part 2

    三.封装方式二:SFHFKeychainUtils

    1.+(NSString *) getPasswordForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error;

    获取serviceName和username匹配的item数据.
    查找属性字典:
    kSecClass = kSecClassGenericPassword;
    kSecAttrAccount = username;
    kSecAttrService = serviceName;
    首先使用kSecReturnAttributes = kCFBooleanTrue;查找属性值是否存在。
    若属性存在,则使用kSecReturnData = kCFBooleanTrue;获取data即密码字段,并转换称NSString返回。
    属性存在,而密码不存在时返回特殊的错误码。

    2.+(BOOL) storeUsername: (NSString *) username andPassword: (NSString *) password forServiceName: (NSString *) serviceName updateExisting: (BOOL) updateExisting error: (NSError **) error;

    设置serviceName和username的密码为password。
    已存在则update(SecItemUpdate),不存在则add(SecItemAdd)。
    kSecClass = kSecClassGenericPassword;
    kSecAttrService = serviceName;
    kSecAttrLabel = serviceName;
    kSecAttrAccount = username;
    kSecValueData = [password dataUsingEncoding: NSUTF8StringEncoding];

    3.+(BOOL) deleteItemForUsername: (NSString *) username andServiceName: (NSString *) serviceName error: (NSError **) error;

    删除serviceName,username对应的item。

    使用方式:

    存储用户名/密码对,通过用户名获取到对应的密码

        #import “SFHFKeychainUtils.h”
    
        //Store new Password in keychain
        NSError *error = nil;
        NSString *username = usernameFiled.text;
        NSString *password = passwordField.text;
        [SFHFKeychainUtils storeUsername:username andPassword:password forServiceName:@"myApp",updateExisting:TRUE error:&err];
    
        //Get password from keychain
        NSError *error = nil;
        NSString *username = @"xuguoxing";
        password = [SFHFKeychainUtils getPasswordForUsername:username andServiceName:@"myApp",error:&err];

    SourceCode:
    https://github.com/ldandersen/scifihifi-iphone/tree/master/security/
    SFHFKeychainUtils.h
    SFHFKeychainUtils.m

    参考:
    Simple iPhone Tutorial: Password Management using the keychain by using SFHFKeychainUtils

    三.封装方式三:苹果提供的KeychainItemWrapper

    - (id)initWithIdentifier: (NSString *)identifier accessGroup:(NSString *) accessGroup;
    - (void)setObject:(id)inObject forKey:(id)key;
    - (id)objectForKey:(id)key;
    - (void)resetKeychainItem;

    使用方式:

    每个keychain用Identifier标示,根据keychain的各种key设置value,同时可以根据key获取到value。

    KeychainItemWrapper* keychain = [[KeychainItemWrapper alloc] initWithIdentifier:@"KeychainTest" accessGroup:nil];
    [keychain setObject:kSecAttrAccessibleWhenUnlocked forKey:kSecAttrAccessible];
    
    NSLog(@"%@, %@", [keychain objectForKey:kSecAttrAccount], [keychain objectForKey:kSecValueData]);
    
    [keychain setObject:@"example@email.com" forKey:kSecAttrAccount];
    [keychain setObject:@"MySuperSecretPassword" forKey:kSecValueData];
    
    [keychain release]; 

    SourceCode:
    KeychainItemWrapper.h
    KeychainItemWrapper.m

    参考:
    GenericKeychain
    Using the Keychain to store passwords on iOS

    本文出自 清风徐来,水波不兴 的博客,转载时请注明出处及相应链接。

    本文永久链接: http://www.winddisk.com/2012/04/09/keychain-api%e5%8f%8a%e5%85%b6%e5%b0%81%e8%a3%85/

  • 相关阅读:
    September 17th 2016 Week 38th Saturday
    【2016-09-16】UbuntuServer14.04或更高版本安装问题记录
    September 16th 2016 Week 38th Friday
    September 11th 2016 Week 38th Sunday
    September 12th 2016 Week 38th Monday
    September 10th 2016 Week 37th Saturday
    September 9th 2016 Week 37th Friday
    c++暂停
    八皇后问题
    ( 转转)Android初级开发第九讲--Intent最全用法(打开文件跳转页面等)
  • 原文地址:https://www.cnblogs.com/greywolf/p/3461429.html
Copyright © 2011-2022 走看看