基於時間的一次密碼TOTP

相關算法


  • HOTP(HMAC-based One-Time Password,基於HMAC的一次性口令)
  • TOTP(Time-Based One-Time Password,基於時間的一次性口令)
  • HMAC(Hash-based message authentication code,基於散列函數的消息認證碼算法)

HMAC


  • 算法公式 HMAC(K, m) = H((K’ xor opad) || H ((K’ xor ipad) || m))
    • H 散列函數
    • K 共享密鑰
    • K’ 通過K(密鑰)計算所得(當散列函數是SHA-1, MD5, RIPEMD-128/160,K’大小爲64字節不足後面填充0)
    • xor 異或
    • opad 外層HASH填充值,0x5c5c5c….長度與K’相當
    • ipad 內層HASH填充值,0x363636….長度與K’相當
    • m 一個消息輸入
    • || 表示連接
  • 簡化理解 sha1(opad.sha1(ipad.m))
  • 計算結果 根據所選散列函數變動,sha1爲例會得到一個20字節40位的16進制
  • PHP自帶 hash_hmac ( string algo,string data , string key[,bool raw_output = false ] )
  • 代碼示例

function my_hash($algo, $key, $msg) {
    $blocksize = '64';
    if (strlen($key) > $blocksize)
        $key = hash($algo, $key);
    if (strlen($key) < $blocksize)
        $key = str_pad($key, $blocksize, chr(0x00));
    $o_pad = str_repeat(chr(0x5c), $blocksize) ^ $key;
    $i_pad = str_repeat(chr(0x36), $blocksize) ^ $key;
    return hash($algo, $o_pad. hash($algo, $i_pad. $msg, true));
}

HOTP


  • 算法公式 HOTP(K,C) = (Truncate(HMAC(K,C)) & 0x7FFFFFFF) mod 10d
    • C 計數器,對應HMAC中的m
    • & 與
    • T HMAC sha1後得到的結果太長,經過Truncate處理後我會得到一個32bit的無附號整數
    • mod 取餘,與10的d次方模運算得到d位的一個數字口令
    • Truncate代碼示例

   function truncate($hash) {

        $offset = ord($hash[19]) & 0xf;
        return (
            ((ord($hash[$offset+0]) & 0x7f) << 24 ) |
            ((ord($hash[$offset+1]) & 0xff) << 16 ) |
            ((ord($hash[$offset+2]) & 0xff) << 8 ) |
            (ord($hash[$offset+3]) & 0xff)
        ) % pow('10', '6');

    }

TOTP


  • 算法公式 TOTP = HOTP(K, TC)
    • TC floor((unixtime(now) − unixtime(T0)) / TS)
    • T0 開始計算的時間步長
    • TS 時間步長,默認30出於安全與考慮不宜過大
  • 代碼片斷
    function totp($secretKey, $f2, $len=6) {

        $hash 	 = hash_hmac ('sha1', $data, $key, true);
        return str_pad(self::truncateHash($hash), $len, '0', STR_PAD_LEFT);

    }

關鍵點


  • 密鑰共享
  • 時間戳/計數器同步與混淆

相關資料


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章