二要素認証とは何ですか?
人気話す、一般的な認証は、これは、パスワード認証のための唯一の要因である、ユーザ名/パスワードの方法である、二要素の増加は、セキュリティを強化する要素認証以外の何ものでもありません。
一般的なソリューション
- SMS
- 郵便
- 音声による電話
- TOTPソリューション
最初の三つのプログラムは、それらはすべて類似していました。検証サーバ、サーバの後に利用者にSMS、電子メールや電話の方法、ランダムなパスワードを介してユーザに配信ランダムパスワードのアルゴリズムによって生成されたサーバー側は、ログオン資格情報などの二要素認証を完了しました。しかし、そこに事業会社のためのテキストメッセージや電話音声は、いくつかの非インターネットアプリケーションに加えて、公衆網を介してではないかもしれないが、一定のコストである。この場合、TOTPが良い二要素認証ソリューションであること。
TOTPとは何ですか?
これは、タイムスタンプに基づいてワンタイムパスワードアルゴリズムを表し、時間ベースのワンタイムパスワードの省略形です。
私たちはファンタジー西の旅を果たした場合は、上の将军令
不慣れすべきではない、これはTOTPに基づく製品です。
OTP
導入TOTP前に、最初に導入OTP
ワンタイムパスワードの速記は、ワンタイムパスワードを表します。
OTP(K,C) = Truncate(HMAC-SHA-1(K,C))
ここで、キーストリングのKを表す、HMAC-SHA-1 DO HMAC SHA-1で表される; Cは、乱数を表す数です。
暗号化された文字列のための関数は、いくつかのフィールドと文字列を取って暗号化されたデジタル、取られている切り捨てます。
暗号化されたHMAC-SHA-1モードでは、以下を達成するために切り捨てされます。
- HMAC-SHA-1暗号化された20バイトの暗号化された文字列の長さを与えます。
- 標準オフセット暗号化された文字列としたバイトの下位4ビットを要する20バイトの暗号化された文字列の最後のバイトを取ります。
- 開始オフセット索引4つのバイトを得るためによれば、ビッグエンディアン(下位アドレスに上位バイト)の整数の実施形態により構成されています。
- インターセプト後整数6または8文字列に変換されます。
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;
}
返された結果は、動的パスワードの数を確認することです。
HOTP
私たちは、乱数にパラメータCのちょうど1 OTP、HOTPの基本原則を知っています
式を変更します。
HOTP(K、C)=切捨て(HMAC-SHA-1(K、C))
HOTP:与えられたカウントにOTPを生成します
すなわち:Cは、引数として、動的パスワードを取得します。
SHA2を使用して一般的なHOTP所定のハッシュ関数、すなわち:SHA-256やSHA-512 [SHA2]同期検証ハッシュ関数に基づいてイベントを行います。
詳細TOTP
TOTPタイムスタンプによって生成された番号にだけ、パラメータC。
TOTP(K,C) = HOTP(K,C) = Truncate(HMAC-SHA-1(K,C))
TOTPはC.計算したタイムスタンプと異なっています
C = (T - T0) / X;
Tは現在のUnixタイムスタンプを表し
ゼロT0一般的な値です。
X時間ステップの数を表し、それは動的なパスワードよりも多くを言うことですが、長い時間のために生成され、この時間間隔は、ステップの時間Xの数は、システムのデフォルトは30秒です。
例えば:
T0 = 0;
X = 30。
T = 30〜59、C = 1; 59から30は、30秒を一致動的パスワードを表します。
T = 60〜89、C = 2; 59から30は、30秒を一致動的パスワードを表します。
異なるメーカーが異なるの時間ステップを使用します。
- 時間の数は、使用アリババ宝アイデンティティは60秒です手順。
- むしろシールドトークンを使用して、時間ステップの数は、60秒です。
- Googleの認証の時間ステップ数は30秒です。
- 時間ステップのトークンテンセント数は60秒です。
アプリケーション
多くのクライアントが記載されている上記の達成があります。サーバー側の実装ライブラリは一見も非公式達成され、比較的小さいです。ここでは、お勧めのJava実装ライブラリプライベートライブラリ、心の友だけで、自分のラインとホイールです。
ここで認識に基づくライブラリーは、いくつかのデモコードは、参照のみを目的として与えられています。
package com.github.chenqimiao.util;
import java.text.MessageFormat;
import com.warrenstrange.googleauth.GoogleAuthenticator;
import com.warrenstrange.googleauth.GoogleAuthenticatorConfig;
import com.warrenstrange.googleauth.GoogleAuthenticatorConfig.GoogleAuthenticatorConfigBuilder;
import com.warrenstrange.googleauth.GoogleAuthenticatorKey;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
/**
* @Auther: chenqimiao
* @Date: 2019/8/26 22:58
* @Description: refer https://github.com/wstrange/GoogleAuth
*/
@Slf4j
public class GoogleAuthenticatorUtils {
// 前缀
private static final String DEFAULT_USER_PREFIX = "TOTP_USER:";
// 用户名|密钥|发行者
public static final String QRCODE_TEMPLATE = "otpauth://totp/" + DEFAULT_USER_PREFIX + "{0}?secret={1}&issuer={2}";
// 默认的发行者
public static final String DEFAULT_ISSUER = "DAS_TOTP";
private static final GoogleAuthenticatorConfig DEFAULT_CONFIG;
static {
GoogleAuthenticatorConfigBuilder builder = new GoogleAuthenticatorConfigBuilder();
// Do something here if you want to set config for GoogleAuthenticator
DEFAULT_CONFIG = builder.build();
}
public static String createQrCodeContent(String username, String secret) {
return createQrCodeContent(username, secret, DEFAULT_ISSUER);
}
public static String createQrCodeContent(String username, String secret, String issuer) {
return MessageFormat.format(QRCODE_TEMPLATE, username, secret, issuer);
}
public static String createSecret() {
return createSecret(DEFAULT_CONFIG);
}
public static String createSecret(GoogleAuthenticatorConfig config) {
GoogleAuthenticator gAuth = new GoogleAuthenticator(config);
final GoogleAuthenticatorKey key = gAuth.createCredentials();
return key.getKey();
}
public static boolean verify(Integer totpPwd, String secret) {
return verify(totpPwd, secret, DEFAULT_CONFIG);
}
public static boolean verify(Integer totpPwd, String secret, GoogleAuthenticatorConfig config) {
GoogleAuthenticator gAuth = new GoogleAuthenticator(config);
return gAuth.authorize(secret, totpPwd);
}
public static Integer getTotpPassword(String secret) {
return getTotpPassword(secret, DEFAULT_CONFIG);
}
public static Integer getTotpPassword(String secret, GoogleAuthenticatorConfig config) {
GoogleAuthenticator gAuth = new GoogleAuthenticator(config);
return gAuth.getTotpPassword(secret);
}
@SneakyThrows
public static void main(String args[]) {
String secret = createSecret();
String qrcodeContent = createQrCodeContent("chenqimiao", secret);
System.out.println("qrcodeContent is " + qrcodeContent);
Integer totpPwd = getTotpPassword(secret);
System.out.println("Current totp password is " + totpPwd);
boolean result = verify(totpPwd, secret);
System.out.println("result is " + result);
}
qrcodeContent二次元コードを使用して、二次元コードツールによって生成することができるGoogle認証を二次元コードをスキャンした後、それはユーザバインドオーセンティケータと同等です。