The keychain is about the only place that an iPhone application can safely store data that will be preserved across a re-installation of the application. Each iPhone application gets its own set of keychain items which are backed up whenever the user backs up the device via iTunes. The backup data is encrypted as part of the backup so that it remains secure even if somebody gets access to the backup data. This makes it very attractive to store sensitive data such as passwords, license keys, etc.
The only problem is that accessing the keychain services is complicated and even the GenericKeychain example code is hard to follow. I hate to include cut and pasted code into my application, especially when I do not understand it. Instead I have gone back to basics to build up a simple iPhone keychain access example that does just what I want and not much more.
In fact all I really want to be able to do is securely store a password string for my application and be able to retrieve it a later date.
Getting Started
A couple of housekeeping items to get started:
- Add the “Security.framework” framework to your iPhone application
- Include the header file <Security/Security.h>
Note that the security framework is a good old fashioned C framework so no Objective-C style methods calls. Also it will only work on the device not in in the iPhone Simulator.
The Basic Search Dictionary
All of the calls to the keychain services make use of a dictionary to define the attributes of the keychain item you want to find, create, update or delete. So the first thing we will do is define a function to allocate and construct this dictionary for us:
static NSString *serviceName = @"com.mycompany.myAppServiceName";
- (NSMutableDictionary *)newSearchDictionary:(NSString *)identifier {
NSMutableDictionary *searchDictionary = [[NSMutableDictionary alloc] init];
[searchDictionary setObject:(id)kSecClassGenericPassword forKey:(id)kSecClass];
NSData *encodedIdentifier = [identifier dataUsingEncoding:NSUTF8StringEncoding];
[searchDictionary setObject:encodedIdentifier forKey:(id)kSecAttrGeneric];
[searchDictionary setObject:encodedIdentifier forKey:(id)kSecAttrAccount];
[searchDictionary setObject:serviceName forKey:(id)kSecAttrService];
return searchDictionary;
}
The dictionary contains three items. The first with key kSecClass defines the class of the keychain item we will be dealing with. I want to store a password in the keychain so I use the value kSecClassGenericPassword for the value.
The second item in the dictionary with key kSecAttrGeneric is what we will use to identify the keychain item. It can be any value we choose such as “Password” or“LicenseKey”, etc. To be clear this is not the actual value of the password just a label we will attach to this keychain item so we can find it later. In theory our application could store a number of passwords in the keychain so we need to have a way to identify this particular one from the others. The identifier has to be encoded before being added to the dictionary
The combination of the final two attributes kSecAttrAccount and kSecAttrServiceshould be set to something unique for this keychain. In this example I set the service name to a static string and reuse the identifier as the account name.
You can use multiple attributes for a given class of item. Some of the other attributes that we could also use for the kSecClassGenericPassword item include an account name, description, etc. However by using just a single attribute we can simplify the rest of the code.
Searching the keychain
To find out if our password already exists in the keychain (and what the value of the password is) we use the SecItemCopyMatching function. But first we add a couple of extra items to our basic search dictionary:
- (NSData *)searchKeychainCopyMatching:(NSString *)identifier {
NSMutableDictionary *searchDictionary = [self newSearchDictionary:identifier];
// Add search attributes
[searchDictionary setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit];
// Add search return types
[searchDictionary setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData];
NSData *result = nil;
OSStatus status = SecItemCopyMatching((CFDictionaryRef)searchDictionary,
(CFTypeRef *)&result);
[searchDictionary release];
return result;
}
The first attribute we add to the dictionary is to limit the number of search results that get returned. We are looking for a single entry so we set the attributekSecMatchLimit to kSecMatchLimitOne.
The next attribute determines how the result is returned. Since in our simple case we are expecting only a single attribute to be returned (the password) we can set the attribute kSecReturnData to kCFBooleanTrue. This means we will get an NSData reference back that we can access directly.
If we were storing and searching for a keychain item with multiple attributes (for example if we were storing an account name and password in the same keychain item) we would need to add the attribute kSecReturnAttributes and the result would be a dictionary of attributes.
Now with the search dictionary set up we call the SecItemCopyMatching function and if our item exists in the keychain the value of the password is returned to in the NSData block. To get the actual decoded string you could do something like:
NSData *passwordData = [self searchKeychainCopyMatching:@"Password"];
if (passwordData) {
NSString *password = [[NSString alloc] initWithData:passwordData
encoding:NSUTF8StringEncoding];
[passwordData release];
}
Creating an item in the keychain
Adding an item is almost the same as the previous examples except that we need to set the value of the password we want to store.
- (BOOL)createKeychainValue:(NSString *)password forIdentifier:(NSString *)identifier {
NSMutableDictionary *dictionary = [self newSearchDictionary:identifier];
NSData *passwordData = [password dataUsingEncoding:NSUTF8StringEncoding];
[dictionary setObject:passwordData forKey:(id)kSecValueData];
OSStatus status = SecItemAdd((CFDictionaryRef)dictionary, NULL);
[dictionary release];
if (status == errSecSuccess) {
return YES;
}
return NO;
}
To set the value of the password we add the attribute kSecValueData to our search dictionary making sure we encode the string and then call SecItemAddpassing the dictionary as the first argument. If the item already exists in the keychain this will fail.
Updating a keychain item
Updating a keychain is similar to adding an item except that a separate dictionary is used to contain the attributes to be updated. Since in our case we are only updating a single attribute (the password) this is easy:
- (BOOL)updateKeychainValue:(NSString *)password forIdentifier:(NSString *)identifier {
NSMutableDictionary *searchDictionary = [self newSearchDictionary:identifier];
NSMutableDictionary *updateDictionary = [[NSMutableDictionary alloc] init];
NSData *passwordData = [password dataUsingEncoding:NSUTF8StringEncoding];
[updateDictionary setObject:passwordData forKey:(id)kSecValueData];
OSStatus status = SecItemUpdate((CFDictionaryRef)searchDictionary,
(CFDictionaryRef)updateDictionary);
[searchDictionary release];
[updateDictionary release];
if (status == errSecSuccess) {
return YES;
}
return NO;
}
Deleting an item from the keychain
The final (and easiest) operation is to delete an item from the keychain using theSecItemDelete function and our usual search dictionary:
- (void)deleteKeychainValue:(NSString *)identifier {
NSMutableDictionary *searchDictionary = [self newSearchDictionary:identifier];
SecItemDelete((CFDictionaryRef)searchDictionary);
[searchDictionary release];
}
相关推荐
`KeychainAccess`是一个开源Swift库,它为开发者提供了一种简单易用的方式来操作Keychain,使得原本复杂的Objective-C接口变得更为简洁。本项目通过`KeychainAccess`对Keychain进行了封装,旨在提高开发效率,降低...
钥匙串访问 KeychainAccess是适用于iOS和OS X的Keychain的简单Swift包装器。它使Keychain API的使用极为简便,并且在Swift中使用起来更加可口。 :light_bulb: 产品特点简单的界面支持访问组 :open_book: 用法 :eyes:...
9. **Keychain Access Groups**:通过配置Keychain Access Groups,可以控制哪些应用程序可以访问特定的Keychain项目,这对于跨应用的数据共享非常有用。 10. **Keychain Item Types**:Keychain支持多种类型的条目...
本项目提供了一个名为"KeychainAccess"的简单Swift包装器,它简化了对Keychain API的调用,使开发者能够更方便地在各种Apple设备上使用Keychain功能。 KeychainAccess库的主要优点在于其易用性和跨平台兼容性。它...
4. **共享访问**: 如果需要在多个应用程序间共享数据,可以通过设置Keychain Access Group实现。这需要在应用程序的Info.plist文件中指定相同的Keychain Access Group标识符。 5. **错误处理**: ...
- 访问标识符(Access Identifier,简称Access Group):如果多个应用需要共享同一份Keychain数据,可以通过设置相同的访问标识符实现。否则,每个应用的数据默认是独立的。 2. **KeychainItemWrapper**: 这是...
KeyChain的设计旨在确保数据的安全性,即使应用程序被删除,存储在KeyChain中的信息也不会丢失,用户重新安装应用后仍可访问。 KeyChain服务的核心概念是“KeyChain项”,每个项都代表一个独立的数据条目,可以包含...
Keychain服务允许应用将这些数据安全地存储,并在需要时检索,而无需每次都要求用户输入。本Demo是关于如何使用Keychain进行数据AES加密的实践。 首先,了解Keychain的基本概念。Keychain并不是一个简单的字典或...
本资源“最新IOS KeyChain的封装”提供了一种方便快捷的方式来操作Keychain,它已经过真机测试,可以直接应用于项目中。 Keychain的基本概念: 1. **Keychain Item**: Keychain中的每一项数据被称为Keychain Item,...
在iOS开发中,Keychain库是一个非常重要的工具,它用于安全地存储用户的敏感信息,如密码、证书和访问令牌。Keychain服务通过提供一个统一的接口来管理这些数据,确保了数据的安全性和隐私性,避免了明文存储带来的...
首先,下载并安装Apple Worldwide Developer Relations Certification Authority(AppleWWDRCA.cer)到Keychain Access。然后,通过Keychain Access生成一个Certificate Signing Request(CSR)文件,这将用于向...
2. **导入CSR到Keychain Access**:在Mac上,使用Keychain Access应用程序导入CSR,这将生成一个私钥和对应的证书。 3. **添加设备和Provisioning Profile**:在开发者门户中,开发者需要添加他们的设备UDID,创建...
1、按压缩包内路径添加至unity工程,若工程内划分了程序集,可以自行在Assets\Plugins\iOS\Keychain路径下创建程序集 2、打开KeychainWrapper.m文件,将appStoreTeamID和accessGroup设置为自己的AppStore Team ID ...
Keychain就是苹果提供的一种安全存储解决方案。Keychain服务允许开发者将这些信息存储在一个加密的数据库中,保证了数据的安全性。下面我们将深入探讨iOS中的Keychain开发。 一、Keychain的基本概念 Keychain是iOS...
apk文件 KeyChain(电视直播视频)apk文件 KeyChain(电视直播视频)apk文件 KeyChain(电视直播视频)apk文件 KeyChain(电视直播视频)apk文件 KeyChain(电视直播视频)apk文件 KeyChain(电视直播视频)apk文件 ...
其中,`Keychain`是一种安全、持久的数据存储方式,尤其适用于存储敏感信息,如用户凭据、密码和其他个人识别信息(PII)。本篇文章将深入探讨如何在Swift中封装Keychain以实现数据的永久保存。 一、Keychain的基本...
在Android平台上,KeyChain是一个非常重要的安全组件,它主要用于存储和管理用户的证书和私钥,为应用程序提供安全的加密通信。这份"Android应用源码之KeyChain_源码.zip"包含的是KeyChain组件的源代码,这对于理解...
`ios-keychain.zip`中的内容很可能是关于如何利用`Keychain`进行安全数据存储的示例代码。 `Keychain`是iOS提供的一种安全存储机制,它是一个专门用于存储诸如用户账号、密码、证书等敏感信息的安全数据库。与`...
LibGDX是一个流行的跨平台游戏开发框架,而"ios存入资源到keychain SDK"的标签中提到了"libgdx ios keychain sdk 绑定",这表明这个SDK可能是为了解决在使用LibGDX开发iOS应用时,如何在LibGDX中接入和使用Keychain ...