iOS逆向攻防之用戶密碼加密

在互聯網時代,用戶信息對於一個企業的重要性就好比血液,能夠說一個公司最核心,最重要的就是用戶的信息,用戶的信息所有都存在服務器中,並經過用戶的帳號關聯着,因此該帳號對應的密碼安全性很是重要!因此咱們今天來研究一下用戶密碼加密的問題,先來還原一下業務場景:算法

企業的產品必需要用戶註冊該企業的平臺帳號,
用戶在註冊的時候,會輸入帳號和密碼
做爲之後用戶在該平臺上全部操做的依據。
複製代碼

如今的需求就是儘量的保證該用戶帳號/密碼的安全。咱們來一步步的討論不一樣方案的可行性數據庫

1、嘗試各類加密方案~


把用戶真實的帳號密碼保存在服務器中可不可行呢?安全

互聯網初始階段,也確實這樣作過,把用戶的真實密碼保存在服務器中,可是很是不安全,也很是不可取。bash

若是用戶的真實密碼保存在服務器中,一旦服務器出了問題,好比數據庫密碼泄漏,那麼服務器中存的全部的用戶密碼都會泄漏。這對一個互聯網公司是致命的!因此如今都是隻有重置密碼功能,並不會有找回舊密碼的功能。由於服務器根本就沒存舊密碼~服務器

既然不能直接保存用戶真實密碼,那麼這時候Hash算法就派上用場了,由於Hash算法的特性,單向不可逆,能夠用來作識別,咱們能夠在用戶註冊帳號的時候把用戶密碼的Hash值保存到服務器,這樣用戶之後每次登錄,將用戶密碼的Hash值傳給服務器,和服務器中存的Hash進行對比,也能夠驗證用戶信息登錄。優化

代碼演示部分: 好比用戶密碼是’123456‘,用戶在註冊的時候,將密碼進行一次Hash算法,並打印網站

//
//  ViewController.m
//  PasswordTestProject
//  用戶密碼加密
//  Created by battleMage on 2019/10/9.
//  Copyright © 2019 battleMage. All rights reserved.
//

#import "ViewController.h"
#import "NSString+Hash.h"

@interface ViewController ()
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    //用戶登陸
    NSString * pwd = @"123456";
    pwd = pwd.md5String;
    NSLog(@"如今的密碼是:%@", pwd);
}

@end

複製代碼

Run運行一下,點擊屏幕,獲得打印臺的結果爲'e10adc3949ba59abbe56e057f20f883e'這麼一串128位的十六進制字符ui

2019-10-09 23:31:01.898337+0800 PasswordTestProject[10311:1544249] 如今的密碼是:e10adc3949ba59abbe56e057f20f883e

複製代碼

可是Hash有個特色,相同的數據運算獲得的Hash值是相同的,而且因爲Hash有散列碰撞現象,有一個專門的網站https://www.cmd5.com,是專門用來作Hash散列碰撞的,而後就獲得了原密碼~加密

www.cmd5.com網站截圖.png

這個時候你還認爲簡單的Hash還很安全嗎?spa

還有小夥伴們用過的,密碼加鹽後再Hash。 加鹽操做,顧名思義就是初始密碼拼接上一串奇怪的字符串,這個字符串能夠很長,從而保證加密的安全性。

下面咱們來加鹽進行代碼演示一下:

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    //用戶登陸
    NSString * pwd = @"123456";
    //y加鹽
    NSString * salt = @"abcde";
    pwd = [pwd stringByAppendingString:salt];
    pwd = pwd.md5String;
    NSLog(@"如今的密碼是:%@", pwd);
}

複製代碼

再次運行,點擊模擬器,打印結果以下,獲得一個Hash串 ‘600c849881fb596aacc5717f29f6081a’

2019-10-09 23:50:29.314117+0800 PasswordTestProject[10627:1563651] 如今的密碼是:600c849881fb596aacc5717f29f6081a

複製代碼

把這個結果粘貼到網站中,點擊查詢,傻眼了吧~ 直接被查出來~,截圖以下:

加鹽以後,再次查詢.png

