安全握手的陷阱(security handshake pitfall),這些發生在握手階段,完成握手有兩種方案,即單向認證(one-way authentication)和雙向認證(mutual authentication)。
1.單向認證
單向認證的思想很簡單。如果有兩個使用者a和b進行身份認證,其中b要對a進行身份認證,但a不需要認證b。實現這種型別的認證的方法有多中,比較知名的有:只登陸(login only)、共享金鑰(shared secret)和單向公鑰(one-way public key)。
1.1 只登陸認證
在這種簡單的方法中:(1)使用者a以明文的形式把它的使用者名稱和和密碼傳送給另乙個使用者b。(2)b驗證該使用者名稱和密碼,如果該使用者名稱和密碼正確,就可以在a和b之間進行通訊,不需要用其他的加密形式加密或完整性檢驗。
這種方法實現起來很簡單,也很好理解。但是,不是很有效,需要更好的認證機制,其中a把口令的訊息摘要,而不是初始口令傳送給b,口令加密是另一種方法。
1.2 共享金鑰的方法
這裡假定使用者a和b在實際的通訊開始之前,已經協商好了乙個共享對稱金鑰kab。因此,對這種方法取名為共享金鑰。該方法的工作如下所示:
1.a傳送其使用者名稱和口令給b。
2.b建立乙個隨機挑戰r,並將它傳送給a。
3.a用a與b之間的共享金鑰kab加密該隨機挑戰r,並把已加密的r傳送給b。b也用相同的共享的金鑰kab加密初始隨機挑戰r。如果這個已加密的隨機挑戰與a傳送的匹配,那麼b就認為a是合法的,即a通過了b的認證。
但是,這裡存在乙個問題,這是乙個單向認證,即b認證a,但a不能認證b,因此攻擊者c可以傳送乙個舊的隨機挑戰r給a。在a用kab加密r,並把它傳送回c後,只需忽略它即可。於是,a錯誤地認證c就是b。也就是說,c可以裝扮成b,並與a進行通訊。
這種協議有乙個變體,b不是把隨機挑戰r傳送給a,而是用共享金鑰kab將它加密後,把這個已加密的隨機挑戰傳送給a。a把已加密的隨機挑戰解密,從而獲得初始的未加密的隨機挑戰r,並把它傳送回b,以認證自己。
基本的共享金鑰認證方案還有另一種變體,它只要求乙個從a到b的訊息,不需要隨機挑戰。a只需要共享對稱金鑰kab加密當前的時間戳,並把這個已加密的時間戳傳送給b。b將它解密,如果是所期望的,則b通過a的認證。為此,a和b需要預先同步化它們的時間戳。這種協議有一定的優點,該協議很容易實現,以替代傳送明文口令,a往b傳送的不是使用者名稱和明文口令了,而是使用者名稱和已加密的當前時間戳。
1.3 單向公鑰的方法
前面的協議是基於共享秘密,即共享對稱金鑰kab,如果攻擊者能讀取b的資料庫,那麼它就可以訪問該金鑰kab,那麼它就非常容易地偽裝為a來與b進行通訊。如果用公鈅來替換共享金鑰,那麼就可以避免這些。這裡的思想很簡單:(1)a傳送其使用者名稱給b;(2)b傳送隨機挑戰r給a;(3)a用它的私鑰加密該隨機挑戰r,並把它傳送給b,b使用a的公鑰解密這個加密的隨機挑戰,並把它與初始隨機挑戰r進行匹配。
也可以稍作修改,如下所示:
1.a傳送其使用者名稱給b;
2.b生成乙個隨機挑戰r,用a的公鑰加密該隨機挑戰。b把已加密的隨機挑戰發給a;
3.a用它的私鑰將已加密的隨機挑戰解密,並把它傳送給b。b將它與初始的隨機挑戰r匹配。
上述方案都存在一些問題,需要強行規定簽名金鑰必須與加密金鑰不同,即,每個使用者必須有兩個公鑰-私鑰對,一對使用者簽名和驗證,另一對用於加密和解密。
2.雙向認證
在雙向認證中,a和b相互認證對方,因此這裡為雙向認證。該方法也可以以不同的方式來實現:共享秘密和基於時間戳的方法。
2.1 共享秘密的方法
該方法假設a和b具有乙個共享對稱金鑰kab,其工作步驟如下:
1.a傳送其使用者名稱給b;
2.b傳送隨機挑戰r1給a;
3.a用kab加密隨機挑戰,並把它傳送給b;
4.a傳送另乙個不同的隨機挑戰r2給b;
5.b用kab加密r2,並把它傳送給a。
此時,b像以前那樣認證a,a也要認證b,因此這是雙向認證,如下圖所示:
可以看到,這裡需要交換很多訊息,使得其方法效率低。可以減少到只有3條訊息,把更多的訊息放置在這3條訊息中。修改的方法如下所述:
1.a傳送使用者名稱和隨機挑戰r2給b;
2.b用共享對稱金鑰加密kab加密r2,生成乙個新的隨機挑戰r1,並把這兩個隨機挑戰發給a;
3.a驗證r2,用共享對稱金鑰kab加密r1,並把它傳送給b。b驗證r1。
該過程如下圖所示:
這種方法把訊息數量減少為3了,但是,它容易受到反射攻擊法攻擊。假設c想偽裝為a與b通訊,首先,攻擊者c開始如下步驟:
1.c往b傳送乙個含有a的使用者名稱和隨機挑戰r2的訊息;
2.b用共享對稱金鑰kab加密r2,生成乙個新的隨機挑戰r1,並把這兩個隨機挑戰傳送給c,此時b以為以為是在傳送給a。
攻擊者不能用kab加密r1。但是c讓b加密了r2。現在,攻擊者c開啟與b的另一會話,該會話與第乙個不同,第乙個會話仍是活動的,此時,攻擊者執行如下步驟:
1.c傳送乙個含有a的使用者名稱和隨機挑戰r1;
2.b用共享對稱金鑰kab加密r1,生成乙個新的隨機挑戰r3,並把這兩個隨機挑戰傳送給c,b以為他是傳送給a了。
然後,c可以回到第乙個會話,由於第乙個會話,c有了用kab加密的r1,c把r1傳送給b,就完成了驗證。
要解決這種反射攻擊,一種思想是使用不同的金鑰(假如kab和kba)。當a要加密傳送給b的內容時使用kab,當b要加密傳送給a的內容時使用kba。這樣,b就不能用kab來加密r1。這就意味著c不能像反射攻擊那樣在隨後誤用它了。
2.2 公鑰的方法
雙向認證也可以使用公鑰技術來完成。如果a和b知道了對方的公鑰,要完成雙向認證過程需要3個訊息,如下所示:
1.a把它的使用者名稱和用b的公鑰加密的隨機挑戰r2傳送給b;
2.b用它的私鑰把隨機挑戰r2解密。b建立乙個新的隨機挑戰r1,並用a的公鑰加密,b把這兩個隨機挑戰(已解密的r2和已加密的r1)傳送給a;
3.a用它的私鑰把隨機挑戰r1解密,並把它傳送給b,b驗證r1。
同樣,這種方法有乙個變體,如下所示:
1.a傳送它的使用者名稱和r2給b;
2.b用它的私鑰加密r2,並把它和r1傳送給a;
3.a為r1簽名後返回給b。
2.3 基於時間戳的方法
通過時間戳,而不是像隨機挑戰之類的隨機數,可以把雙向認證的過程減少為只有兩步。其工作過程如下所示:
1.a把它的使用者名稱和用共享金鑰kab加密後的當前時間戳傳送給b;
2.b通過用kab把上面的資料解密來獲得時間戳,並把該時間戳加1。b用kba將這個結果加密,並把它與它的使用者名稱傳送給a。
思維的陷阱
最近在做介面測試的時候遇到乙個不算太大的問題,但卻值得深思,先說說問題的背景,還有我一步步修復這個問題的過程。大家都知道,當應用程式對資料庫進行寫操作的同時往往都會記錄下最後一次寫操作的時間,有時候我們需要對這個時間進行檢查,既檢查我執行了寫操作以後,我期望的時間欄位被更新為當前時間。好像很簡單嘛,...
指標的陷阱
首先在前面我們就講解了指標的基本的一些基本的概念以及一些指標相關的定義,這篇我們就來講解講解一下指標中的一些陷進。指標其實不難理解,難理解是指標指向的記憶體個一些指標的sizeof 的運算。陷進一 指標陣列和陣列指標 例如下面的 include include int main 我們進行如下兩個操作...
C STL VC fread函式的陷阱
如果想實現從某個檔案中一次次n個位元組般讀出來,那建議不要用 read fread buff,n,1,data file 因為就算當檔案的位元組數比n大,但這時strlen buff 絕不是n個位元組大小!也不是read個位元組大小!查幫助文件,可知,read是指成功讀入的單元塊數,這裡對應的就是,...