Як працюють одноразові паролі, засновані на часі, і чому ви повинні використовувати їх у своєму додатку.

Зі зростанням загрози кібербезпеки стає все більш необхідним вдосконалювати стандарти безпеки ваших веб-додатків. Потрібно переконатися, що облікові записи користувачів безпечні.

На сьогоднішній день багато Інтернет-додатків просять користувачів додати додатковий рівень безпеки для свого облікового запису. Вони роблять це, увімкнувши двофакторну автентифікацію. Існують різні методи реалізації 2-факторної автентифікації, і TOTP (алгоритм одноразового пароля на основі часу) є одним із них.

У цій статті пояснюється, що це таке, і як і для чого його використовувати. Але перш ніж це зрозуміти, давайте спочатку коротко подивимося, що означає двофакторна автентифікація.

Що таке двофакторна аутентифікація?

Двофакторна автентифікація (або багатофакторна автентифікація) - це лише додатковий рівень безпеки для облікового запису користувача. Це означає, що після ввімкнення двофакторної автентифікації користувач повинен пройти ще один крок для успішного входу. Наприклад, звичайними кроками для входу в обліковий запис є:

Але після ввімкнення 2-факторної автентифікації кроки виглядають приблизно так:

Отже, це додає ще один крок до процесу входу. Цей метод є більш безпечним, оскільки злочинець не може отримати доступ до облікового запису користувача, якщо у нього немає доступу як до звичайного, так і до одноразового пароля користувача.

В даний час існує два широко використовувані методи отримання цього одноразового пароля:

  1. На основі SMS: за цього методу кожен раз, коли користувач входить в систему, він отримує текстове повідомлення на свій зареєстрований номер телефону, який містить одноразовий пароль.
  2. На основі TOTP: під час увімкнення двофакторної автентифікації користувачеві пропонується сканувати QR-зображення за допомогою певної програми для смартфона.

    Потім ця програма постійно генерує одноразовий пароль для користувача.

Метод на основі SMS не потребує пояснення. Це легко, але у нього є свої проблеми, такі як очікування SMS-повідомлення при кожній спробі входу, проблеми з безпекою тощо. Метод на основі TOTP стає популярним завдяки своїм перевагам перед методом на основі SMS. Тож давайте розберемося, як працює метод на основі TOTP.

Як працює метод на основі TOTP

Перш ніж це зрозуміти, давайте спочатку обговоримо, які проблеми для нас вирішить цей метод.

За допомогою методу TOTP ми створюємо одноразовий пароль на стороні користувача (замість сервера) за допомогою програми для смартфона.

Це означає, що користувачі завжди мають доступ до свого одноразового пароля. Таким чином, це заважає серверу надсилати текстові повідомлення щоразу, коли користувач намагається увійти.

Крім того, згенерований пароль змінюється через певний інтервал часу, тому він поводиться як одноразовий пароль.

Чудово! Тепер давайте розберемось у роботі методу TOTP і спробуємо реалізувати вищезазначене рішення самостійно. Наша вимога тут - створити пароль на стороні користувача, і цей пароль повинен постійно змінюватися.

Наступне може бути способом реалізації цього рішення:

When the user enables two factor authentication:
1. Backend server creates a secret key for that particular user.2. Server then shares that secret key with the user’s phone application.3. Phone application initializes a counter.4. Phone application generate a one time password using that secret key and counter.5. Phone application changes the counter after a certain interval and regenerates the one time password making it dynamic.

Це має спрацювати, але з цим є три основні проблеми:

  1. Як програма генерує одноразовий пароль за допомогою секретного ключа та лічильника?
  2. Як оновиться лічильник? Як веб-сервер буде відстежувати лічильник?
  3. Як сервер поділиться секретним ключем із програмою телефону?

Рішення першої задачі визначено в алгоритмі HOTP.

Розуміння HOTP:

HOTP означає "Одноразовий пароль на основі HMAC". Цей алгоритм був опублікований як RFC4226 Робочою групою Інженерного проектування (IETF). HOTP визначає алгоритм створення одноразового пароля з секретного ключа та лічильника.

Ви можете використовувати цей алгоритм у два етапи:

  1. Першим кроком є ​​створення хешу HMAC із секретного ключа та лічильника.
// Obtain HMAC hash (using SHA-1 hashing algorithm) by secretKey and counter
hmacHash = HMAC-SHA-1(secretKey, counter);

2. У цьому коді результат буде 20-байтним рядком. Цей довгий рядок не підходить як одноразовий пароль. Отже, нам потрібен спосіб усічення цього рядка. HOTP визначає спосіб усічення цього рядка до нашої бажаної довжини.

// hmacHash[19] means 19th byte of the string.offset = hmacHash[19] & 0xf;
truncatedHash = (hmacHash[offset++] & 0x7f) << 24 | (hmacHash[offset++] & 0xff) << 16 | (hmacHash[offset++] & 0xff) << 8 | (hmacHashh[offset++] & 0xff);
finalOTP = (truncatedHash % (10 ^ numberOfDigitsRequiredInOTP));

