iOS keychain入门
学了很久的iOS,一直都是明文保存用户名和密码在本地,手机一般都是自己用的,而且非越狱手机东西也不怎么能拿到数据,所以也就没在乎那么多,当然,这是不科学的。悄悄的说,这块一直不是我写的~~~
用户隐私信息正常都是加密保存在本地,各种各样的加密方法,大家自己去找找就好了,今天介绍下keychain。
官方文档介绍如下:
Keychain Services provides secure storage of passwords, keys, certificates, and notes for one or more users. A user can unlock a keychain with a single password, and any Keychain Services–aware application can then use that keychain to store and retrieve passwords。
简单的翻译下,keychain可以存储密码、证书等等,至于有什么好处,呵呵哒,自己百度去吧,总结一点就是更安全,而且取的更方便吧,看app场景吧。
本次代码,分为两段,一段为保存代码
1 - (BOOL)saveData:(NSString *)str 2 { 3 OSStatus status = noErr; 4 NSMutableDictionary *query = [[NSMutableDictionary alloc] init]; 5 [query setObject:(id)kSecClassGenericPassword forKey:(id)kSecClass]; 6 /// query one 7 [query setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit]; 8 [query setObject:@"password" forKey:(id)kSecAttrService]; 9 CFMutableDictionaryRef outDicRef = nil; 10 status = SecItemCopyMatching((CFDictionaryRef)query, (CFTypeRef *)&outDicRef); 11 if(status==noErr) 12 { 13 NSLog(@"#######################query success"); 14 [query removeObjectForKey:(id)kSecMatchLimit]; 15 NSLog(@"=============code %d",SecItemDelete((CFDictionaryRef)query)); 16 NSMutableDictionary *dt = [[NSMutableDictionary alloc] init]; 17 [dt setObject:@"label" forKey:(id)kSecAttrLabel]; 18 [dt setObject:@"password" forKey:(id)kSecAttrService]; 19 [dt setObject:[str dataUsingEncoding:NSUTF8StringEncoding] forKey:(id)kSecValueData]; 20 [dt setObject:(id)kSecClassGenericPassword forKey:(id)kSecClass]; 21 22 [dt setObject:@"Item label" forKey:(__bridge id)kSecAttrLabel]; 23 24 [dt setObject:@"Item description" forKey:(__bridge id)kSecAttrDescription]; 25 26 [dt setObject:@"Account" forKey:(__bridge id)kSecAttrAccount]; 27 28 [dt setObject:@"Service" forKey:(__bridge id)kSecAttrService]; 29 30 [dt setObject:@"Your comment here." forKey:(__bridge id)kSecAttrComment]; 31 status = SecItemAdd((CFDictionaryRef)dt, NULL); 32 if(status==noErr) 33 { 34 NSLog(@"#######################save success"); 35 return YES; 36 } 37 return YES; 38 } 39 else 40 if(status==errSecItemNotFound) 41 { 42 NSLog(@"#####################not found"); 43 //store 44 NSMutableDictionary *dt = [[NSMutableDictionary alloc] init]; 45 [dt setObject:@"label" forKey:(id)kSecAttrLabel]; 46 [dt setObject:@"password" forKey:(id)kSecAttrService]; 47 [dt setObject:[str dataUsingEncoding:NSUTF8StringEncoding] forKey:(id)kSecValueData]; 48 [dt setObject:(id)kSecClassGenericPassword forKey:(id)kSecClass]; 49 50 [dt setObject:@"Item label" forKey:(__bridge id)kSecAttrLabel]; 51 52 [dt setObject:@"Item description" forKey:(__bridge id)kSecAttrDescription]; 53 54 [dt setObject:@"Account" forKey:(__bridge id)kSecAttrAccount]; 55 56 [dt setObject:@"Service" forKey:(__bridge id)kSecAttrService]; 57 58 [dt setObject:@"Your comment here." forKey:(__bridge id)kSecAttrComment]; 59 status = SecItemAdd((CFDictionaryRef)dt, NULL); 60 if(status==noErr) 61 { 62 NSLog(@"#######################save success"); 63 return YES; 64 } 65 if(outDicRef) 66 CFRelease(outDicRef); 67 return NO; 68 } 69 else 70 { 71 NSLog(@"########################error query %d",status); 72 } 73 return NO; 74 }
代码有些凌乱,各位将就下吧,急着去睡觉~
读取代码如下:
1 - (NSString *)getData 2 { 3 OSStatus status = noErr; 4 NSMutableDictionary *query = [[NSMutableDictionary alloc] init]; 5 [query setObject:(id)kSecClassGenericPassword forKey:(id)kSecClass]; 6 /// query one 7 [query setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit]; 8 [query setObject:@"Service" forKey:(id)kSecAttrService]; 9 ///如果想取到相关属性,这里必须设置。就这个地方,害我搞半天 10 [query setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnAttributes]; 11 CFDictionaryRef attributes = nil; 12 ///取到属性了 13 status = SecItemCopyMatching((__bridge CFDictionaryRef)query, (CFTypeRef *)&attributes); 14 if(status==noErr) 15 { 16 NSLog(@"--------%@",attributes); 17 } 18 [query removeObjectForKey:(id)kSecReturnAttributes]; 19 CFDataRef outData; 20 ///取值,实际存放密码的地方,这里要设置 21 [query setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData]; 22 status = SecItemCopyMatching((CFDictionaryRef)query, (CFTypeRef *)&outData); 23 ///解析回来 24 NSString *str = [[NSString alloc] initWithData:(__bridge NSData *)outData encoding:NSUTF8StringEncoding]; 25 return str; 26 }
测试下:
取到属性:
取密码