[GH-ISSUE #170] Google Authenticator and Authy App generating invalid codes #312

Closed
opened 2026-03-01 17:49:06 +03:00 by kerem · 1 comment
Owner

Originally created by @tuckerww on GitHub (Jun 30, 2021).
Original GitHub issue: https://github.com/antonioribeiro/google2fa/issues/170

It appears that neither the Google Authenticator nor the Authy app generate valid codes, whereas other TOTP apps such as iPhone's built-in 2FA/password manager and the FreeOTP+ app on Android work fine.

My suspicion is that Google and/or Authy updated something in their codebases so that they're no longer compatible with the way the google2fa library generates either the secret or the valid auth-codes.

I tested both by scanning QR codes and by manually entering the secrets.

I also ensured that NTP is running on the server and that the date/time match up. Just in case I even tried passing an extremely large $window (100) to $google2fa->verifyKey() but that doesn't seem to be the issue.

Example Code:

<?

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

$google2fa = new Google2FA;
$google2fa->setAlgorithm('sha512');
$google2fa->setEnforceGoogleAuthenticatorCompatibility(true);

$user = array(
    "username" => "tucker",
    "secret" => "2HJTI6WHCC362T5Y" // a previously generated secret
);

if (isset($_GET["generate"])) {
    // to generate a new secret and thus QR code below too
    $user["secret"] = $google2fa->generateSecretKey();
}

$realCode = $google2fa->getCurrentOtp($user["secret"]); // get current valid code to compare

if ($_SERVER["REQUEST_METHOD"] == "POST") {
    // verify the code
    $window = 4;
    $valid = $google2fa->verifyKey($user["secret"], $_POST["code"], $window);
    if (!$valid) {
        print "INVALID CODE";
    } else {
        print "VALID CODE";
    }
}

// now to generate and print the QR code
$g2faUrl = $google2fa->getQRCodeUrl(
    'Google2fa Test',
    $user["email"],
    $user["secret"]
);

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

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

print "
<div style='text-align:center'>
    <h2>2FA Test using google2fa</h2>
    <b>Secret:</b> " . $user["secret"] . "<br>
    <b>QR Code:</b><br>
    <img src='data:image/png;base64, " . $qrcode_image . " '/>
    <form method='post'>
        <label for='code'>2FA Code</label>
        <input name='code'>
        <button type='submit'>Submit</button>
        <br><b>Current Valid Code:</b> " . $realCode . "<br>
    </form>
</div>";

PHP Version

PHP 7.2.20
Originally created by @tuckerww on GitHub (Jun 30, 2021). Original GitHub issue: https://github.com/antonioribeiro/google2fa/issues/170 It appears that neither the Google Authenticator nor the Authy app generate valid codes, whereas other TOTP apps such as iPhone's built-in 2FA/password manager and the FreeOTP+ app on Android work fine. My suspicion is that Google and/or Authy updated something in their codebases so that they're no longer compatible with the way the google2fa library generates either the secret or the valid auth-codes. I tested both by scanning QR codes and by manually entering the secrets. I also ensured that NTP is running on the server and that the date/time match up. Just in case I even tried passing an extremely large `$window` (100) to `$google2fa->verifyKey()` but that doesn't seem to be the issue. Example Code: ``` <? use PragmaRX\Google2FA\Google2FA; use BaconQrCode\Renderer\ImageRenderer; use BaconQrCode\Renderer\Image\ImagickImageBackEnd; use BaconQrCode\Renderer\RendererStyle\RendererStyle; use BaconQrCode\Writer; $google2fa = new Google2FA; $google2fa->setAlgorithm('sha512'); $google2fa->setEnforceGoogleAuthenticatorCompatibility(true); $user = array( "username" => "tucker", "secret" => "2HJTI6WHCC362T5Y" // a previously generated secret ); if (isset($_GET["generate"])) { // to generate a new secret and thus QR code below too $user["secret"] = $google2fa->generateSecretKey(); } $realCode = $google2fa->getCurrentOtp($user["secret"]); // get current valid code to compare if ($_SERVER["REQUEST_METHOD"] == "POST") { // verify the code $window = 4; $valid = $google2fa->verifyKey($user["secret"], $_POST["code"], $window); if (!$valid) { print "INVALID CODE"; } else { print "VALID CODE"; } } // now to generate and print the QR code $g2faUrl = $google2fa->getQRCodeUrl( 'Google2fa Test', $user["email"], $user["secret"] ); $writer = new Writer( new ImageRenderer( new RendererStyle(400), new ImagickImageBackEnd() ) ); $qrcode_image = base64_encode($writer->writeString($g2faUrl)); print " <div style='text-align:center'> <h2>2FA Test using google2fa</h2> <b>Secret:</b> " . $user["secret"] . "<br> <b>QR Code:</b><br> <img src='data:image/png;base64, " . $qrcode_image . " '/> <form method='post'> <label for='code'>2FA Code</label> <input name='code'> <button type='submit'>Submit</button> <br><b>Current Valid Code:</b> " . $realCode . "<br> </form> </div>"; ``` PHP Version ``` PHP 7.2.20 ```
kerem closed this issue 2026-03-01 17:49:07 +03:00
Author
Owner

@tuckerww commented on GitHub (Jun 30, 2021):

Aha! I have discovered the issue.

If you set the encryption algorithm to SHA512 then it doesn't work with the Google Authenticator App, but if you leave it as default then it works.

So in my above example I simply removed this line:

$google2fa->setAlgorithm('sha512');

This is because

Currently, the algorithm parameter is ignored by the Google Authenticator implementations.

So it uses SHA1 in the app no matter what you specify.

https://github.com/google/google-authenticator/wiki/Key-Uri-Format#algorithm

Closing this.

<!-- gh-comment-id:871601564 --> @tuckerww commented on GitHub (Jun 30, 2021): Aha! I have discovered the issue. If you set the encryption algorithm to SHA512 then it doesn't work with the Google Authenticator App, but if you leave it as default then it works. So in my above example I simply removed this line: ``` $google2fa->setAlgorithm('sha512'); ``` This is because > Currently, the algorithm parameter is ignored by the Google Authenticator implementations. So it uses SHA1 in the app no matter what you specify. https://github.com/google/google-authenticator/wiki/Key-Uri-Format#algorithm Closing this.
Sign in to join this conversation.
No labels
bug
pull-request
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/google2fa#312
No description provided.