我正在使用SSKeyChain库来存储和访问钥匙串中的密码。我正在iPhone模拟器中测试,我可以编写和访问钥匙串。但是当我关闭应用程序时(双击主页按钮,向上轻扫应用程序以使其不再处于后台)我无法访问Keychain中的数据。我的理解是,除非明确删除,否则这些数据将保留在那里。我错了,或者我可能没有正确存储数据?
第二个问题是,这些数据是否应加密或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];
}
}
答案 0 :(得分:0)
此代码看起来正确,除非模拟器正在重置,否则数据应该保持不变。你能在设备上进行测试吗?
要回答第二个问题,根据您的设备和iOS版本,钥匙串密码要么使用3DES或AES加密,要么确切的实施可能在将来发生变化。
答案 1 :(得分:0)
对于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"]
根据current iOS 11 security guide钥匙串项目使用AES 128加密。
钥匙串项目的组件: 与访问组一起,每个Keychain项包含管理元数据(例如“已创建”和“上次更新”时间戳)。 它还包含用于查询项目的属性的SHA-1哈希值(例如帐户和服务器名称),以允许在不解密每个项目的情况下进行查找。最后,它包含加密数据,其中包括以下内容: •版本号 •访问控制列表(ACL)数据 •值,指示项目所在的保护等级 •使用保护类密钥包装的每项密钥 •描述项目的属性字典(传递给SecItemAdd),编码为二进制plist并使用每项密钥加密 加密是GCM中的AES 128(伽罗瓦/计数器模式);访问组包含在属性中,并受加密期间计算的GMAC标记保护。