Google Authenticator,是谷歌推出的一款動(dòng)態(tài)口令工具,解決大家的google賬戶遭到惡意攻擊的問題;許多安全性比較高的網(wǎng)站都會(huì)采用這種工具來驗(yàn)證登錄或者交易;這個(gè)動(dòng)態(tài)口令就是Google身份驗(yàn)證器每隔30s會(huì)動(dòng)態(tài)生成一個(gè)6位數(shù)的數(shù)字。它的作用是:對你的賬號進(jìn)行“二步驗(yàn)證”保護(hù),或者說做一個(gè)雙重身份驗(yàn)證,來達(dá)到提升安全級別的目的。
通過 一致算法保持手機(jī)端和服務(wù)端相同,并每30秒改變認(rèn)證碼。
一致算法:
totp是基于時(shí)間的,htop是基于次數(shù)的。
秘鑰生成原理(基于時(shí)間)
1、時(shí)間戳,精確到微秒,除以1000,除以30(動(dòng)態(tài)6位數(shù)字每30秒變化一次)
2、對時(shí)間戳余數(shù) hmac_sha1 編碼
3、然后 base32 encode 標(biāo)準(zhǔn)編碼
4、輸出大寫字符串,即秘鑰
動(dòng)態(tài)6位數(shù)字驗(yàn)證:
Google Authenticator會(huì)基于密鑰和時(shí)間計(jì)算一個(gè)HMAC-SHA1的hash值,這個(gè)hash是160 bit的,然后將這個(gè)hash值隨機(jī)取連續(xù)的4個(gè)字節(jié)生成32位整數(shù),最后將整數(shù)取31位,再取模得到一個(gè)的整數(shù)。
這個(gè)就是Google Authenticator顯示的數(shù)字。
在服務(wù)器端驗(yàn)證的時(shí)候,同樣的方法來計(jì)算出數(shù)字,然后比較計(jì)算出來的結(jié)果和用戶輸入的是否一致。
Google Authenticator PHP類
https://github.com/PHPGangsta/GoogleAuthenticator
生成安全碼并綁定手機(jī)
<?php
require_once './PHPGangsta/GoogleAuthenticator.php';
$ga = new PHPGangsta_GoogleAuthenticator();
// 創(chuàng)建新的"安全密匙SecretKey"
// 把本次的"安全密匙SecretKey" 入庫,和賬戶關(guān)系綁定,客戶端也是綁定這同一個(gè)"安全密匙SecretKey"
// 安全密匙SecretKey 可以和手機(jī)端綁定
$secret = $ga->createSecret();
echo "安全密匙SecretKey: " . $secret . "\n\n";
//第一個(gè)參數(shù)是"標(biāo)識",第二個(gè)參數(shù)為"安全密匙SecretKey" 生成二維碼信息
$qrCodeUrl = $ga->getQRCodeGoogleUrl('www.xxx.com', $secret);
//Google Charts接口 生成的二維碼圖片,方便手機(jī)端掃描綁定安全密匙SecretKey
echo "Google Charts URL for the QR-Code: " . $qrCodeUrl . "\n\n";
輸出:
安全密匙SecretKey: M5X3M4PGBQRFPUTY
Google Charts URL for the QR-Code: https://api.qrserver.com/v1/create-qr-code/?data=otpauth%3A%2F%2Ftotp%2Fwww.xxx.com%3Fsecret%3DM5X3M4PGBQRFPUTY&size=200x200&ecc=M
綁定手機(jī)方式

- 通過安全秘鑰
-
通過二維碼(圖片地址就是Google Charts生成的可以直接打開)
image.png
動(dòng)態(tài)口令驗(yàn)證

<?php
require_once './PHPGangsta/GoogleAuthenticator.php';
$ga = new PHPGangsta_GoogleAuthenticator();
// 把提交的驗(yàn)證碼和服務(wù)端上生成的驗(yàn)證碼做對比
// $secret 服務(wù)端的 "安全密匙SecretKey"
// $oneCode 手機(jī)上看到的 "一次性驗(yàn)證碼"
// 最后一個(gè)參數(shù) 為容差時(shí)間,這里是2 那么就是 2* 30 sec 一分鐘.
$oneCode = '371922';
$secret = 'M5X3M4PGBQRFPUTY';
$checkResult = $ga->verifyCode($secret, $oneCode, 2);
if ($checkResult) {
//這里添加自定義邏輯
echo '匹配! OK';
} else {
echo '匹配! FAILED';
}
