APP密碼??存儲在何處比較安全--密碼存儲

  • 現在很多人對于安全越來越重視,作為程序猿的我們,也需要在這一方面多下功夫,讓我們APP用戶儲存的私人信息更加的安全,我看到過很多的人寫代碼,雖然明文密碼不會被儲存,經常是儲存服務器返回的一個秘鑰,大部分程序猿就裸存了,直接就存儲在NSUserDefaults里面了,也有些程序猿有對其進行AES或DES加密后再儲存,但是其本身AES或DES的秘鑰都是寫在代碼中的,一旦程序被反編譯,想要獲取的秘鑰也是相當容易的一件事了。
  • 蘋果自己本身就有一個方法可以讓我們儲存一些機密的東西,儲存的機制就是將我們需要儲存的東西儲存在鑰匙串??里面,這樣除非整個iOS的安全機制被破解,要不然你儲存的東西就會相對的安全。

下面提供一個工具類KeychainTool用戶存儲

  • KeychainTool.h
#import <Foundation/Foundation.h>

@interface KeychainTool : NSObject

/**
 *  儲存字符串到??鑰匙串
 *
 *  @param sValue 對應的Value
 *  @param sKey   對應的Key
 */
+ (void)saveKeychainValue:(NSString *)sValue Key:(NSString *)sKey;

/**
 *  從??鑰匙串獲取字符串
 *
 *  @param sKey 對應的Key
 *
 *  @return 返回儲存的Value
 */
+ (NSString *)readKeychainValue:(NSString *)sKey;

/**
 *  從??鑰匙串刪除字符串
 *
 *  @param sKey 對應的Key
 */
+ (void)deleteKeychainValue:(NSString *)sKey;

@end

  • KeychainTool.m
#import "KeychainTool.h"

@implementation KeychainTool

+ (NSMutableDictionary *)getKeychainQuery:(NSString *)service
{
    return [NSMutableDictionary dictionaryWithObjectsAndKeys:
            (__bridge_transfer id)kSecClassGenericPassword,(__bridge_transfer id)kSecClass,
            service, (__bridge_transfer id)kSecAttrService,
            service, (__bridge_transfer id)kSecAttrAccount,
            (__bridge_transfer id)kSecAttrAccessibleAfterFirstUnlock,(__bridge_transfer id)kSecAttrAccessible,
            nil];
}

+ (void)saveKeychainValue:(NSString *)sValue Key:(NSString *)sKey
{
    //Get search dictionary
    NSMutableDictionary *keychainQuery = [self getKeychainQuery:sKey];
    //Delete old item before add new item
    SecItemDelete((__bridge_retained CFDictionaryRef)keychainQuery);
    //Add new object to search dictionary(Attention:the data format)
    [keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:sValue] forKey:(__bridge_transfer id)kSecValueData];
    //Add item to keychain with the search dictionary
    SecItemAdd((__bridge_retained CFDictionaryRef)keychainQuery, NULL);
}

+ (NSString *)readKeychainValue:(NSString *)sKey
{
    NSString *ret = nil;
    NSMutableDictionary *keychainQuery = [self getKeychainQuery:sKey];
    
    //Configure the search setting
    [keychainQuery setObject:(id)kCFBooleanTrue forKey:(__bridge_transfer id)kSecReturnData];
    [keychainQuery setObject:(__bridge_transfer id)kSecMatchLimitOne forKey:(__bridge_transfer id)kSecMatchLimit];
    CFDataRef keyData = NULL;
    if (SecItemCopyMatching((__bridge_retained CFDictionaryRef)keychainQuery, (CFTypeRef *)&keyData) == noErr) {
        @try {
            ret = (NSString *)[NSKeyedUnarchiver unarchiveObjectWithData:(__bridge_transfer NSData *)keyData];
        } @catch (NSException *e) {
            NSLog(@"Unarchive of %@ failed: %@", sKey, e);
        } @finally {
        }
    }
    return ret;
}


+ (void)deleteKeychainValue:(NSString *)sKey {
    NSMutableDictionary *keychainQuery = [self getKeychainQuery:sKey];
    SecItemDelete((__bridge_retained CFDictionaryRef)keychainQuery);
}

@end
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容