先來看看這個網站,正如簡短的網站介紹說的,專門針對md五、sha1等全球通用公開的加密算法進行反向查詢,經過窮舉字符組合的方式,以key-value的形式(例如key爲123456,value爲123456的Hash值e10adc3949ba59abbe56e057f20f883e)建立了明文密文對應查詢數據庫,建立的記錄約90萬億條,佔用硬盤超過500TB~

www.cmd5.com選項.png

仔細點一下這個不起眼的網站中間的選項部分,你會發現這個網站可不只僅像它本來的UI界面這麼簡單,它還能夠選擇屢次Hash嵌套,還有你能想到的加鹽,只要你能拿到鹽,那麼破解的難度就會大幅度下降,密碼破解中的說法,若是你須要10年才能窮舉出來的破解,若是如今1個小時就能作到,就算破解成功!因此說單純的加鹽還不夠安全!

可能小夥伴在質疑,把鹽弄得複雜一點,不就行了麼~

固然不行!加鹽也存在隱患,鹽可能會泄漏;就算生成複雜鹽,若是泄露了規則,也不夠安全。

下面就來提供一下這個問題的解決辦法:

2、解決辦法:HMAC加密方案


一、HMAC加密方案介紹

HMAC加密方案是使用一個密鑰加密,而且作了兩次散列,在實際開發中,密鑰來自服務器.通常是根據當前服務器時間相關的隨機值

複製代碼

代碼演示部分:

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    
    //用戶登陸
    NSString * pwd = @"123456";
    
//    //y加鹽
//    NSString * salt = @"abcde";
//    pwd = [pwd stringByAppendingString:salt];
//    pwd = pwd.md5String;
    
    pwd = [pwd hmacMD5StringWithKey:@"BattleMage"];
    
    NSLog(@"如今的密碼是:%@", pwd);
}


複製代碼

運行點擊,打印結果

2019-10-10 00:15:31.523575+0800 PasswordTestProject[10979:1585298] 如今的密碼是:0a763947ac5811b8c8222a1458b1d28f


複製代碼

HMAC加密後,cmd5網站截圖.png

再去網站上找,就找不到了,並且根本沒有HMAC選項,被告知須要等一段時間,是查不出來的,想都不用想~

那麼看下圖HMAC業務分析流程:

HMAC加密流程圖.png

那麼問題又來了,在另外一臺設備上是否是就沒有這個key了?因此真正的業務流程應該是這樣子的

一、登陸時,用戶輸入帳號account
二、客戶端經過帳號在本地鑰匙串中查詢是否有保存的key
三、若是本地沒有,就向服務器獲取
四、服務器把key發給客戶端,客戶端用HMAC加密,發送給服務器保存

複製代碼

3、HMAC加密方案最終優化

經過HMAC加密後,密碼確實不容易破解了,可是你們能發現一個問題,不管你用什麼樣的方式加密,你發給服務器驗證的永遠都是加密後的一串數字,若是黑客經過https攔截,拿到這一串數字,照樣能夠拿到登陸權限!

那麼咱們如何防禦呢?

只須要加一點點處理:在HMAC加密以前,向服務器獲取當前的時間戳(201910100105 這個時間戳精確到分鐘),而後將HMAC獲得的Hash值再拼接上當前的時間戳,再進行Hash,獲得一個最終的Hash值字符串發送給服務器,服務器在接收到最終的字符串後,使用一樣的算法,拿當前的時間戳進行驗證,若是當前分鐘時間戳不知足,就取上一分鐘的時間戳,兩次若是校驗失敗,那麼驗證失敗。這樣,隔兩分鐘,客戶端發給服務器的字符串就不同,黑客就算拿到這個字符串了,若是在2分鐘內不能碰撞出密碼,那麼就一直登陸失敗,就算碰撞出來密碼,也只是破解了一個用戶的帳號,每一個帳號都是獨立的,因此強行破解收益超級低!這樣就作到了相對安全! 心疼黑客一下~

最後整理一下優化後的HMAC加密流程圖:

HMAC加密方案優化.png
相關文章
相關標籤/搜索