From 7a6c4c3d2bf4f06ba868b1c3694abcd05f8371c7 Mon Sep 17 00:00:00 2001 From: ErickSkrauch Date: Sat, 30 Sep 2017 02:41:26 +0300 Subject: [PATCH] =?UTF-8?q?=D0=A2=D0=B5=D0=BF=D0=B5=D1=80=D1=8C=20=D0=B8?= =?UTF-8?q?=D0=B7=20otp=20secret=20=D1=83=D0=B4=D0=B0=D0=BB=D1=8F=D1=8E?= =?UTF-8?q?=D1=82=D1=81=D1=8F=20=D0=B7=D0=BD=D0=B0=D1=87=D0=B5=D0=BD=D0=B8?= =?UTF-8?q?=D1=8F,=20=D0=BA=D0=BE=D1=82=D0=BE=D1=80=D1=8B=D0=B5=20=D0=BD?= =?UTF-8?q?=D0=B0=20=D0=BF=D0=B8=D1=81=D1=8C=D0=BC=D0=B5=20=D0=BC=D0=BE?= =?UTF-8?q?=D0=B3=D1=83=D1=82=20=D0=B1=D1=8B=D1=82=D1=8C=20=D1=81=D0=BF?= =?UTF-8?q?=D1=83=D1=82=D0=B0=D0=BD=D1=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../accounts/models/TwoFactorAuthInfo.php | 33 ++++++++++++++----- 1 file changed, 24 insertions(+), 9 deletions(-) diff --git a/api/modules/accounts/models/TwoFactorAuthInfo.php b/api/modules/accounts/models/TwoFactorAuthInfo.php index b3b0986..43e0829 100644 --- a/api/modules/accounts/models/TwoFactorAuthInfo.php +++ b/api/modules/accounts/models/TwoFactorAuthInfo.php @@ -42,20 +42,12 @@ class TwoFactorAuthInfo extends BaseAccountForm { } /** - * otp_secret кодируется в Base32, т.к. после кодирования в результурющей строке нет символов, - * которые можно перепутать (1 и l, O и 0, и т.д.). Отрицательной стороной является то, что итоговая - * строка составляет 160% от исходной. Поэтому, генерируя исходный приватный ключ, мы должны обеспечить - * ему такую длину, чтобы 160% его длины было равно запрошенному значению - * * @param int $length - * * @throws ThisShouldNotHappenException */ private function setOtpSecret(int $length = 24): void { $account = $this->getAccount(); - $randomBytesLength = ceil($length / 1.6); - $randomBase32 = trim(Base32::encodeUpper(random_bytes($randomBytesLength)), '='); - $account->otp_secret = substr($randomBase32, 0, $length); + $account->otp_secret = $this->generateOtpSecret($length); if (!$account->save()) { throw new ThisShouldNotHappenException('Cannot set account otp_secret'); } @@ -77,4 +69,27 @@ class TwoFactorAuthInfo extends BaseAccountForm { return str_pad($content, 91, '#'); } + /** + * otp_secret кодируется в Base32, но после кодирования в результурющей строке есть символы, + * которые можно перепутать (1 и l, O и 0, и т.д.). Т.к. целевая строка не предназначена для + * обратной расшифровки, то мы можем безжалостно их удалить. Итоговая строка составляет 160% + * от исходной. Поэтому, генерируя исходные случайные байты, мы должны обеспечить такую длину, + * чтобы 160% её было равно запрошенному значению. + * + * @param int $length + * @return string + */ + private function generateOtpSecret(int $length): string { + $randomBytesLength = ceil($length / 1.6); + $result = ''; + while (strlen($result) < $length) { + $encoded = Base32::encodeUpper(random_bytes($randomBytesLength)); + $encoded = trim($encoded, '='); + $encoded = str_replace(['I', 'L', 'O', 'U', '1', '0'], '', $encoded); + $result .= $encoded; + } + + return substr($result, 0, $length); + } + }