天天看點

【IoT】加密與安全:動态令牌 OTP、HOTP、TOTP 原了解析

1、OTP、HOTP、TOTP 簡介

1.1、OTP

One-Time Password 簡寫,表示一次性密碼。

1.2、HOTP

HMAC-based One-Time Password 簡寫,表示基于 HMAC 算法加密的一次性密碼。是事件同步,通過某一特定的事件次序及相同的種子值作為輸入,通過 HASH 算法運算出一緻的密碼。

1.3、TOTP

Time-based One-Time Password 簡寫,表示基于時間戳算法的一次性密碼。 

時間同步,基于用戶端的動态密碼和動态密碼驗證伺服器的時間比對,一般每 60 秒産生一個新密碼,要求用戶端和伺服器能夠十分精确的保持正确的時鐘,用戶端和服務端基于時間計算的動态密碼才能一緻。  

2、TOTP 弱點和漏洞編輯

TOTP 代碼可以像密碼一樣被釣魚,但它們需要網絡釣魚者實時代理憑證,而不是及時收集它們,不限制登入嘗試的實作容易受到強制執行代碼的攻擊。

竊取共享密鑰的攻擊者可以随意生成新的有效 TOTP 代碼。如果攻擊者破壞了大型身份驗證資料庫,這可能是一個特殊問題。

由于 TOTP 裝置的電池電量不足,時鐘可以解除同步,并且由于軟體版本在使用者可能丢失或被盜的手機上,是以所有實際實施都有繞過保護的方法(例如:列印的代碼,電子郵件 - 重置等),這可能給大型使用者群帶來相當大的支援負擔,并且還為欺詐使用者提供額外的利用向量。

TOTP 代碼的有效期超過它們在螢幕上顯示的時間(通常是兩倍或更多倍)。這是一個讓步,認證和認證方的時鐘可以大幅度扭曲。

所有一次性基于密碼的身份驗證方案(包括 TOTP 和 HOTP 等)仍然容易受到會話劫持,即在使用者登入後占用使用者的會話。

3、原理介紹

3.1、OTP 基本原理

計算 OTP 串的公式:

OTP(K,C) = Truncate(HMAC-SHA-1(K,C))

其中,

K 表示秘鑰串;

C 是一個數字,表示随機數;

HMAC-SHA-1 表示使用 SHA-1 做 HMAC;

Truncate 是一個函數,就是怎麼截取加密後的串,并取加密後串的哪些字段組成一個數字。

對 HMAC-SHA-1 方式加密來說,Truncate 實作如下:

HMAC-SHA-1 加密後的長度得到一個 20 位元組的密串;

取這個 20 位元組的密串的最後一個位元組,取這位元組的低 4 位,作為截取加密串的下标偏移量;

按照下标偏移量開始,擷取4個位元組,按照大端方式組成一個整數;

截取這個整數的後 6 位或者 8 位轉成字元串傳回。

示例:

Java 代碼實作:

public static String generateOTP(String K,
                                     String C,
                                     String returnDigits,
                                     String crypto){
       int codeDigits = Integer.decode(returnDigits).intValue();
       String result = null;
 
       // K是密碼
       // C是産生的随機數
       // crypto是加密算法 HMAC-SHA-1
       byte[] hash = hmac_sha(crypto, K, C);
       // hash為20位元組的字元串
 
       // put selected bytes into result int
       // 擷取hash最後一個位元組的低4位,作為選擇結果的開始下标偏移
       int offset = hash[hash.length - 1] & 0xf;
 
       // 擷取4個位元組組成一個整數,其中第一個位元組最高位為符号位,不擷取,使用0x7f
       int binary =
               ((hash[offset] & 0x7f) << 24) |
               ((hash[offset + 1] & 0xff) << 16) |
               ((hash[offset + 2] & 0xff) << 8) |
               (hash[offset + 3] & 0xff);
       // 擷取這個整數的後6位(可以根據需要取後8位)
       int otp = binary % 1000000;
       // 将數字轉成字元串,不夠6位前面補0
       result = Integer.toString(otp);
       while (result.length() < codeDigits) {
           result = "0" + result;
       }
       return result;
   }
           

傳回的結果就是看到一個數字的動态密碼。

3.2、HOTP 基本原理

知道了 OTP 的基本原理,HOTP 隻是将其中的參數 C 變成了随機數。

HOTP(K,C) = Truncate(HMAC-SHA-1(K,C))

HOTP: 

Generates the OTP for the given count

C 作為一個參數,擷取動态密碼。

示例:

HOTP 的 python 代碼片段:

class HOTP(OTP):
    def at(self, count):
        """
        Generates the OTP for the given count
        @param [Integer] count counter
        @returns [Integer] OTP
        """
        return self.generate_otp(count)
           

一般規定 HOTP 的散列函數使用 SHA2,即:基于 SHA-256 or SHA-512 [SHA2] 的散列函數做事件同步驗證;

3.3、TOTP 基本原理

TOTP 隻是将其中的參數 C 變成了由時間戳産生的數字。

TOTP(K,C) = HOTP(K,C) = Truncate(HMAC-SHA-1(K,C))
           

不同點是 TOTP 中的 C 是時間戳計算得出。

