iOS 登入加密

小輝哥的掘金發表於2017-12-25
第一種:明文

有一些APP的登入註冊就直接明文,其實這是十分危險的,危險因素多的數不勝數。 譬如

  • 後臺被黑客攻破,使用者的所有資訊都會暴露出來
  • 網路劫持:劫持之後也可以直接看到我們的明文密碼
  • 如果攻擊者破解app,拿到了沙盒中的資料,也會造成資料洩漏

以前聽一個朋友講他們公司最開始的時候就是用明文進行登入註冊的,然後有一個大三的學生把他們公司的伺服器給攻破了。辛虧那位學生並沒有按什麼壞的心眼,只是把攻破的結果告訴了他們公司,然後他們公司的程式設計師一個兌一兩千塊錢給了那個學生,算是息事寧人了。由此可見,使用明文登入註冊是多麼危險。其實現在一般公司都是會對資料進行加密的,除非是那些外包公司做的外包專案,他們實在是懶得跟你加密,才回使用明文。

第二種:MD5加密

MD5是一個安全的雜湊演算法,輸入兩個不同的明文不會得到相同的輸出值,根據輸出值,不能得到原始的明文,即其過程不可逆;所以要解密MD5沒有現成的演算法,只能用窮舉法,把可能出現的明文,用MD5演算法雜湊之後,把得到的雜湊值和原始的資料形成一個一對一的對映表,通過比在表中比破解密碼的MD5演算法雜湊值,通過匹配從對映表中找出破解密碼所對應的原始明文。

MD5有一下四個特點:

  • 不可逆的
  • 數量是有限的,可以使用窮舉法破解,MD5破解就是根據這個
  • MD5演算法 不管是什麼語言得到的結果都是一樣的。
  • 字串,影象,視訊都可以使用MD5加密成32為字串

蘋果內部用C語言寫了MD5加密演算法,但是我們對只用用C語言來寫的話,會感到一點點的麻煩,所以,網上有很多的人都對MD5進行了一些簡單的封裝,我這裡就隨便摘抄一段

+(NSString *)MD5ForLower32Bate:(NSString *)str{
    const char* input = [str UTF8String];
    unsigned char result[CC_MD5_DIGEST_LENGTH];
    CC_MD5(input, (CC_LONG)strlen(input), result);
    
    NSMutableString *digest = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
    for (NSInteger i = 0; i < CC_MD5_DIGEST_LENGTH; i++) {
        [digest appendFormat:@"%02x", result[i]];
    }
    
    return digest;
}
複製程式碼

我來對上一段的程式碼進行簡單的分析啊。

  • const char* input = [str UTF8String];,進行UTF8的轉碼,把字串型別轉化為char型別,因為加密的底層是C語言寫的,我們要轉化為C語言能看懂的語言。

  • unsigned char result[CC_MD5_DIGEST_LENGTH];,設定一個接受字元陣列

  • CC_MD5(input, (CC_LONG)strlen(input), result);,extern unsigned char *CC_MD5(const void *data, CC_LONG len, unsigned char *md)官方封裝好的加密方法。把字串轉換成了32位的16進位制數列(這個過程不可逆轉) 儲存到了result這個空間中

8BBC7766-23C5-4352-8412-52501B14B8DB.png

加密結果:e10adc3949ba59abbe56e057f20f883e 然後把這個字串放到MD5解密網站上

F45FFEF6-A246-46B0-A937-7D1ADCA7EC97.png

所以,單純的MD5對我們的登入密碼進行加密也不是十分完善的。那些比較懶的使用者可能會輸入一個比較簡單的密碼,我們也要保護這部分使用者的密碼不會被輕易的破解。這時候我們就引入了下一個概念。

第三種:加鹽

普通的MD5加密,現在已經有軟體可以進行破解,所有我們想出來一種方法,使MD5這種加密更加複雜,更難被破解。這種方式就是加鹽(原始密碼 + 鹽) MD5 運算.保證密碼不被破解,就要保證鹽值足夠長/足夠鹹

什麼是加鹽值

為了加強MD5的安全性(本身是不可逆的),從而加入了新的演算法部分即加鹽值,加鹽值是隨機生成的一組字串,可以包括隨機的大小寫字母、數字、字元,位數可以根據要求而不一樣,使用不同的加鹽值產生的最終密文是不一樣的。

程式碼中如何使用加鹽值

由於使用加鹽值以後的密碼相當的安全,即便是你獲得了其中的salt和最終密文,破解也是一個耗費相當多時間的過程,可以說是破解單純MD5的好幾倍,那麼使用加鹽值以後的密文是如何產生的呢? 1).首先我們得到的是明文的hash值 2).進行計算獲取MD5明文hash值 3).隨機生成加鹽值並插入 4).MD5插入加鹽值得到的hash 5).得到最終的密文

我們就簡單的使用一下

82E362E1-CB8B-41E0-A487-AA41A05BF145.png

同樣的字串123456在加鹽以後就解密不出來了

C5B552CD-6BCE-4F1B-971E-64CCE0DCA581.png

