iOS進階學習-網路之資料安全,ios進階
一、資料安全
1、術語:
- 密鑰:密鑰是一種參數,它是在明文轉換為密文或將密文轉換為明文的演算法中輸入的參數。密鑰分為對稱金鑰與非對稱金鑰(也可以根據用途來分為加密金鑰和解密密鑰)。
- 明文:沒有進行加密,能夠直接代表原文含義的資訊。
- 密文:經過加密處理處理之後,隱藏原文含義的資訊。
- 加密:將明文轉換成密文的實施過程。
- 解密:將密文轉換成明文的實施過程。
2、資料安全
- 資料安全:是一種主動的包含措施,資料本身的安全必須基於可靠的密碼編譯演算法與安全體系,主要是有對稱演算法與公開密鑰密碼體系兩種(非對稱演算法),都包含了資料的加密和解密過程
- 對稱演算法:對稱密碼演算法有時又叫傳統密碼演算法,是指加密金鑰可以從解密密鑰中推算出來,反過來也成立。
- 非對稱演算法:非對稱金鑰也叫公開祕密金鑰加密,就是不能由其中一個密鑰推匯出另一個密鑰。
- 密碼編譯演算法有很多種,在iOS開發當中,MD5是我們常用的摘要演算法。
二、MD5加密
1、雜湊演算法:
- 雜湊演算法:雜湊演算法將任意長度的二進位值對應為較短的固定長度的二進位值,這個小的二進位值稱為雜湊值。
- 雜湊值是一段資料唯一且極其緊湊的數值表示形式。資料的雜湊值可以檢驗資料的完整性。一般用於快速尋找和密碼編譯演算法。
- 典型的的雜湊演算法有:MD2、MD4、MD5 和 SHA-1等。
2、MD5:
- MD5:Message Digest Algorithm MD5(中文名為訊息摘要演算法第五版)為電腦安全領域廣泛使用的一種散列函數,用以提供訊息的完整性保護。
- MD5演算法具有以下特點:
- 壓縮性:任意長度的資料,算出的MD5值長度都是固定的(16進位,32位)。
- 容易計算:從原資料計算出MD5值很容易。
- 抗修改性:對原資料進行任何改動,哪怕只修改1個位元組,所得到的MD5值都有很大區別。
- 強抗碰撞:已知原資料和其MD5值,想找到一個具有相同MD5值的資料(即偽造資料)是非常困難的。
3、擷取字串MD5值:引入<CommonCrypto/CommonCrypto.h>、擷取字串的MD5值。
程式碼範例:
// 1.準備一個字串用於加密(同一個字串進行MD5加密出來的內容類別似) NSString *str = @"I Love you"; // 2.因為MD5是基於C語言的,所以需要將字串進行編碼 const char *data = [str UTF8String]; // 3.使用字串數組去存取加密後相關的內容(MD5 16進位,32位) // CC_MD5_DIGEST_LENGTH 表示長度 unsigned char result [CC_MD5_DIGEST_LENGTH]; // 4.進行MD5加密 // 參數1:需要加密的內容 // 參數2:要加密的data的一個長度 // 參數3:儲存加密結果的數組(MD5) CC_MD5(data, (CC_LONG)strlen(data), result); // 5.建立可變字串,儲存結果 NSMutableString *mStr = [NSMutableString string]; // 6.遍曆結果數組,然後添加到可變字串中 for (int i = 0; i < CC_MD5_DIGEST_LENGTH; i++) { [mStr appendFormat:@"%02x", result[i]]; }
4、擷取其它對象MD5值:引入<CommonCrypto/CommonCrypto.h>、將其它對象轉化為NSData對象(可以將對象事先寫入檔案)、讀取NSData對象的MD5值。
程式碼範例:(以數組為例)
// 需求:建立一個數組,數組中儲存元素,將這個數組寫入到沙箱裡 // 建立數組 NSArray *array = @[@"Jack", @"Rose"]; // 找沙箱路徑 NSString *path = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0]; // 拼接路徑 NSString *arrayPath = [path stringByAppendingPathComponent:@"array.plist"]; // 寫入 [sender writeToFile:arrayPath atomically:YES]; // 從沙箱中取出NSData資料 NSData *data = [NSData dataWithContentsOfFile:arrayPath]; // NSData類型資料加密過程 // 1.建立MD5對象 CC_MD5_CTX md5; // 2.初始化MD5對象 CC_MD5_Init(&md5); // 3.準備開始進行資料加密 CC_MD5_Update(&md5, data.bytes, (CC_LONG)data.length); // 4.結束MD5加密 // 準備一個字串數組用來儲存結果 unsigned char result[CC_MD5_DIGEST_LENGTH]; CC_MD5_Final(result, &md5); // 5.擷取結果 NSMutableString *mStr = [[NSMutableString alloc] initWithCapacity:CC_MD5_DIGEST_LENGTH]; // 遍曆數組給可變字串賦值 for (int i = 0; i< CC_MD5_DIGEST_LENGTH; i++) { [mStr appendFormat:@"%02x", result[i]]; } NSLog(@"%@", mStr);
註:
- 雜湊演算法是一種摘要演算法,主要作用是用來擷取資料的摘要。嚴格意義上來說不屬於密碼編譯演算法(因為沒有解密過程)
- 擷取字串的MD5值比較簡單,其它對象可以先轉化成NSData對象再進行操作
- 可以根據路徑直接擷取檔案資料,也可以將對象寫入檔案件後擷取為NSData對象
- iOS同樣支援SHA1、base64、AES、鑰匙串等方式加密資料
三、鑰匙串加密
1、鑰匙串簡介:鑰匙串:(英文:Keychain)是蘋果公司Mac OS中的密碼管理系統。它在Mac OS 8.6中和iOS7之後被匯入,並且包括在了所有後續的各版本中。一個鑰匙串可以包含多種類型的資料:密碼(包括網站,FTP伺服器,SSH帳戶,網際網路共用,無線網路,群組軟體,加密磁碟鏡像等),私密金鑰,電子認證和加密筆記等。
2、鑰匙串加密:
- 蘋果 iOS 和 Mac OS X 系統內建了一套敏感資訊儲存方案:"鑰匙串" (Keychain)。
- 儲存在鑰匙串的內容相當於系統對其做了保護,在鎖定裝置時進行了加密處理。
- 鑰匙串中的條目稱為SecItem,但它是儲存在CFDictionary中的。SecItemRef類型並不存在。SecItem有五類:通用密碼互連網密碼、認證、密鑰和身份。在大多數情況下,我們用到的都是通用密碼。
- 鑰匙串的使用和字典非常的相似。
- 用原生的 Security.framework 就可以實現鑰匙串的訪問、讀寫。但是只能在真機上進行。通常我們使用KeychainItemWrapper(github)來完成鑰匙串的加密。
3、鑰匙串的使用:
- 拷貝鑰匙串類到工程中
- 引入標準標頭檔
- 產生鑰匙串對象
- 儲存加密的資料
- 獲得鑰匙串對象
- 擷取加密的資料
- 程式碼範例:
// 首先需要匯入鑰匙串的第三方KeychainItemWrapper.h/m // 建立鑰匙串對象 // 參數1:標識,用於識別後面加密的內容(回傳標識符) // 參數2:分組,一般為nil KeychainItemWrapper *keychainItem = [[KeychainItemWrapper alloc] initWithIdentifier:identifier accessGroup:nil]; // 常用與加密使用者名稱和密碼 // 系統提供的索引值對中的兩個鍵,非系統的鍵是沒法添加到字典中的 id kUserName = (__bridge id)kSecAttrAccount; id kPasswordName = (__bridge id)kSecValueData; [keychainItem setObject:@"user" forKey:kUserName]; [keychainItem setObject:@"123456" forKey:kPasswordName]; // 通過相同的標識建立的鑰匙串中具有相同的資料 KeychainItemWrapper *keychainItem2 = [[KeychainItemWrapper alloc] initWithIdentifier:identifier accessGroup:nil]; NSString *name = [keychainItem objectForKey:kUserName]; NSString *pwd = [keychainItem2 objectForKey:kPasswordName]; NSLog(@"%@, pwd = %@", name, pwd);
4、注意:
- 引入的標頭檔是MRC模式的,需要進行混編
- 擷取對象的時候Identify必須一致
- 非系統key值是無法添加到字典中的
四、公開金鑰加密
1、公開金鑰加密簡介:
- 公開金鑰加密也叫非對稱式加密。
- 常用演算法有RSA、ElGamal、背包演算法、Rabin等等,IOS中用的最多的是RSA(github)。
- iOS 使用 RSA 加密, 只需要公開金鑰。
- 首先需要引入第三方RSA.h。
2、公開金鑰加密:(公開金鑰和私密金鑰的具體產生方法)
//公開金鑰和私密金鑰都是使用認證產生的,並非我們自訂字串就可以。我們使用的是產生好的公開金鑰和私密金鑰//其中-----BEGIN PUBLIC KEY-----和-----END PUBLIC KEY-----不屬於密鑰部分//公開金鑰:iOS用戶端使用,我們拿到手公開金鑰以後,只需要根據公開金鑰處理資料就可以 // 擷取公開金鑰的資料 NSString *publicKey = @"-----BEGIN PUBLIC KEY-----MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDfzVL2ZaZvmSGAl6j3Fxsn1aqYq1gbDhQGZIeLxDwh5FVNdIvGIFe/S3wlTIO8lHlc9IACD894GG6Aqlfs24oTgKeHGCIiaBKB7x3g458/GbwSiOryUnVxJKFkV+lKB9TlJJW4egcHieiN/m1xKnlKmRsGlTJYyoY7Nhihyc8HAQIDAQAB-----END PUBLIC KEY-----"; // 建立字串 NSString *testStr = @"加密樣本"; // 建立儲存公開金鑰的字串,加密 NSString *encPublicKey = [RSA encryptString:testStr publicKey:publicKey]; NSLog(@"encpublic = %@", encPublicKey);
3、私密金鑰解密:(私密金鑰解密的字串需要由JAVA後台提供,)
// 私密金鑰:用於解密資料的.注意:不能泄露,否則資料不安全! NSString *privateKey = @"-----BEGIN PRIVATE KEY-----MIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAN/NUvZlpm+ZIYCX qPcXGyfVqpirWBsOFAZkh4vEPCHkVU10i8YgV79LfCVMg7yUeVz0gAIPz3gYboCqV+zbihOAp4cYIiJoEoHvHeDjnz8ZvBKI6vJSdXEkoWRX6UoH1OUklbh6BweJ6I3+bXEqeUqZGwaVMljKhjs2GKHJzwcBAgMBAAECgYEAjPJIv3kBOuNb4BqjhQn+RjYgfIncsR1Kq0QAwZtSq52bw24U4TBZUtZ9Vxg7FzcCv/IT9Dh01xO79DhTq44QBE7Gkxy9sLK/uKo6ffnYxWxx0/l6yWtPLiwRfzvI1BInnxf24UOn/Qe1wZPBG305y3es2mdIem5Kko7SVHqtLYECQQDzd4cxIYcOZIyVWjTCIpwC6w45yRbndBbpt4GpgOZ6 hGQ8eeFHpZjLnJgHWISnCvCG76PWBFG+4fwewL7/5mNJAkEA61Klr4wnMCUyrkjAPK+pt9yQLb71qoobendLFd1BoYL1fZNar3ntkq0bp4AB+MkwS2dZvXAJKXTtyw9fBH/N+QJBAKwXbOP5gvFVeVmIbYpb1FLrux51WU8464lAQNKDXmZzdjaZH/f4wUwK4BsxInLAdMusT+5TF0UJj6BdNaTEQKECQ+duJLt7BwM2tVzORrOfKwMgEwRYMpSSb8dFl9lNtuEkUIIqAfrxwuv5XGeMEf0BcasMfdoDSKLW3aENLjHV5kCQQC4FJK6 nB02fK7f1co1254OlaYHDmD7NErYAazqeT+KVHZjV76rO6BGeldy+SnXTzLrWGbIjxgYr1bFTXL+0AI/-----END PRIVATE KEY-----"; // 建立儲存私密金鑰的字串 NSString *result = @"";// 經過加密之後需要把加密的內容傳送給後台,此時後台會給你返回一個字串 // 參數1:由java後台提供 // 參數2:私密金鑰 NSString *encPrivateKey = [RSA decryptString:result privateKey:privateKey]; NSLog(@"(PHP enc)encPrivate = %@", encPrivateKey);
五、KVO
1、KVO簡介:
- KVO:(Key-Value-Observer)索引值觀察者,是觀察者設計模式的一種具體實現。
- KVO觸發機制:一個對象(觀察者),監測另一對象(被觀察者)的某屬性是否發生變化,若被監測的屬性發生的更改,會觸發觀察者的一個方法(方法名固定,類似代理方法)。
2、KVO使用步驟:
- 註冊觀察者(為被觀察者指定觀察者以及被觀察屬性)
;
- 實現回調方法
;
- 觸發回調方法(被觀察屬性發生更改);
- 移除觀察者。
- 程式碼範例:
- (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view, typically from a nib. // 第一步:註冊觀察者\ //參數1:添加的觀察者對象\ //參數2:字串標識的key\ //參數3:什麼時候回觸發添加觀察者對象\ //NSKeyValueObservingOptionNew key和value只要有一個更新的時候就會觸發\ //NSKeyValueObservingOptionOld \ //NSKeyValueObservingOptionInitial\ //NSKeyValueObservingOptionPrior\ //參數4:常值內容 一般為nil [self addObserver:self forKeyPath:@"array" options:NSKeyValueObservingOptionNew context:nil];}// 視圖將要消失的時候- (void)viewWillDisappear:(BOOL)animated{ // 在不需要觀察者的時候 [self removeObserver:self forKeyPath:@"array"];}// 第二步:實現回調方法- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context{ NSLog(@"keyPath = %@",keyPath); NSLog(@"object = %@", object); NSLog(@"change = %@", change); // 可以進行重新整理UI的操作 }// 第三步:觸發可變數組進行改變- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{ NSArray *subArr = @[@"1", @"2", @"3"]; // 根據keyPath擷取到可變資料對象,setArray給可變數組對象設定資料 [[self mutableArrayValueForKeyPath:@"array"] setArray:subArr]; NSLog(@"subArr = %@", [self mutableArrayValueForKeyPath:@"array"]);}