[英]iOS Keychain Access
我正在使用 SSKeyChain 库来存储和访问钥匙串中的密码。 我正在 iPhone 模拟器中进行测试,我可以编写和访问钥匙串。 但是当我关闭应用程序(双击主页按钮,向上滑动应用程序使其不再在后台)时,我无法访问钥匙串中的数据。 我的理解是,除非特别删除,否则这些数据将保留在那里。 我错了还是我没有正确存储数据?
第二个问题是,这些数据应该加密还是 Keychain 已经处理了? 如果应该加密,有什么建议吗?
这是我的代码:
- (void)viewDidLoad
{
[super viewDidLoad];
/*
Let sskeychain know how the keychain values can be accessed - these are the options:
kSecAttrAccessibleWhenUnlocked Only accessible when device is unlocked.
kSecAttrAccessibleAfterFirstUnlock Accessible while locked. But if the device is restarted it must first be unlocked for data to be accessible again.
kSecAttrAccessibleAlways Always accessible.
kSecAttrAccessibleWhenUnlockedThisDeviceOnly Only accessible when device is unlocked. Data is not migrated via backups.
kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly Accessible while locked. But if the device is restarted it must first be unlocked for data to be accessible again. Data is not migrated via backups.
kSecAttrAccessibleAlwaysThisDeviceOnly Always accessible. Data is not migrated via backups.
*/
[SSKeychain setAccessibilityType:kSecAttrAccessibleWhenUnlocked];
txtUserName = [[UITextField alloc] initWithFrame:CGRectMake((self.view.frame.size.width/2)-100.0, 200.0, 200.0, 30.0)];
txtUserName.placeholder = @"User Name";
txtUserName.font = [UIFont fontWithName:@"Avenir" size:18.0];
txtUserName.layer.cornerRadius = 8.0f;
txtUserName.backgroundColor = [UIColor whiteColor];
txtUserName.layer.borderWidth = 1.0;
[self.view addSubview:txtUserName];
txtSignon = [[UITextField alloc] initWithFrame:CGRectMake((self.view.frame.size.width/2)-100.0, txtUserName.frame.origin.y + txtUserName.frame.size.height + 20.0, 200.0, 30.0)];
txtSignon.placeholder = @"Password";
txtSignon.font = [UIFont fontWithName:@"Avenir" size:18.0];
txtSignon.layer.cornerRadius = 8.0f;
txtSignon.backgroundColor = [UIColor whiteColor];
txtSignon.layer.borderWidth = 1.0;
txtSignon.secureTextEntry = YES;
[self.view addSubview:txtSignon];
UIButton* btnSubmit = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[btnSubmit setTitle:@"Submit" forState:UIControlStateNormal];
[btnSubmit addTarget:self action:@selector(storeValues:) forControlEvents:UIControlEventTouchUpInside];
[btnSubmit setFrame:CGRectMake((self.view.frame.size.width/2)-100, txtSignon.frame.origin.y + txtSignon.frame.size.height + 20.0, 200.0, 30.0)];
[self.view addSubview:btnSubmit];
UIButton* btnGetData = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[btnGetData setTitle:@"Get Stored Credentials" forState:UIControlStateNormal];
[btnGetData addTarget:self action:@selector(getStoredValues:) forControlEvents:UIControlEventTouchUpInside];
[btnGetData setFrame:CGRectMake((self.view.frame.size.width/2)-100, btnSubmit.frame.origin.y + btnSubmit.frame.size.height + 20.0, 200.0, 30.0)];
[self.view addSubview:btnGetData];
}
- (void) storeValues : (UIButton*) myButton {
[self.view endEditing:YES];
//get the saved values
NSString* strUserName = txtUserName.text;
NSString* strUserPass = txtSignon.text;
self.strStoredUserName = strUserName;
//pass them along to the keychain
[SSKeychain setPassword:strUserPass forService:@"com.sanofi.us" account:strUserName];
UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"Success" message:@"Your user name and password were stored in the devices keychain!" delegate:nil cancelButtonTitle:@"Okay" otherButtonTitles:nil, nil];
[alert show];
txtUserName.text = @"";
txtSignon.text = @"";
}
- (void) getStoredValues : (UIButton*) myButton {
NSString* strUserName = self.strStoredUserName;
// Access that token when needed
NSString* strPassword = [SSKeychain passwordForService:@"com.sanofi.us" account:strUserName];
if (strPassword) {
UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"Success" message:[NSString stringWithFormat:@"Your credentials stored in the keychain are:\nUsername: %@\nPassword: %@", strUserName, strPassword] delegate:nil cancelButtonTitle:@"Okay" otherButtonTitles:nil, nil];
[alert show];
}
}
这段代码看起来是正确的,除非模拟器被重置,否则数据应该会一直存在。 你能在设备上测试吗?
要回答第二个问题,根据您的设备和 iOS 版本,钥匙串密码使用 3DES 或 AES 加密,但确切的实现方式将来可能会发生变化。
对于 Swift,您可以使用KeychainAccess ,它更易于使用:
// Create keychain object
let keychain = Keychain(service: "com.company.AppName")
// Store value in keychain
keychain["password"] = "test"
// Retrieve value from keychain
let password = keychain["password"]
根据当前的 iOS 11 安全指南,钥匙串项目使用 AES 128 加密。
Keychain 项目的组件:与访问组一起,每个 Keychain 项目都包含管理元数据(例如“创建”和“上次更新”时间戳)。 它还包含用于查询项目(例如帐户和服务器名称)的属性的 SHA-1 哈希值,以允许在不解密每个项目的情况下进行查找。 最后,它包含加密数据,其中包括以下内容: • 版本号 • 访问控制列表 (ACL) 数据 • 指示项目所在保护级别的值 • 用保护级别密钥包装的每项密钥 • 属性字典描述项目(传递给 SecItemAdd),编码为二进制 plist 并使用每个项目的密钥加密 加密是 GCM(Galois/Counter Mode)中的 AES 128; 访问组包含在属性中,并受加密期间计算的 GMAC 标记保护。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.