簡體   English   中英

iOS 鑰匙串訪問

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM