Research on the keychain Storage Structure in iOS, ioskeychain
Keychain is stored in the sqlite database in ios.
Location of the database file:
Real machine:
/Private/var/Keychains/keychain-2.db
Virtual Machine:
/Users/USER-HOME/Library/Developer/CoreSimulator/Devices/26DCA62C-B516-4DEA-A601-5C2D0EA07710/data/Library/Keychains/keychain-2-debug.db
In a virtual machine, this database cannot be read after it is obtained, which is strange.
Each of the following items represents a table. The fields in each table are different.
Table corresponding to kSecClassGenericPassword: genp
Table corresponding to kSecClassInternetPassword: inet
Table corresponding to kSecClassCertificate: cert
Table corresponding to CFTypeRef kSecClassKey: keys
Table corresponding to CFTypeRef kSecClassIdentity: Not found. It should be the two tables cert and key used together, each with a part.
Fields in each table are defined starting with kSecAttr.
Some fields in the table are maintained by the system, such as cdate: Creation Time, mdate: modification time, and creator.
All these fields specify the data type. Therefore, the field determines the type of the field value.
For example, kSecAttrService under kSecClassGenericPassword can only save strings.
Because the values of some fields are of the enumeration type, such
The kSecAttrProtocol field under kSecClassInternetPassword is an enumeration type,
Therefore, many constants starting with kSecAttrProtocol are defined.
The most common kSecClassGenericPassword table: genp
The primary keys of this table are kSecAttrAccount and kSecAttrService. Therefore, when a new SecItem item is created, the two items cannot be duplicated in the existing items.
All three constants correspond to the data fields of the table, but after being retrieved from the database, they are converted to different data types.
This field is encrypted and saved.
KSecValueData
KSecValueRef
KSecValuePersistentRef
KSecClassGenericPassword item attributes:
KSecAttrAccessible
KSecAttrAccessControl
The corresponding field of kSecAttrAccessGroup: agrp
KSecAttrCreationDate field: cdat
KSecAttrModificationDate field: mdat
KSecAttrDescription field: desc
KSecAttrComment
KSecAttrCreator field: crtr
KSecAttrType: type
KSecAttrLabel: labl
KSecAttrIsInvisible field: invi
KSecAttrIsNegative: nega
KSecAttrAccount field: acct
Corresponding field of kSecAttrService: svce
KSecAttrGeneric field: gena
KSecClassGenericPassword is used in the official KeychainItemWrapper library, but an error is returned. This database is too old and has not been updated for a long time. It is not recommended.
-(Id) initWithIdentifier: (NSString *) identifier accessGroup :( NSString *) accessGroup;
Set the value of identifier to the kSecAttrGeneric field. This is incorrect because kSecAttrGeneric is not the primary key.
In the following code, an error is reported when the second item is created, because the primary key is repeated.
KeychainItemWrapper * keychin1 = [[KeychainItemWrapper alloc] initWithIdentifier: @ "pwd1" accessGroup: nil];
[Keychin1 setObject: pwd1 forKey :( _ bridge id) kSecValueData];
// After the preceding execution, the following execution error occurs:
KeychainItemWrapper * keychin2 = [[KeychainItemWrapper alloc] initWithIdentifier: @ "pwd2" accessGroup: nil];
[Keychin2 setObject: pwd2 forKey :( _ bridge id) kSecValueData];
Replace it with the following:
KeychainItemWrapper * keychin2 = [[KeychainItemWrapper alloc] initWithIdentifier: @ "pwd2" accessGroup: nil];
[Keychin2 setObject: pwd2 forKey :( _ bridge id) kSecAttrService];