原文連接:https://blog.csdn.net/LVXIANGAN/article/details/73775969java
原理jquery
動態密碼的密碼其實不是隨機的,而是由規律的。當下動態密碼分爲兩類,時間性和事件性。何爲時間性動態密碼?該類令牌產出動態密碼是以時間爲參數的,而事件性通常以使用次數爲參數的。咱們以時間性動態爲主要說明對象。整個驗證的過程以下:android
1.動態密碼令牌產生動態密碼 以時間和種子爲參數,進行迭代,得出動態密碼,這裏的時間通常是秒數。每一個時間性動態密碼令牌中會內置一個時鐘芯片。git
2.服務器校驗動態密碼。 服務器讀取系統時間加上種子,以相同的迭代方法得出動態密碼,而後雙方進行比對。算法
講到這邊,可能有所懷疑難道令牌的時間和服務器的時間必定會一致嗎?個人答案確定是不一致的。那怎麼能檢驗的過去呢?原來很簡單,服務器校驗是是在一個時間區間裏校驗的,好比如今是12:00,服務器會生成11:55-12:05中全部的動態密碼,而後和令牌產生的動態密碼比對,這樣不就解決了時間不一致的問題了。另外服務器會把令牌和服務器相差的時間記錄下來,下次檢驗的會先把這個偏移值記錄下來,以減小動態密碼迭代次數,這樣就完成了另一個比較重要的功能,偏移值自動調整。數組
動態口令,又叫動態令牌、動態密碼。它的主要原理是: 用戶登陸前,依據用戶私人身份信息,並引入隨機數產生隨機變化的口令,使每次登陸過程當中傳送的口令信息都不一樣,以提升登陸過程當中用戶身份認證的安全性。安全
銀行一般提供給用戶兩種動態口令: 一種是固定數量的動態口令,最多見的就是刮刮卡。用戶每次根據銀行提示,刮開卡上相應區域的塗層,便可得到一個口令。刮刮卡成本低廉,使用方法簡單,所以不少銀行採用這種方法,如工商銀行; 另外一種是硬件形式的動態口令,即電子令牌,它採用專用硬件,每次能夠用自帶的密碼生成芯片獲得一個當前可用的一次性動態密碼,交通銀行等就採用這種方式。通常來說,每一個客戶端的電子令牌都有一個惟一的密鑰,該密鑰同時存放在服務器端,每次認證時令牌與服務器分別根據一樣的密鑰,一樣的隨機數和一樣的算法計算出認證時的動態口令,從而確保口令的一致性和認證的成功。因每次認證時,隨機數的參數不一樣,因此每次產生的動態口令也不一樣。每次計算時參數的隨機性保證了每次口令不可預測,以保證系統安全。服務器
這些隨機數是怎樣產生的呢?動態口令隨機數分爲如下幾類。網絡
1. 口令爲一個單向的先後相關的序列,系統只記錄第N個口令。用戶用第N—1個口令登陸時,系統用單向算法算出第N個口令與本身保存的第N個口令匹配,以判斷用戶的合法性。因爲N是有限的,用戶登陸N次後必須從新初始化口令序列。數據結構
2. 時間同步: 以用戶登陸時間做爲隨機因素。這種方式對雙方的時間準確度要求較高,通常採起以分鐘爲時間單位的折中辦法。在這種動態口令中,對時間偏差的容忍可達±1分鐘。
3. 事件同步: 經過某一特定的事件次序及相同的種子值做爲輸入,使用相同的算法運算出一致的密碼,其運算機理決定了其整個工做流程同時鍾無關,不受時鐘的影響。它節省了用戶每次輸入挑戰信息的麻煩,但當用戶的挑戰序列與服務器產生誤差後,須要從新同步。
4. 挑戰/應答: 也叫異步認證方式。它比時間/事件同步方式操做相對煩瑣,實現相對複雜,通常用於對安全性要求更高的場合,好比登陸網上銀行等,須要附加認證的情形。當用戶須要訪問系統時,遠程認證服務器根據用戶的電子令牌資料產生一個隨機的數字串,即「挑戰碼」,用戶將該數字串輸入到電子令牌中。電子令牌利用內置的種子密鑰和算法計算出相應的應答數(一般也是一個數字串)。
5. 用戶將該應答數輸入系統。 系統根據所保存的該用戶相應電子令牌信息(種子密鑰和算法)計算出應答數,並與用戶輸入的應答數進行比較。若是二者相同,則認證經過。因爲每一個電子令牌的種子密鑰不一樣,所以不一樣用戶的電子令牌對一樣的挑戰數計算出應答數也並不相同。只有用戶持有指定的電子令牌才能計算出正確的應答數以經過系統認證。從而能夠保證該用戶是持有指定電子令牌的合法用戶。
因爲口令每次都變化,即便獲得密碼也沒用,並且這種動態口令由專用算法生成,隨機性高,不太容易被破解。傳統的木馬程序即便竊取到用戶我的信息,拿去登陸銀行網頁,也已通過期。所以,動態口令極大地提升了用戶身份認證的安全性。
動態口令(OTP,One-Time Password)又稱一次性密碼,是使用密碼技術實現的在客戶端和服務器之間經過共享祕密的一種認證技術,是一種強認證技術,是加強目前靜態口令認證的一種很是方便技術手段,是一種重要的雙因素認證技術,動態口令認證技術包括客戶端用於生成口令產生器的,動態令牌,是一個硬件設備,和用於管理令牌及口令認證的後臺動態口令認證系統組成。
1、OTP歷史溯源
動態口令(OTP)有一個同名確不一樣翻譯的前輩,一次性密碼(OTP, One-Time Pad),也叫密電本,是一種應用於軍事領域的諜報技術,即對通訊信息使用預先約定的一次性密電本進行加密和解密,使用後的密電本部分丟棄再也不使用,可以作到一次一密。若是看過一些國內的諜戰電視劇可能會對在二戰時期,日本轟炸重慶中的一個號稱「獨臂大盜」的日本間諜有印象的話,他同日軍通電使用的就是一次性密碼技術,使用諾貝爾獲獎的小說《The Good Earth》進行諜報編碼,最後是被稱爲美國密碼之父的赫伯特·亞德利破獲。而目前在安全強認證領域使用的OTP動態密碼技術,源於最先由RSA公司於1986年開發的RSA SecureID產品,動態密碼並非一次性密碼技術,而是動態一次性口令技術。目前,國際上動態口令OTP有2大主流算法,一個是RSA SecurID ,一個是OATH組織的OTP算法。若是在國內來講的話,另外一個是國密的OTP密碼算法。RSA SecurID使用AES對稱算法,OATH使用HMAC算法,國密算法使用的國密SM1(對稱)和SM3(HASH)算法。
2、OTP認證原理與同步方法
動態口令的基本認證原理是在認證雙方共享密鑰,也稱種子密鑰,並使用的同一個種子密鑰對某一個事件計數、或時間值、或者是異步挑戰數進行密碼算法計算,使用的算法有對稱算法、HASH、HMAC,以後比較計算值是否一致進行認證。能夠作到一次一個動態口令,使用後做廢,口令長度一般爲6-8個數字,使用方便,與一般的靜態口令認證方式相似,使用方便與系統集成好,所以OTP動態口令技術的應用很是廣泛,能夠應用於多種系統渠道使用,如:Web應用、手機應用、電話應用、ATM自助終端等。
動態口令的同步機制有3種,即時間型、事件型和挑戰與應答型,目前應用最多的是時間型動態口令,挑戰與應答型動態口令的應用也逐漸增多,而且動態口令逐漸變爲多種同步類型複合的機制發展,如時間+挑戰與應答型。
3、OTP與經常使用認證技術比較
目前在信息系統中使用的加強型認證技術包括:
1 USBKey: 申請PKI證書。
2 動態口令卡:打印好的密碼刮刮卡。
3 動態短信:使用電信通道下發口令。
4 IC卡/SIM卡:內置與用戶身份相關的信息。
5 生物特徵:採用獨一無二的生物特徵來驗證身份,如指紋。
6 動態令牌:動態口令生成器和認證系統。
不一樣方案比較以下:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
由上面的比較能夠很是直觀的看出,動態口令認證技術有着必定優點。
4、動態口令認證技術不足
動態口令認證技術沒有第3方權威機構認證,若是業務應用系統安全策略不完善的狀況下,可能會受到中間人攻擊。如某某銀行使用時間型動態令牌受到網絡釣魚攻擊。建議在應用中完善安全使用策略,劃清口令使用權限,增強交易系統流程控制,用以提升系統安全性。
附:OATH算法Java源代碼:http://download.csdn.net/detail/goldboar/3932212
銀行的動態口令令牌是什麼原理?
有網銀的少年們通常都收到過銀行給的這樣一個令牌,俗稱動態口令,在支付的時候輸入本身的密碼和動態口令上的動態密碼,就能完成驗證,銀行就相信你不是壞人了,今天咱們來簡述一下這個動態口令令牌是個什麼原理。
PS:本篇閱讀可能須要讀者有一些密碼學基礎,預警一下。
RSA SecurID SID700
如圖的RSA SecurID SID700是當前市面上流行使用的動態口令令牌,在筆者準備資料的過程當中發現國內描寫動態口令的野生博客有很多謬誤,其中大可能是對銀行這一套認證機制結構的不瞭解,因此首先要強調的是:
在大衆用戶手中的動態口令令牌,並不使用任何對稱或者非對稱加密的算法,在整個銀行的認證體系中,動態口令令牌只是一個一次性口令的產生器,在其中運行的主要計算僅包括時間因子的計算和散列值的計算。
動態口令算法又叫一次性口令算法,英文寫做OTP(One-Time Password Algorithm),動態口令令牌使用的算法是OTP中的一類,TOTP(Time-Based One-Time Password Algorithm) — 時間同步型動態口令。
時間同步型動態口令產生口令的時候和時間有關係,咱們能夠經過其工做的原理圖來看一下:
圖示給出了動態口令的工做原理,突出了整個認證機制中的動態口令部分,咱們能夠清楚看到在最左邊和最右邊有徹底相同的兩個流程,這裏分別表明了用戶的令牌卡和銀行服務器的驗證機器作的工做。本文的重點就在這兩個徹底相同的流程上。
在用戶從銀行手中拿到動態口令令牌卡的時候,在令牌卡的內部已經存儲了一份種子文件(即圖中鑰匙所表明的seed),這份種子文件在銀行的服務器裏保存的徹底同樣的一份,因此對於動態口令令牌來講,這種方式是share secret的。另外在令牌硬件上的設置中,假使有人打開了這個令牌卡,種子文件將會從令牌卡的內存上擦除(待考證)。
令牌卡中有了種子文件,並實現了TOTP算法,在預先設置的間隔時間裏它就能不斷產生不一樣的動態口令,並顯示到屏幕上,而銀行服務器上跟隨時間作一樣的計算,也會獲得和令牌卡一樣的口令,用做認證。
那麼TOTP算法具體作了什麼操做呢?在RFC6238中有詳細的算法描述,這裏也會作簡單的敘述。
TOTP是來自 HOTP [RFC4226] 的變形,從統籌上看,他們都是將數據文件進行散列計算,只是HOTP的因子是事件因子,TOTP將因子換成了時間因子,具體的TOTP計算公式(其中的HMAC-SHA-256也多是 HMAC-SHA-512):
TOTP = Truncate(HMAC-SHA-256(K,T))
其中: K 爲這裏的種子文件內容; T 爲計算出來的時間因子
公式中的 HMAC是密鑰相關的哈希運算消息認證碼(Hash-based Message Authentication Code),HMAC運算利用哈希算法,以一個密鑰和一個消息爲輸入,生成一個消息摘要做爲輸出。而公式中給出的哈希算法是 SHA-256,這種哈希算法目前並無好的破解辦法。
令牌卡中預先設置了要顯示的口令長度,TOTP 中的 Truncate 操做剪切得到口令。
以上就是動態口令令牌卡的內部原理。
幾點補充:
一、時間同步型動態口令對令牌卡和服務器的時間同步要求很高,時間偏差會形成整個令牌的失靈,因此每一次用戶成功使用令牌認證,服務器都會作相應的時間偏差矯正。
二、種子文件的產生使用了一種AES-128 變形而來的算法, AES-128 也是目前頂尖級的對稱加密技術。
三、目前從加密技術上以及數學理論上整個銀行機制的認證系統基本無解。
四、歡迎勘誤。
公司項目需求:爲局域網之外的網站後臺用戶開發動態密保的功能。
在當前的現有設備下,最方便實現的就兩種:一、經過短信獲取動態密碼登陸;二、經過手機令牌來實現。
項目採用:
https://code.google.com/p/androidtoken/ 實現TOTP動態口令登陸
android token 該項目支持HOTP (事件令牌)和TOTP (時間令牌)規範
配置令牌支持:KeyUriFormat和QR碼,以及手動建立;
項目實現:
我這裏採用添加方便的qr碼,也就是常見的二維碼來實現用戶經過手機來綁定一個token;
首先,須要有的就是服務器端和客戶端都共有的一個seed。
private final static String NUM_CHAR = "0123456789";
private static int charLen = NUM_CHAR.length();
/**
* 根據系統時間得到指定位數的隨機數
* @param randomNumberDigit 隨機數的位數
* @return 得到的隨機數
*/
public static String getRandomNumber(int randomNumberDigit) {
long seed = System.currentTimeMillis();// 得到系統時間,做爲生成隨機數的種子
StringBuffer sb = new StringBuffer();// 裝載生成的隨機數
Random random = new Random(seed);// 調用種子生成隨機數
for (int i = 0; i < randomNumberDigit; i++) {
sb.append(NUM_CHAR.charAt(random.nextInt(charLen)));
}
return sb.toString();
}
經過http://www.oschina.net/p/jquery-qrcode-js能夠很方便的生成二維碼。
二維碼的內容
otpauth://totp/oa?secret=63985989418859891633&period=60&digits=8(android 支持這個協議,能直接掃描讀取,添加一個token)
secret:密鑰,也就是上面生成的seed;period:每60秒生成一次;digits:生成的隨機碼長度。
經過動態口令驗證之後,服務器端也保存上seed;須要登錄的時候,服務器端生成動態口令和手機的來次對比就好了。
服務器端生成動態密碼的方法:
/** * 每60秒生成1個8位動態密碼 * * @param seed * @return */ public static String getTOTP(String seed) { long T0 = 0; long X = 60; Calendar cal = Calendar.getInstance(); long time = cal.getTimeInMillis() / 1000; String steps = "0"; try { long T = (time - T0) / X; steps = Long.toHexString(T).toUpperCase(); while (steps.length() < 16) steps = "0" + steps; return generateTOTP(seed, steps, "8", "HmacSHA1"); } catch (final Exception e) { System.out.println("Error : " + e); return "生成動態口令失敗"; } }/** * This method generates a TOTP value for the given set of parameters. * * @param key * : the shared secret, HEX encoded * @param time * : a value that reflects a time * @param returnDigits * : number of digits to return * @param crypto * : the crypto function to use * * @return: a numeric String in base 10 that includes * {@link truncationDigits} digits */ public static String generateTOTP(String key, String time, String returnDigits, String crypto) { int codeDigits = Integer.decode(returnDigits).intValue(); String result = null; // Using the counter // First 8 bytes are for the movingFactor // Compliant with base RFC 4226 (HOTP) while (time.length() < 16) time = "0" + time; // Get the HEX in a Byte[] byte[] msg = hexStr2Bytes(time); byte[] k = hexStr2Bytes(key); byte[] hash = hmac_sha(crypto, k, msg); // put selected bytes into result int int offset = hash[hash.length - 1] & 0xf; int binary = ((hash[offset] & 0x7f) << 24) | ((hash[offset + 1] & 0xff) << 16) | ((hash[offset + 2] & 0xff) << 8) | (hash[offset + 3] & 0xff); int otp = binary % DIGITS_POWER[codeDigits]; result = Integer.toString(otp); while (result.length() < codeDigits) { result = "0" + result; } return result; }