基於TOTP的雙向認證演算法
基於otp演算法的雙向認證
先舉例一個應用場景吧,我們應該都用U盾,或者將軍令這種生成動態金鑰的工具,其實它內部就是基於OTP演算法來實現的。
谷歌也有開源這樣的開源專案,本文就是博主通讀了谷歌開源專案原始碼來實現的,專案地址:
演算法概要
TOTP(基於時間的一次性密碼演算法)是支援時間作為動態因素基於HMAC一次性密碼演算法的擴充套件。
本演算法是一個對稱演算法,也就是說,後臺和移動端採用同樣的金鑰,同時這個演算法是依賴於當前的系統時間的,所以可以用於動態驗證。
TOTP = HMAC-SHA-1(K, (T - T0) / X)
K 共享金鑰
T 當前時間戳
T0 開始的時間戳
X 時間步長
多嘮叨幾句:我們整體演算法採用處理金鑰的方式,是要將金鑰轉換成byte陣列之後進行操作的,還有就是谷歌的這套雙向認證演算法中嚴格的採用了Base32字串的方式,Base32中只有A-Z和2-7這些字元。
程式碼效果:
2017/08/09 20:39:56
983452
2017/08/09 20:39:57
983452
2017/08/09 20:39:58
983452
2017/08/09 20:39:59
983452
2017/08/09 20:40:00
977560
2017/08/09 20:40:01
977560
2017/08/09 20:40:02
977560
2017/08/09 20:40:03
977560
2017/08/09 20:40:04
977560
應用在app中的效果圖:
應用在app中的效果圖:
核心程式碼演算法:
演算法GitHub地址:https://github.com/linsir6/TOTP
演算法的核心類:
/**
* Created by linSir
* date at 2017/8/8.
* describe: 演算法的核心類
*/
public class PasscodeGenerator {
private static final int MAX_PASSCODE_LENGTH = 9;
private static final int[] DIGITS_POWER
// 0 1 2 3 4 5 6 7 8 9
= {1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000};
private final Signer signer;
private final int codeLength;
interface Signer {
byte[] sign(byte[] data) throws GeneralSecurityException;
}
public PasscodeGenerator(Signer signer, int passCodeLength) {
if ((passCodeLength < 0) || (passCodeLength > MAX_PASSCODE_LENGTH)) {
throw new IllegalArgumentException(
"PassCodeLength must be between 1 and " + MAX_PASSCODE_LENGTH
+ " digits.");
}
this.signer = signer;
this.codeLength = passCodeLength;
}
private String padOutput(int value) {
String result = Integer.toString(value);
for (int i = result.length(); i < codeLength; i++) {
result = "0" + result;
}
return result;
}
public String generateResponseCode(long state)
throws GeneralSecurityException {
byte[] value = ByteBuffer.allocate(8).putLong(state).array();
return generateResponseCode(value);
}
public String generateResponseCode(byte[] challenge)
throws GeneralSecurityException {
byte[] hash = signer.sign(challenge);
int offset = hash[hash.length - 1] & 0xF;
int truncatedHash = hashToInt(hash, offset) & 0x7FFFFFFF;
int pinValue = truncatedHash % DIGITS_POWER[codeLength];
return padOutput(pinValue);
}
private int hashToInt(byte[] bytes, int start) {
DataInput input = new DataInputStream(
new ByteArrayInputStream(bytes, start, bytes.length - start));
int val;
try {
val = input.readInt();
} catch (IOException e) {
throw new IllegalStateException(e);
}
return val;
}
}
整體演算法的思想和程式碼實現大概就是這樣,如果有什麼問題,歡迎大家在GitHub上面提Issues
相關文章
- Kubernetes客戶端認證——基於CA證書的雙向認證方式客戶端
- https雙向認證HTTP
- 利用基於 NTP 的 TOTP 演算法缺陷繞過 WordPress 登陸驗證演算法
- 基於TOTP演算法的Github兩步驗證2FA(雙因子)機制Python3.10實現演算法GithubPython
- 關於SSL證書雙向認證該怎麼操作
- Keytool配置 Tomcat的HTTPS雙向認證TomcatHTTP
- Openssl 設定 雙向認證證書的過程
- NodeJS Https HSM雙向認證實現NodeJSHTTP
- Https雙向認證Android客戶端配置HTTPAndroid客戶端
- QUIC 雙向認證、DDS 代理功能升級UI
- 扯一扯HTTPS單向認證、雙向認證、抓包原理、反抓包策略HTTP
- APP爬蟲-雙向認證抓包的兩種方法APP爬蟲
- 聊一聊HTTPS雙向認證的簡單應用HTTP
- 【認證與授權】2、基於session的認證方式Session
- 《數字身份驗證指南》草案中提議禁用基於簡訊的雙因子認證
- Kubernetes客戶端認證(二)—— 基於ServiceAccount的JWTToken認證客戶端JWT
- 007.iSCSI伺服器CHAP雙向認證配置伺服器
- Windows下IIS部署自建CA證書進行雙向認證的過程Windows
- 【等保】等保測評中雙因素認證是什麼意思?等於雙因子認證嗎?
- java 雙向證書請求 雙向驗證機制 轉載Java
- SpringBoot服務間使用自簽名證書實現https雙向認證Spring BootHTTP
- nginx配置ssl加密(單/雙向認證、部分https) – HTTPS SSL 教程Nginx加密HTTP
- 基於vue實現的雙向資料繫結Vue
- ASP.NET Core 基於JWT的認證(一)ASP.NETJWT
- ASP.NET Core 基於JWT的認證(二)ASP.NETJWT
- 雙向最大匹配演算法——基於詞典規則的中文分詞(Java實現)演算法中文分詞Java
- egg基於jsonwebtoken的Token實現認證機制JSONWeb
- 基於JWT規範實現的認證微服務JWT微服務
- Spring Boot 基於 SCRAM 認證整合 Kafka 的詳解Spring BootKafka
- 基於gin的golang web開發:認證利器jwtGolangWebJWT
- 雙因素認證解決方案
- 基於區塊鏈的身份認證系統開發區塊鏈
- 基於 JWT + Refresh Token 的使用者認證實踐JWT
- 如何在 Linux 中配置基於金鑰認證的 SSHLinux
- 基於MongodbDB的使用者認證-運維筆記MongoDB運維筆記
- 理解ASP.NET Core - 基於Cookie的身份認證(Authentication)ASP.NETCookie
- 理解ASP.NET Core - 基於JwtBearer的身份認證(Authentication)ASP.NETJWT
- 基於使用者認證的前後端實現後端
- 雙因素認證繞過的釣魚工具