一:基本知识
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
在虚拟机中,这个数据库考出来就不能读了,很奇怪,不过也可以打开MAC上的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
这三个常量都对应表的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
使用到的api:
SecItemAdd 增
SecItemDelete 删
SecItemUpdate 改
SecItemCopyMatching 查
首先使用kSecReturnAttributes = kCFBooleanTrue;查找属性值是否存在。若属性存在,则使用kSecReturnData = kCFBooleanTrue;获取data即密码字段,并转换称NSString返回。属性存在,而密码不存在时返回特殊的错误码。
需要共享数据的应用,要保证AppIdentifierPrefix(也叫teamid, 一个appId账号对应一个teamid)相同。
二、代码部分,可以参考下苹果自带的demo:KeychainItemWrapper