C = (T - T0) / X;
           

T 表示目前 Unix 時間戳:

【IoT】加密與安全:動态令牌 OTP、HOTP、TOTP 原了解析

T0 一般取值為 0,也就是 1970 年 1 月 1 日。

是以上式可以簡化為:

C = T / X;
           

X 表示時間步數,也就是說多長時間産生一個動态密碼,這個時間間隔就是時間步數 X,系統預設是 30 秒;

例如:

T0 = 0;

X = 30;
           

簡化為:C = T / 30

1)T = 30 ~ 59

C = 1;

表示 30 ~ 59 這  30  秒内的動态密碼一緻。
           

2)T = 60 ~ 89

C = 2; 

表示 30 ~ 59 這 30 秒内的動态密碼一緻。
           

不同廠家使用的時間步數不同:

阿裡巴巴的身份寶使用的時間步數是 60 秒;

甯盾令牌使用的時間步數是 60 秒;

Google 的身份驗證器的時間步數是 30 秒;

騰訊的 Token 時間步數是 60 秒;
           

TOTP 的 python 代碼片段:

class TOTP(OTP):
    def __init__(self, *args, **kwargs):
        """
        @option options [Integer] interval (30) the time interval in seconds
            for OTP This defaults to 30 which is standard.
        """
        self.interval = kwargs.pop('interval', 30)
        super(TOTP, self).__init__(*args, **kwargs)
    def now(self):
        """
        Generate the current time OTP
        @return [Integer] the OTP as an integer
        """
        return self.generate_otp(self.timecode(datetime.datetime.now()))
 
    def timecode(self, for_time):
        i = time.mktime(for_time.timetuple())
        return int(i / self.interval)
           

self.interval 是時間步數 X;

datetime.datetime.now() 為目前的 Unix 時間戳;

timecode 表示 (T - T0) / X,即擷取擷取動态密碼計算的随機數。

TOTP 的實作可以使用 HMAC-SHA-256 或者 HMAC-SHA-512 散列函數;

TOTP 的要求:

用戶端和伺服器必須能夠彼此知道或者推算出對方的 Unix Time;

用戶端和伺服器端必須共享一個密鑰;

算法必須使用 HOTP 作為其關鍵實作環節;

用戶端和伺服器端必須使用相同的步長 X;

每一個用戶端必須擁有不同的密鑰;

密鑰的生成必須足夠随機;

密鑰必須儲存在防篡改的裝置上,而且不能在不安全的情況下被通路或使用;

對該算法中 T 的實作必須大于 int32,因為它在 2038 年将超出上限;

T0 和 X 的協商必須在之前的步驟中就已經做好了。

4、參考

4.1、python 的 otp 實作

https://pypi.python.org/pypi/pyotp

https://github.com/pyotp/pyotp
           

4.2、基于 pyotp 的簡單應用

>>> import base64
>>> base64.b32encode('This is my secret key')
'KRUGS4ZANFZSA3LZEBZWKY3SMV2CA23FPE======'
>>> secretKey = base64.b32encode('This is my secret key')
>>> import pyotp
>>> totp = pyotp.TOTP(secretKey)
>>> totp.now()
423779
           

簡單說明:

加載base64的子產品,将我的秘鑰做一下base32的加密,加載pyotp子產品,otp使用base32加密後的秘鑰傳作為種子,生成随機數字驗證的。

可以使用pyotp和expect一起實作基于google authenticator的自動登入(免去每次雙認證,輸入密碼和動态密碼)。

4.3、pyotp 的 TOTP 的使用說明

totp = pyotp.TOTP('base32secret3232')
totp.now() # => 492039
 
# OTP verified for current time
totp.verify(492039) # => True
time.sleep(30)
totp.verify(492039) # => False
           

4.4、pyotp 的 HOTP 的使用說明

hotp = pyotp.HOTP('base32secret3232')
hotp.at(0) # => 260182
hotp.at(1) # => 55283
hotp.at(1401) # => 316439
 
# OTP verified with a counter
hotp.verify(316439, 1401) # => True
hotp.verify(316439, 1402) # => False
           

4.5、使用場景

伺服器登入動态密碼驗證(如阿裡雲ECS登入,騰訊機房伺服器登入等);
公司VPN登入雙因素驗證;
網絡接入radius動态密碼;
銀行轉賬動态密碼;
網銀、網絡遊戲的實體動态密碼牌;
等動态密碼驗證的應用場景。
           

4.6、市面上基于 HOTP 的産品

甯盾令牌
阿裡巴巴的身份寶 
Google 的身份驗證器(google-authenticator)
           

4.7、Google 基于 TOTP 的開源實作

https://github.com/google/google-authenticator

RFC6238中TOTP基于java代碼的實作。
           

4.8、golang 的一個 otp 實作

https://github.com/gitchs/gootp
           

4.9、RFC 參考

RFC 4226 One-Time Password and HMAC-based One-Time Password.

RFC 6238 Time-based One-Time Password.

RFC 2104 HMAC Keyed-Hashing for Message Authentication.
           

refer:

https://www.cnblogs.com/voipman/p/6216328.html

http://www.bubuko.com/infodetail-1884978.html