Це може виглядати страшно, але це не так. У цьому алгоритмі ми спочатку отримуємо, offsetякий є останніми 4 бітами hmacHash[19]. Після цього ми об'єднуємо байти з hmacHash[offset]до hmacHash[offset+3]і зберігаємо останні 31 біт до truncatedHash. Нарешті, використовуючи просту модульну операцію, ми отримуємо одноразовий пароль розумної довжини.

Це майже визначає алгоритм HOTP. Документ RFA4226 пояснює, чому це найбезпечніший спосіб отримати одноразовий пароль із цих двох значень.

Чудово! Отже, ми знайшли спосіб отримати одноразовий пароль за допомогою секретного ключа та лічильника. Але як щодо другої проблеми? Як вести облік лічильника?

Рішення другої проблеми знаходиться в TOTP.

Розуміння TOTP:

TOTP розшифровується як «Одноразовий пароль на основі часу». Це було опубліковано IETF як RFC6238.

A TOTP uses the HOTP algorithm to obtain the one time password. The only difference is that it uses “Time” in the place of “counter,” and that gives the solution to our second problem.

That means that instead of initializing the counter and keeping track of it, we can use time as a counter in the HOTP algorithm to obtain the OTP. As a server and phone both have access to time, neither of them has to keep track of the counter.

Also, to avoid the problem of different time zones of the server and phone, we can use a Unix timestamp, which is independent of time zones.

However the Unix time is defined in seconds, so it changes every second. That means the generated password will change every second which is not good. Instead, we need to add a significant interval before changing the password. For example, the Google Authenticator App changes the code every 30 seconds.

counter = currentUnixTime / 30

So we have solved the problem of the counter. Now we need to address our third problem: sharing the secret key with the phone application. Here, a QR code can help us.

Using a QR code

Though we can ask the users to type the secret key into their phone application directly, we want to make secret keys quite long for security reasons. Asking the user to type in such a long string would not be a user friendly experience.

Since the majority of smartphones are equipped with a camera, we can use it and ask the user to scan a QR code to obtain the secret key from it. So all we need to do is to convert the secret key in the QR code and show it to the user.

We have solved all three problems! And now you know how TOTP works. Let’s see how to implement it in an application.

How to implement TOTP

There are some free phone applications (like Google Authenticator App, Authy, and so on) available which can generate an OTP for the user. Therefore, in most cases, creating your own phone application is not necessary.

The following pseudo codes explain a way to implement TOTP-based 2-factor authentication in a web application.

When user request to enable 2-factor authentication
// Generate a secret key of length 20.secretKey = generateSecretKey(20);
// Save that secret key in database for this particular user.saveUserSecretKey(userId, secretKey);
// convert that secret key into qr image.qrCode = convertToQrCode(secretKey);
// send the qr image as responseresponse(qrCode);

The user is asked to scan that QR code. When the phone application scans the QR code, it gets the user’s secret key. Using that secret key, the current Unix time, and the HOTP algorithm, the phone application will generate and display the password.

We ask the user to type the generated code after scanning the QR code. This is required, because we want to make sure that the user has successfully scanned the image and the phone application has successfully generated the code.

User types the code displayed in the application.
// Fetch secret key from database.secretKey = getSecretKeyOfUser(userId);
if (codeTypedByUser == getHOTP(secretKey, currentUnixTime / 30)) { enableTwoFactorAuthentication(userId);}

Here we use the HOTP algorithm on the server side to get the OTP-based authentication on the secret key and current unix time. If that OTP is the same as the one typed by the user, then we can enable 2-factor authentication for that user.

Now after every login operation, we need to check if this particular user has 2-factor authentication enabled. If it is enabled, then we ask for the one time password displayed in the phone application. And if that typed code is correct, only then is the user authenticated.

User types the code displayed in the phone application to login
// Fetch secret key from database.secretKey = getSecretKeyOfUser(userId);
if (codeTypedByUser == getHOTP(secretKey, currentUnixTime)) { signIn(userId);}

What happens if the user loses the code?

There are a couple of ways to help the user to recover the code. Usually when they are enabling 2-factor authentication, we can show the secret key to them along with the QR code and ask them to save that code somewhere safely.

Applications like Google Authenticator App let you generate the password by directly entering the secret key. If the user loses the code, they can enter that safely saved secret key in the phone application to generate the OTP again.

If we have the user’s phone number, we can also use the SMS-based method to send an OTP to the user to help them recover the code.

Wrapping Up

Two factor authentication is gaining popularity. A lot of web applications are implementing it for extra security.

Unlike the SMS-based method, the TOTP method does not require a lot of extra effort either. So this feature is worth implementing for any application.