當然鹽後臺傳給我們是最好的,使用後臺傳來的鹽(salt)時,登入註冊我們需要考慮一下邏輯

  • 在註冊時成功後,後臺給我們隨機的返回一個salt,並且後臺使用鹽(salt)md5加密
  • 登入的時候,我們用鹽(salt)加密
  • 當我們更換手機登入的時候,我們向註冊賬號傳送登入請求資訊,當登入賬號允許新的手機登入的時候,後臺給新的手機傳送以前的salt值(案例:我們跟換微信登入的時候,微信會給我們傳送一個驗證碼,我們輸入驗證碼的過程就是我們想後臺請求salt的過程)
第四種:HMAC加密

其實上面的思想都有一點HMAC加密的思想,現在國外HMAC加密用的十分廣泛了。

HMAC加密演算法是一種安全的基於加密hash函式和共享金鑰的訊息認證協議.它可以有效地防止資料在傳輸過程中被截獲和篡改,維護了資料的完整性、可靠性和安全性. HMAC加密演算法是一種基於金鑰的報文完整性的驗證方法,其安全性是建立在Hash加密演算法基礎上的。它要求通訊雙方共享金鑰、約定演算法、對報文進行Hash運算,形成固定長度的認證碼。通訊雙方通過認證碼的校驗來確定報文的合法性。HMAC加密演算法可以用來作加密、數字簽名、報文驗證等。

HMAC加密演算法的定義

HMAC加密演算法是一種執行“校驗和”的演算法,它通過對資料進行“求和”來檢查資料是否被更改了。在傳送資料以前,HMAC加密演算法對資料塊和雙方約定的公鑰進行“雜湊操作”,以生成稱為“摘要”的東西,附加在待傳送的資料塊中。當資料和摘要到達其目的地時,就使用HMAC加密演算法來生成另一個校驗和,如果兩個數字相匹配,那麼資料未被做任何篡改。否則,就意味著資料在傳輸或儲存過程中被某些居心叵測的人作了手腳。 程式碼如下:

+  (NSString *)HMacHashWithKey:(NSString *)key data:(NSString *)data{

    const char *cKey  = [key cStringUsingEncoding:NSASCIIStringEncoding];
    const char *cData = [data cStringUsingEncoding:NSASCIIStringEncoding];


    unsigned char cHMAC[CC_SHA256_DIGEST_LENGTH];

    //關鍵部分
    CCHmac(kCCHmacAlgSHA256, cKey, strlen(cKey), cData, strlen(cData), cHMAC);

    NSData *HMAC = [[NSData alloc] initWithBytes:cHMAC
    length:sizeof(cHMAC)];

    //將加密結果進行一次BASE64編碼。
    NSString *hash = [HMAC base64EncodedStringWithOptions:0];
    return hash;
}
複製程式碼

其中被加密的欄位data,我們可以設定一種特殊的生成方式。 加密的密匙key也可以和server端商定一致。

我們做了這些已經為保護使用者賬號安全做了很多了,但是,我們還有改進的機會。

我們知道,現在使用者經常連線公共Wi-Fi,而黑客可以通過這個公共Wi-Fi來獲取我們加密後的密碼以及key,這個時候我們還可以新增一層新的防護

第五種:時間戳密碼+HMAC

基本介紹

  • 動態密碼:相同的密碼明文+相同的加密演算法-->因為每次登陸時間都不同,所以每次計算出的結果也都不相同.可以充分保證密碼的安全性.

  • 伺服器會計算兩個時間值,當期時間和前一分鐘的時間(比如:第59S傳送的網路請求,一秒鐘後伺服器收到並作出響應,這時伺服器當前時間比客戶端傳送時間晚一分鐘,仍然能夠判斷準確的值)

補充介紹:token值

token 值: 登入令牌.利用 token 值來判斷使用者的登入狀態.類似於 MD5 加密之後的長字串.

使用者登入成功之後,在後端(伺服器端)會根據使用者資訊生成一個唯一的值.這個值就是 token 值.

基本使用:

  • 在伺服器端(資料庫)會儲存這個 token 值,以後利用這個 token 值來檢索對應的使用者資訊,並且判斷使用者的登入狀態.

  • 使用者登入成功之後,伺服器會將生成的 token 值返回給 客戶端,在客戶端也會儲存這個 token 值.(一般可以儲存在 cookie 中,也可以自己手動確定儲存位置(比如偏好設定.)).

  • 以後客戶端在傳送新的網路請求的時候,會預設自動附帶這個 token 值(作為一個引數傳遞給伺服器.).伺服器拿到客戶端傳遞的 token 值跟儲存在 資料庫中的 token 值做對比,以此來判斷使用者身份和登入狀態.

登入狀態判斷

  • 如果客戶端沒有這個 token 值,意味著沒有登入成功過,提示使用者登入.

  • 如果客戶端有 token 值,一般會認為登入成功.不需要使用者再次登入(輸入賬號和密碼資訊).

token 值有失效時間:

  • 一般的 app ,token值得失效時間都在 1 年以上. 特殊的 app :銀行類 app /支付類 app :token值失效時間 15 分鐘左右.
  • 一旦使用者資訊改變(密碼改變),會在伺服器生成新的 token 值,原來的 token值就會失效.需要再次輸入賬號和密碼,以得到生成的新的 token 值.

唯一性判斷: 每次登入,都會生成一個新的token值.原來的 token 值就會失效.利用時間來判斷登入的差異性.

相關文章