0

我需要在钥匙串中存储多个具有唯一密钥的密码/密码。在从钥匙串中获取存储的数据期间,我得到了 nil 值。任何人都可以帮助我解决这个问题。

这是我的代码...

- (void)storeSensitiveDataToKeychain:(NSString *)value withKey:(NSString *)key {
    NSString *keyValue = [self fetchDataFromKeychain:key];
    if ([keyValue isEqualToString:@""] || [keyValue isEqual:[NSNull null]] || !keyValue.length || keyValue == nil) {
        [keychainClass insert:key :[value dataUsingEncoding:NSUTF8StringEncoding]];
    } else {
        [keychainClass update:key :[value dataUsingEncoding:NSUTF8StringEncoding]];
    }
}

- (NSString *)fetchDataFromKeychain:(NSString *)key {

    NSData *value = [keychainClass find:key];
    if (value == nil) {
        NSLog(@"key value is nil");
        return @"";
    } else {
        return  [[NSString alloc] initWithData:value
                                                   encoding:NSUTF8StringEncoding];
    }
}
4

1 回答 1

0

我已按照以下步骤将我自己的密钥和值存储到钥匙串中,

效果很棒!

1.创建一个NSObject类

2.进口

#import<Security/Security.h>框架

3.在头文件中添加,

- (id) initWithService:(NSString *) service_ withGroup:(NSString*)group_;

- (BOOL)insert:(NSString *)key dataValue:(NSData *)data;
- (BOOL)update:(NSString*)key dataValue:(NSData*)data;
- (BOOL)remove:(NSString*)key;
- (NSData*)find:(NSString*)key;

3.在实现文件中添加,

- (id) initWithService:(NSString *) service_ withGroup:(NSString*)group_ {
    self =[super init];
    if(self) {
        service = [NSString stringWithString:service_];
        if(group_)
            group = [NSString stringWithFormat:@"%@.%@",[KeyChain bundleSeedID],group_];
    }
    NSLog(@"%@",group);
    return  self;
}

- (NSMutableDictionary*)prepareDict:(NSString *)key {

    NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
    [dict setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass];

    NSData *encodedKey = [key dataUsingEncoding:NSUTF8StringEncoding];
    [dict setObject:encodedKey forKey:(__bridge id)kSecAttrGeneric];
    [dict setObject:encodedKey forKey:(__bridge id)kSecAttrAccount];
    [dict setObject:service forKey:(__bridge id)kSecAttrService];
    [dict setObject:(__bridge id)kSecAttrAccessibleAlwaysThisDeviceOnly forKey:(__bridge id)kSecAttrAccessible];

    //This is for sharing data across apps
    if(group != nil)
        [dict setObject:group forKey:(__bridge id)kSecAttrAccessGroup];

    return  dict;
}

- (BOOL)insert:(NSString *)key dataValue:(NSData *)data {

    NSMutableDictionary * dict =[self prepareDict:key];
    [dict setObject:data forKey:(__bridge id)kSecValueData];

    OSStatus status = SecItemAdd((__bridge CFDictionaryRef)dict, NULL);
    if(errSecSuccess != status) {
        NSLog(@"Unable add item with key =%@ error:%d",key,(int)status);
    }
    return (errSecSuccess == status);
}

- (NSData*)find:(NSString*)key {
    NSMutableDictionary *dict = [self prepareDict:key];
    [dict setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit];
    [dict setObject:(id)kCFBooleanTrue forKey:(__bridge id)kSecReturnData];
    CFTypeRef result = NULL;
    OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)dict,&result);

    if( status != errSecSuccess) {
        NSLog(@"Unable to fetch item for key %@ with error:%d",key,(int)status);
        return nil;
    }

    return (__bridge NSData *)result;
}

- (BOOL)update:(NSString*)key dataValue:(NSData*)data {

    NSMutableDictionary * dictKey =[self prepareDict:key];
    NSMutableDictionary * dictUpdate =[[NSMutableDictionary alloc] init];
    [dictUpdate setObject:data forKey:(__bridge id)kSecValueData];

    OSStatus status = SecItemUpdate((__bridge CFDictionaryRef)dictKey, (__bridge CFDictionaryRef)dictUpdate);
    if(errSecSuccess != status) {
        NSLog(@"Unable add update with key =%@ error:%d",key,(int)status);
    }
    return (errSecSuccess == status);

    return YES;
}

- (BOOL)remove: (NSString*)key {
    NSMutableDictionary *dict = [self prepareDict:key];
    OSStatus status = SecItemDelete((__bridge CFDictionaryRef)dict);
    if( status != errSecSuccess) {
        NSLog(@"Unable to remove item for key %@ with error:%d",key,(int)status);
        return NO;
    }
    return  YES;
}

+ (NSString *)bundleSeedID {
    NSDictionary *query = [NSDictionary dictionaryWithObjectsAndKeys:
                           (__bridge NSString *)kSecClassGenericPassword, (__bridge NSString *)kSecClass,
                           @"bundleSeedID", kSecAttrAccount,
                           @"Service_name", kSecAttrService,
                           (id)kCFBooleanTrue, kSecReturnAttributes,
                           nil];
    CFDictionaryRef result = nil;
    OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef *)&result);
    if (status == errSecItemNotFound)
        status = SecItemAdd((__bridge CFDictionaryRef)query, (CFTypeRef *)&result);
    if (status != errSecSuccess)
        return nil;
    NSString *accessGroup = [(__bridge NSDictionary *)result objectForKey:(__bridge NSString *)kSecAttrAccessGroup];
    NSArray *components = [accessGroup componentsSeparatedByString:@"."];
    NSString *bundleSeedID = [[components objectEnumerator] nextObject];
    CFRelease(result);
    return bundleSeedID;
}

@end

您可以根据需要调用以下这些方法。

确保您的密钥名称可能相同。

#pragma mark - 钥匙串代表

- (void)storeSensitiveDataToKeychain:(NSString *)value withKey:(NSString *)key {
    [keychainClass insert:[key lowercaseString] :[value dataUsingEncoding:NSUTF8StringEncoding]];
}

- (NSString *)fetchDataFromKeychain:(NSString *)key {
    NSString *keyValue = [[NSString alloc] initWithData:[keychainClass find:[key lowercaseString]] encoding:NSUTF8StringEncoding];
    if (keyValue.length > 0 && ![keyValue isEqual:[NSNull null]]) {
        return keyValue;
    }
    return @"";
}
于 2016-11-08T07:31:53.637 回答