keychains

keychain在ios中是保存在sqlite数据库中的。
本条数据库文件的职务:
真机:
/private/var/Keychains/keychain-2.db
虚拟机:
/Users/USER-HOME/Library/Developer/CoreSimulator/Devices/26DCA62C-B516-4DEA-A601-5C2D0EA07710/data/Library/Keychains/keychain-2-debug.db
在虚拟机中,这个数据库考出来就不可能读了,很意外。

下边的每一项都代表一张表。每张表的字段是见仁见智的。
kSecClassGenericPassword   对应的表:genp
kSecClassInternetPassword  对应的表:inet
kSecClassCertificate       对应的表:cert
CFTypeRef kSecClassKey     对应的表:keys
CFTypeRef kSecClassIdentity
对应的表:没找到,应该是cert和key这多少个表联起来用,各放一部分。

各类表拥有的字段都是以 kSecAttr起头定义的。
表中有些字段是系统和谐维护的,如cdate:创制时间,mdate:修改时间还有创制者等。
这个字段都指定了数据类型,所以咋样字段放怎么类型的值都是字段定死的。
诸如,kSecClassGenericPassword下的kSecAttrService就只好保留字符串。

因为有点字段的值是枚举类型的,比如
kSecClassInternetPassword下的kSecAttrProtocol字段,就是一个枚举类型,

故而定义了许多kSecAttrProtocol开头的常量。

 

最常用的kSecClassGenericPassword表:genp

以此表的主键是kSecAttrAccount   和kSecAttr瑟维斯(Service)  
,所以新建一项SecItem时,这两项在已有项中不可能重。

这两个常量都对应表的data字段,但在从数据库取出后,会转为不同的数据类型。
那个字段是会加密保存的。
kSecValueData
kSecValueRef
kSecValuePersistentRef

kSecClassGenericPassword item attributes:
        kSecAttrAccessible
        kSecAttrAccessControl
        kSecAttrAccessGroup     对应字段:agrp
        kSecAttrCreationDate    对应字段:cdat 
        kSecAttrModificationDate  对应字段:mdat
        kSecAttrDescription   对应字段:desc
        kSecAttrComment 
        kSecAttrCreator   对应字段:crtr
        kSecAttrType     对应字段:type
        kSecAttrLabel    对应字段:labl
        kSecAttrIsInvisible 对应字段:invi
        kSecAttrIsNegative  对应字段:nega
        kSecAttrAccount   对应字段:acct
        kSecAttrService   对应字段:svce
        kSecAttrGeneric    对应字段:gena

 

苹果官方的KeychainItemWrapper库中用的就是kSecClassGenericPassword,不过用错了。那多少个库太老了,而且很久没更新了,不指出用。

  • (id)initWithIdentifier: (NSString *)identifier accessGroup:(NSString
    *) accessGroup;
    把identifier的值设给了kSecAttrGeneric字段,那是错的,因为kSecAttrGeneric不是主键。

之所以下边的代码中,建第二项时会报错,原因就是主键重复了。
 KeychainItemWrapper * keychin1 = [[KeychainItemWrapper
alloc]initWithIdentifier:@”pwd1″ accessGroup:nil];
 [keychin1 setObject:pwd1 forKey:(__bridge id)kSecValueData];
//上边的推行后,上边的推行出错:
 KeychainItemWrapper * keychin2 = [[KeychainItemWrapper
alloc]initWithIdentifier:@”pwd1″ accessGroup:nil];
 [keychin2 setObject:pwd2 forKey:(__bridge id)kSecValueData];

换成下面的就足以了:
 KeychainItemWrapper * keychin2 = [[KeychainItemWrapper
alloc]initWithIdentifier:@”pwd2″ accessGroup:nil];
 [keychin2 setObject:pwd2 forKey:(__bridge id)kSecAttrService];

网站地图xml地图