PHP - коды URI Google Authenticator не всегда работают
Так что у меня проблема с аутентификатором Google и моим PHP.
Поэтому я использую эту библиотеку для создания QR-кодов: https://github.com/PHPGangsta/GoogleAuthenticator
Поэтому, когда я использую свое имя пользователя для генерации кода, он работает нормально. Я получаю что-то вроде: otpauth://totp/username? Secret=aCodeInBase32&isser=Mysite
Для моего случая это: otpauth://totp/NoahNok? Secret=aCodeInBase32&isser=JukeHost
однако, делая это для любого другого использования, я получаю неверную ошибку токена в приложении Google Authenticator. Неважно, что еще я положил, я всегда получаю эту ошибку, но она отлично работает для моей учетной записи.
Например, этот не работает: otpauth://totp/Test? Secret=KRSX& эмитент = JukeHost
Есть что-то очевидное, что я делаю неправильно?
Код, который я использую: некоторые запросы, прежде чем получить данные
$g = new PHPGangsta_GoogleAuthenticator();
include("Base32.php");
$secret = substr(Base32::encode($username),0,-4);
echo $g->getQRCodeGoogleUrl($username, $secret, "JukeHost");
Создает QR URL
public function getQRCodeGoogleUrl($name, $secret, $title = null, $params = array())
{
$width = !empty($params['width']) && (int) $params['width'] > 0 ? (int) $params['width'] : 200;
$height = !empty($params['height']) && (int) $params['height'] > 0 ? (int) $params['height'] : 200;
$level = !empty($params['level']) && array_search($params['level'], array('L', 'M', 'Q', 'H')) !== false ? $params['level'] : 'M';
$urlencoded = urlencode('otpauth://totp/'.$name.'?secret='.$secret.'');
if (isset($title)) {
$urlencoded .= urlencode('&issuer='.urlencode($title));
}
return 'https://chart.googleapis.com/chart?chs='.$width.'x'.$height.'&chld='.$level.'|0&cht=qr&chl='.$urlencoded.'';
}
1 ответ
Base32 дополняется до ближайшего кратного из 8 символов, поэтому не всегда ====
в конце раздеться. Из ваших примеров мы получаем:
NoahNok => JZXWC2CON5VQ====
а также:
Test => KRSXG5A=
Поэтому, если вы удаляете последние 4 символа всегда, вы создадите недопустимую последовательность Base32 для ситуаций, подобных последним. Вы могли бы вместо этого использовать rtrim
вот так:
$secret = rtrim(Base32::encode($username), '=')
просто удалить все конечные равные (или просто оставить их в).
редактировать
Я просто думал об этом, и хотя вышеизложенное исправит ближайшую проблему, генерация секрета таким образом, вероятно, не очень хорошая идея. Если вы думаете об этом, установка секретного значения равным имени пользователя означает, что если кто-то найдет имя пользователя, он может сгенерировать действительный OTP и, следовательно, сможет передать свой 2FA.
Секрет должен быть уникальным и, как правило, неосуществимым для этой цели, а используемая вами библиотека имеет createSecret
способ сделать это для вас.