pragmarx/google2fa

一款一次性密码认证包,兼容Google Authenticator。

安装次数: 42,306,585

依赖: 109

建议者: 8

安全: 0

星标: 1,826

关注者: 50

分支: 199

公开问题: 12

v8.0.3 2024-09-05 11:56 UTC

README

PHP的Google双因素认证

Google2FA是Google双因素认证模块的PHP实现,支持在RFC 4226中指定的基于HMAC的一次性密码(HOTP)算法和RFC 6238中指定的基于时间的一次性密码(TOTP)算法。

Latest Stable Version License Code Quality Build Downloads

Monthly Downloads Coverage PHP

菜单

版本兼容性

Laravel桥接器

此包是中立的,但有一个Laravel桥接器

关于二维码生成

此包不生成用于双因素认证的二维码。

如果您正在寻找Google双因素认证,但还需要为其生成二维码,可以使用Google2FA QRCode包,该包集成了此包并使用BaconQRCode库生成二维码,或者您可以在此处文档中查看如何自行实现。

演示、示例与游乐场

请检查Google2FA Package Playground

playground

以下是一个演示应用程序,展示了如何使用Google2FA: google2fa-example

您可以使用Google Authenticator应用程序扫描此(旧)演示页面上的二维码,并实时查看代码的变化(几乎)。

要求

  • PHP 7.1或更高版本

安装

使用Composer进行安装

composer require pragmarx/google2fa

要生成内联二维码,您需要安装一个二维码生成器,例如BaconQrCode

composer require bacon/bacon-qr-code

使用方法

直接实例化它

use PragmaRX\Google2FA\Google2FA;

$google2fa = new Google2FA();

return $google2fa->generateSecretKey();

如何生成和使用双因素认证

为您的用户生成一个密钥并将其保存

$user->google2fa_secret = $google2fa->generateSecretKey();

生成二维码

生成二维码更安全的方法是自行生成或使用库。首先您需要安装一个二维码生成器,例如BaconQrCode,如上所述,然后您只需使用以下方式生成二维码url

$qrCodeUrl = $google2fa->getQRCodeUrl(
    $companyName,
    $companyEmail,
    $secretKey
);

一旦您有了二维码url,您就可以将其输入您首选的二维码生成器。

// Use your own QR Code generator to generate a data URL:
$google2fa_url = custom_generate_qrcode_url($qrCodeUrl);

/// and in your view:

<img src="{{ $google2fa_url }}" alt="">

要验证,您只需

$secret = $request->input('secret');

$valid = $google2fa->verifyKey($user->google2fa_secret, $secret);

二维码包

本软件包建议使用Bacon/QRCode,因为它被认为是优秀的二维码包,但您也可以使用其他任何包,例如Google2FA QRCodeSimple QrCodeEndroid QR Code,所有这些包都使用Bacon/QRCode来生成二维码。

通常您需要一个双因素认证(2FA)URL,因此您只需使用URL生成器即可。

$google2fa->getQRCodeUrl($companyName, $companyEmail, $secretKey)

使用示例

Google2FA QRCode

获取用于内联的二维码。

$google2fa = (new \PragmaRX\Google2FAQRCode\Google2FA());

$inlineUrl = $google2fa->getQRCodeInline(
    'Company Name',
    '[email protected]',
    $google2fa->generateSecretKey()
);

并在您的模板中使用它。

<img src="{{ $inlineUrl }}">

Simple QrCode

<div class="visible-print text-center">
    {!! QrCode::size(100)->generate($google2fa->getQRCodeUrl($companyName, $companyEmail, $secretKey)); !!}
    <p>Scan me to return to the original page.</p>
</div>

Endroid QR Code 生成器

生成数据URL。

$qrCode = new \Endroid\QrCode\QrCode($value);
$qrCode->setSize(100);
$google2fa_url = $qrCode->writeDataUri();

并在您的视图中使用。

<div class="visible-print text-center">
    {!! $google2fa_url !!}
    <p>Scan me to return to the original page.</p>
</div>

Bacon/QRCode

<?php

use PragmaRX\Google2FA\Google2FA;
use BaconQrCode\Renderer\ImageRenderer;
use BaconQrCode\Renderer\Image\ImagickImageBackEnd;
use BaconQrCode\Renderer\RendererStyle\RendererStyle;
use BaconQrCode\Writer;

$google2fa = app(Google2FA::class);

$g2faUrl = $google2fa->getQRCodeUrl(
    'pragmarx',
    '[email protected]',
    $google2fa->generateSecretKey()
);

$writer = new Writer(
    new ImageRenderer(
        new RendererStyle(400),
        new ImagickImageBackEnd()
    )
);

