两步验证与Google Authenticator的实现

在当今的网络安全环境中,两步验证已成为保护用户账户免受未授权访问的重要手段。Google Authenticator是一个流行的两步验证应用程序,它通过生成一次性密码(OTP)来增强账户的安全性。本文将介绍如何实现Google Authenticator的OTP生成机制,并提供PHP代码示例。

两步验证,又称为双因素认证,是一种安全措施,要求用户在登录过程中提供两种形式的身份验证。这通常包括用户知道的信息(如密码)和用户拥有的信息(如手机生成的一次性密码)。这种机制大大降低了个人Google账户信息被他人窃取的风险,因为即使黑客获取了用户的用户名和密码,他们还需要获取用于生成六位数字组合的个人密钥。

OTP的生成过程

OTP的生成过程基于RFC6238标准。首先,需要一个以base32编码的密钥。例如:

GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ

这个密钥实际上是一个base32编码的字符串。选择base32而不是base64的原因包括:

  • 生成的字符集全部为大写,这在使用大小写不敏感的文件系统、口头交流或人脑记忆时可能更有利。
  • 字母表被选择来避免不同符号的相似对,因此字符串可以被手工准确转录。
  • 结果可以被包含在URL中而不需要编码任何字符。

简而言之,编码后的消息比base64更容易记忆。

时间因素

OTP的生成还涉及到时间因素,更准确地说,是以30秒为间隔。考虑到不是所有设备都使用NTP进行同步,可能需要检查3-5个连续的代码以确保正确的代码被输入。解决方案越安全,可能想要检查的30秒间隔就越少。

HOTP算法

让使用当前的Unix时间戳来计算HOTP(基于HMAC的一次性密码)。

UnixTimeStamp (time()/30): 44376117.366667

需要计算6位数字的代码。首先,取上述值的截断:

44376117

然后将其转换为十六进制:

2a52035

打包成字节字符串:

0x20a52035

如果十六进制字符串少于16个字符,则使用0字符从左侧填充。

十进制表示:

0 0 0 0 2 165 32 53

现在计算sha1 HMAC:

hash_hmac('sha1', '...<¥ 5...', '12345678901234567890')

计算结果:

af2b88048dc8979b528af4e37085061d88aaaaa5

将此转换为6位数字序列:

  1. 将十六进制数组转换为其十进制形式。
  2. 取数组的第19个元素(在此例中为165),并执行位运算。
  3. 将结果与10的幂次进行模运算,以获取所需的序列长度(对于6位数字,是1000000)。

最终结果为:

895250

这就是Google Authenticator应用程序生成的结果。

PHP实现

以下是使用PHP实现上述算法的示例代码。

首先,需要一些库来简化开发。对于PHP,可以使用:

  • Bryan Ruiz的Base32实现。
  • 社区反馈的PHP HMAC哈希实现。

基于RFC6238的实现:

rfc6238.php

包含帮助类TokenAuth6238,具有多个有用功能。

密钥用于为应用程序和生成代码的设备提供基础,以验证用户的身份。密钥很重要,应该通过安全通道传输。如果攻击者获取了密钥,他们就可以生成验证代码并绕过安全程序。

secret = Base32::encode("yourrandomsecretkey");

Google提供了Android和iPhone应用程序,用于为用户生成验证代码。安装应用程序并创建一个新帐户,输入上一步生成的代码。按照意愿命名帐户,并选择基于时间的令牌。现在,可以在智能手机上看到一个6位长的密码,允许验证用户的身份。

现在有了密钥,智能手机正在生成验证代码,让尝试验证它。

<?php require_once("rfc6238.php"); $secretkey = 'GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ'; $currentcode = '571427'; if (TokenAuth6238::verify($secretkey, $currentcode)) { echo "Code is valid\n"; } else { echo "Invalid code\n"; } ?>

也可以使用库自己生成验证代码。

print TokenAuth6238::getTokenCodeDebug($secretkey, 0);

还可以生成一个图像,该图像可以被移动设备用于配置认证程序:

print sprintf('', TokenAuth6238::getBarCodeUrl('', '', $secretkey)); https://github.com/Voronenko/PHPOTP
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485