$qrcode_image = base64_encode($writer->writeString($g2faUrl));

并以图像的形式显示。

<img src="data:image/png;base64, <?php echo $qrcode_image; ?> "/>

HMAC算法

为了符合RFC6238,此软件包支持SHA1、SHA256和SHA512。默认为SHA1,因此要使用不同的算法,只需使用setAlgorithm()方法即可。

use PragmaRX\Google2FA\Support\Constants;

$google2fa->setAlgorithm(Constants::SHA512);

服务器时间

您需要确保服务器时间与某些NTP服务器同步,在Ubuntu上,您可以将其添加到crontab中。

sudo service ntp stop
sudo ntpd -gq
sudo service ntp start

验证窗口

为了避免时钟略微不同步的问题,我们不仅检查当前密钥,还考虑从过去和未来每个$window密钥。您可以将$window作为可选的第三个参数传递给verifyKey,默认为4。每30秒生成一个新密钥,因此此窗口包括前两分钟和后两分钟的密钥。

$secret = $request->input('secret');

$window = 8; // 8 keys (respectively 4 minutes) past and future

$valid = $google2fa->verifyKey($user->google2fa_secret, $secret, $window);

攻击者可能能够监视用户输入他的凭据和一次性密钥。如果不采取进一步预防措施,密钥将保持有效,直到它不再在服务器时间的窗口内。为了防止使用已经使用过的一次性密钥,您可以使用verifyKeyNewer函数。

$secret = $request->input('secret');

$timestamp = $google2fa->verifyKeyNewer($user->google2fa_secret, $secret, $user->google2fa_ts);

if ($timestamp !== false) {
    $user->update(['google2fa_ts' => $timestamp]);
    // successful
} else {
    // failed
}

请注意,$timestamp要么是false(如果密钥无效或之前已被使用),要么是提供的密钥的Unix时间戳除以30秒的密钥再生周期。

使用更大的值并前缀密钥

尽管16字节(128位)随机字符串的冲突概率非常低,但您可以通过以下方式加强它:

使用更大的密钥。

$secretKey = $google2fa->generateSecretKey(32); // defaults to 16 bytes

您可以在您的密钥前缀。

您可以在密钥前加前缀,但您必须理解,因为您的密钥长度必须是2的幂,所以您的前缀也必须有相应的尺寸。因此,如果您的密钥是16字节长,如果添加前缀,它也必须是16字节长,但由于您的前缀将被转换为32进制,所以前缀的最大长度是10字节。所以,这是您可以在前缀中使用的大小。

1, 2, 5, 10, 20, 40, 80...

并且可以像这样使用。

$prefix = strpad($userId, 10, 'X');

$secretKey = $google2fa->generateSecretKey(16, $prefix);

窗口

窗口属性定义了OTP将工作多长时间,或持续多少个周期。密钥有一个30秒的周期,将窗口设置为0将使密钥持续30秒,将窗口设置为2将使密钥持续120秒。这是设置窗口的方式。

$secretKey = $google2fa->setWindow(4);

但是,您也可以在检查密钥时设置窗口。如果需要在密钥验证期间设置4秒的窗口,这样做:

$isValid = $google2fa->verifyKey($seed, $key, 4);

密钥再生间隔

您可以更改密钥再生间隔,默认为30秒,但请记住,这是大多数身份验证应用程序的默认值,如Google Authenticator,这基本上会使您的应用程序与它们不同步。

$google2fa->setKeyRegeneration(40);

Google Authenticator密钥兼容性

为了与Google Authenticator兼容,您的(转换为32进制)密钥长度至少为8个字符,并且是2的幂:8、16、32、64...

因此,为了防止错误,在生成时您可以这样做:

$secretKey = '123456789';

$secretKey = str_pad($secretKey, pow(2,ceil(log(strlen($secretKey),2))), 'X');

它将生成

123456789XXXXXXX

默认情况下,此包将强制兼容性,但如果Google Authenticator不是目标,您可以通过以下方式禁用它

$google2fa->setEnforceGoogleAuthenticatorCompatibility(false);

Google Authenticator应用程序

要使用双因素认证,您的用户必须安装一个兼容Google Authenticator的应用,以下是一些目前可用的应用

弃用警告

Google API for QR generator已关闭。该包的5.0.0之前的所有版本都已弃用。请升级并查看有关QRCode生成的文档。

测试

此包的测试是用PHPUnit编写的。有一些Composer脚本来帮助您运行测试和分析

PHPUnit

composer test

PHPStan分析

composer analyse

作者

许可证

Google2FA遵循MIT许可证 - 请参阅LICENSE文件以获取详细信息。

贡献

欢迎提交拉取请求和问题。

赞助

直接

间接