⏱️ Kryptografia i protokoły RFC ✓ Analiza standardów IETF

TOTP vs HOTP bez tajemnic: Kluczowe różnice, bezpieczeństwo i zasady działania

Miliony programistów i inżynierów bezpieczeństwa codziennie korzystają z rotacyjnych 6-cyfrowych kodów weryfikacyjnych, lecz niewielu rozumie elegancki aparat matematyczny działający pod powierzchnią ekranu. Od sterowanych zdarzeniami liczników RFC 4226 (HOTP) z 2005 roku po dyskretne kroki czasowe RFC 6238 (TOTP) z 2011 roku — niniejszy przewodnik bada algorytm dynamicznego obcinania na poziomie bajtów, podatności związane z desynchronizacją liczników, tolerancję na dryf zegara oraz powody, dla których TOTP podbiło współczesny internet.

2FA
Zespół Bezpieczeństwa 2FA-Tool
Zaktualizowano: październik 2026
Szacowany czas czytania: 14 min (ponad 2600 słów)
RFC 6238 RFC 4226 Dynamiczne obcinanie
💡 Kluczowe wnioski kryptograficzne (TL;DR)
  • Fundamentalna różnica danych wejściowych: HOTP oblicza skróty na podstawie monotonicznie rosnącego licznika C, podczas gdy TOTP zastępuje C krokiem czasowym epoki T (BieżącyCzasUnix / 30).
  • Bezpośrednie dziedziczenie: Pod względem matematycznym TOTP jest bezpośrednią specjalizacją HOTP: TOTP(K, Czas) = HOTP(K, T). Oba algorytmy wykorzystują dokładnie tę samą funkcję dynamicznego obcinania (Dynamic Truncation).
  • Decydujący czynnik architektoniczny: HOTP jest stanowe (serwery muszą blokować rekord i zapisywać stan licznika na dysku przy każdej walidacji). TOTP jest bezstanowe, co umożliwia nowoczesnym chmurowym mikrousługom walidację tokenów w rozproszonych klastrach za load balancerami bez konieczności centralnego zapisu w bazie danych.
01

Źródła historyczne: Od własnościowych tokenów sprzętowych do otwartych standardów internetowych

Na początku lat 2000. korporacyjne uwierzytelnianie dwuskładnikowe było zdominowane przez własnościowe breloki sprzętowe, takie jak RSA SecurID. Te zamknięte, kosztowne urządzenia zawierały wewnętrzne rezonatory kwarcowe zsynchronizowane z własnościowymi serwerami przedsiębiorstwa. Jeśli organizacja chciała zapewnić wieloskładnikowe bezpieczeństwo tysiącom pracowników, koszty zakupu sprzętu i opłat licencyjnych były astronomiczne.

Aby uniezależnić uwierzytelnianie od monopolistycznych dostawców, liderzy branży powołali konsorcjum OATH (Initiative for Open Authentication), którego celem było opracowanie otwartych, bezpłatnych standardów IETF, możliwych do wdrożenia, inspekcji i audytu przez każdego inżyniera oprogramowania:

📜 2005: RFC 4226 (HOTP)

HMAC-Based One-Time Password Algorithm. Zaprojektowany z myślą o energooszczędnych mikrokontrolerach z fizycznym przyciskiem. Naciśnięcie przycisku inkrementuje wewnętrzny licznik i wyświetla 6-cyfrowy token na małym ekranie LCD.

📜 2011: RFC 6238 (TOTP)

Time-Based One-Time Password Algorithm. Powstał wraz z eksplozją popularności smartfonów. Wykorzystując synchronizację czasu sieciowego NTP w sieciach komórkowych, TOTP całkowicie wyeliminowało problem rozbieżności stanów fizycznych przycisków.

02

Architektura HOTP (RFC 4226) i bajtowa mechanika dynamicznego obcinania

Podstawowa definicja matematyczna algorytmu HOTP jest zwodniczo prosta:

HOTP(K, C) = Truncate(HMAC-SHA-1(K, C)) mod 10DigitCount

Szczegółowy opis parametrów:

  • K: Współdzielony symetryczny klucz tajny (zazwyczaj zdekodowany z Base32 160-bitowy / 20-bajtowy ciąg binarny).
  • C: 8-bajtowy (64-bitowy) licznik całkowity w formacie big-endian.
  • HMAC-SHA-1: Kod uwierzytelniania wiadomości z kluczem, generujący 20-bajtowy (160-bitowy) skrót kryptograficzny.

🔍 Jak Dynamic Truncation (DT) przekształca 20 bajtów w 6 cyfr:

Skrót HMAC-SHA1 składa się ze 160 bitów (20 bajtów). Wyodrębnienie 6 jednolitych cyfr dziesiętnych wymaga deterministycznego, odpornego na kolizje mechanizmu selekcji, zdefiniowanego w sekcji 5.3 normy RFC 4226:

// Krok 1: Obliczenie dynamicznego przesunięcia (Offset)
Offset = HS[19] & 0x0F
Pobierz ostatni bajt (indeks 19) 20-bajtowego skrótu. Maskowanie za pomocą 0x0F izoluje najmłodsze 4 bity, dając liczbę całkowitą z przedziału od 0 do 15 (od 0x0 do 0xF). Gwarantuje to, że kolejne wyodrębnienie 4 bajtów nigdy nie przekroczy 20-bajtowego bufora (ponieważ 15 + 4 = 19).
// Krok 2: Wyodrębnienie 4 kolejnych bajtów z maskowaniem
P = ( (HS[Offset] & 0x7F) << 24 ) | ( (HS[Offset+1] & 0xFF) << 16 ) | ( (HS[Offset+2] & 0xFF) << 8 ) | ( HS[Offset+3] & 0xFF )
Wyodrębnij 4 bajty zaczynając od pozycji Offset. Maska 0x7F zeruje najstarszy bit (MSB), zapobiegając przepełnieniu liczb ze znakiem na różnych architekturach procesorów (co zapewnia czystą, dodatnią 31-bitową liczbę całkowitą).
// Krok 3: Operacja modulo dla uzyskania ostatecznych cyfr
OTP = P mod 106 = P mod 1000000
Zastosowanie modulo 1 000 000 wyodrębnia ostatnie 6 cyfr dziesiętnych, uzupełniając je w razie potrzeby zerami wiodącymi (np. liczba 748 staje się ciągiem „000748”).
🧪 Konkretny wektor testowy z dodatku D normy RFC 4226:

Załóżmy, że kluczem tajnym jest ciąg ASCII "12345678901234567890", a licznik C = 0. Otrzymany skrót HMAC-SHA1 w zapisie szesnastkowym to:

cc 93 cf 18 50 8d 94 93 4c 64 b6 6d 8b fb 87 fb 23 cb 4b 71

1. Ostatnim bajtem jest 0x71. 0x71 & 0x0F = 0x01, zatem Offset = 1.
2. Bajty od 1 do 4 to: 93 cf 18 50. Wyzerowanie najstarszego bitu daje 0x13cf1850, co w zapisie dziesiętnym równa się 332 339 280.
3. 332339280 mod 1000000 = 339280. Otrzymany 6-cyfrowy kod OTP to 339280!

03

Ewolucja TOTP (RFC 6238): Magia kroku czasowego

HOTP wymagało utrzymywania ścisłej synchronizacji stanu licznika pomiędzy klientem a serwerem. Na urządzeniach programowych zliczanie kliknięć lub naciśnięć klawisza generowało nieustanne pomyłki użytkowników.

Norma RFC 6238 zastąpiła licznik C dyskretnym krokiem czasowym T wyliczanym bezpośrednio z zegara epoki Unix:

T = ⌊ (CurrentUnixTime - T0) / X ⌋
  • CurrentUnixTime: Liczba sekund, które upłynęły od 1970-01-01 00:00:00 UTC.
  • T0: Punkt odniesienia inicjalizacji epoki (domyślnie 0 we wszystkich współczesnych implementacjach).
  • X (Okno kroku czasowego): Standardowa zalecana długość wynosząca 30 sekund.
  • Funkcja podłogi ⌊ ⌋: Dla każdego znacznika czasu wewnątrz 30-sekundowego okna wartość T pozostaje niezmienna. Na przykład między sekundami epoki 1728211200 a 1728211229 wartość T daje dokładnie tę samą 64-bitową liczbę całkowitą.

Serializacja binarna: Po obliczeniu wartości T jest ona pakowana do 8-bajtowego bufora binarnego w formacie big-endian (o identycznej strukturze w pamięci jak licznik C w HOTP). W rezultacie ujednolicony wzór upraszcza się do postaci:
TOTP(K, Czas) = HOTP(K, T) Ta matematyczna elegancja wyjaśnia, dlaczego aplikacje uwierzytelniające rotują tokeny synchronicznie co 30 sekund bez konieczności ciągłej synchronizacji stanu sieciowego.

Wsparcie dla SHA-256 i SHA-512 w RFC 6238: Podczas gdy RFC 4226 ściśle definiowało HMAC-SHA-1, RFC 6238 rozszerzyło obsługę o algorytmy HMAC-SHA-256 i HMAC-SHA-512. W przypadku SHA-256 (skrót 32-bajtowy) przesunięcie pobiera się z bajtu 31 (HS[31] & 0x0F); w SHA-512 (skrót 64-bajtowy) z bajtu 63 (HS[63] & 0x0F). Jednak w 99,9% serwisów komercyjnych (Google, Microsoft, GitHub, AWS) domyślnym standardem pozostaje SHA-1 ze względu na kompatybilność ze starszymi klientami mobilnymi.
04

Szczegółowa macierz porównawcza (HOTP vs TOTP)

Wymiar HOTP (RFC 4226) TOTP (RFC 6238)
Zmienna wejściowa Licznik zdarzeń C (monotonicznie rosnący) Krok czasowy T (30-sekundowe okno epoki Unix)
Czas życia tokenu Nieokreślony (ważny do zużycia przy kolejnym logowaniu) Ściśle 30 sekund (automatycznie unieważniany)
Architektura serwera Stanowa (wymaga atomowych zapisów w bazie danych) Bezstanowa (niezależna weryfikacja z użyciem NTP)
Podatność na powtórzenia (Replay) Umiarkowana (przechwycony token jest ważny do momentu użycia) Minimalna (ograniczona do sekund pozostałych w oknie)
Główny powód awarii Desynchronizacja licznika (przypadkowe naciśnięcia przycisku) Dryf zegara (rozbieżność czasu w urządzeniu użytkownika)
Obsługiwane funkcje skrótu Wyłącznie HMAC-SHA-1 HMAC-SHA-1, HMAC-SHA-256, HMAC-SHA-512
Adopcja w branży Starsze tokeny bankowe, wyspecjalizowane bramki dostępu 99,9% nowoczesnych internetowych aplikacji 2FA
05

Desynchronizacja a dryf czasu: Rozwiązania inżynieryjne

W rozproszonych środowiskach produkcyjnych zegary i liczniki nieuchronnie podlegają rozbieżnościom. Twórcy kryptografii przewidzieli specjalne mechanizmy kompensacyjne:

⚙️ Mitygacja w HOTP: Okno weryfikacji w przód (Look-Ahead Window s)

Jeśli użytkownik kliknie przycisk na tokenie 5 razy bez wysłania formularza, licznik w urządzeniu osiągnie stan C+5, podczas gdy serwer pozostaje przy wartości C.
RFC 4226 nakazuje, aby serwer podczas uwierzytelniania obliczał wartości w oknie rozbieżności [C+1, C+s] (zazwyczaj s=20). Po znalezieniu dopasowania serwer natychmiast synchronizuje licznik do nowej wartości.

⏱️ Mitygacja w TOTP: Tolerancja przesunięcia czasu (okno ±1)

Ze względu na opóźnienia sieciowe lub minimalny dryf zegara w telefonie klienta (np. opóźnienie o 10 sekund), tokeny mogą dotrzeć w sąsiednich krokach czasowych.
Serwery produkcyjne sprawdzają tablicę 3 okien: [T-1, T, T+1], co skutecznie wydłuża akceptowalne okno weryfikacji do 90 sekund.

Obowiązkowa reguła Anti-Replay: Aby zapobiec atakom powtórzeniowym w 90-sekundowym oknie, serwery muszą zapisywać zużyte tokeny w pamięci podręcznej (np. Redis) na 90 sekund, odrzucając powtórne próby ich użycia.
🛡️ Porównywanie ciągów w stałym czasie (Obrona przed atakami czasowymi):

Gdy serwer weryfikuje zgodność kodu użytkownika z wyliczonym kodem, naiwne operacje porównywania ciągów (jak userOtp === serverOtp) kończą działanie przy pierwszym niezgodnym znaku. Napastnik mierzący mikroskopijne różnice w czasie odpowiedzi sieciowej może znak po znaku odgadnąć cały kod. Systemy korporacyjne wymuszają porównywanie w stałym czasie (np. crypto.timingSafeEqual w Node.js), eliminując ataki typu side-channel timing analysis.

06

Dlaczego TOTP zdominowało współczesny internet

Ostateczne zwycięstwo TOTP nad HOTP w internecie wynikało z trzech kluczowych filarów architektonicznych:

☁️ Bezstanowa skalowalność w chmurze

W rozproszonych mikrousługach obejmujących wiele regionów dowolna instancja serwera ze zsynchronizowanym czasem NTP może zweryfikować token TOTP bez blokowania centralnej bazy danych.

📱 Synergia z ekosystemem mobilnym

Smartfony nieustannie kalibrują zegary systemowe za pośrednictwem stacji bazowych GSM i GPS, całkowicie eliminując problem dryfu czasu bez konieczności serwisowania sprzętu.

🛡️ Wąskie 30-sekundowe okno ataku

Tokeny HOTP pozostają ważne bezterminowo aż do zużycia. Tokeny TOTP wygasają po 30 sekundach, automatycznie neutralizując ryzyko wynikające z wycieków z logów czy podsłuchu pakietów.

🧮 Czysty silnik RFC 6238 po stronie klienta

Sprawdź obliczenia TOTP w czasie rzeczywistym w 2FA-Tool

Zobacz, jak Twój tajny klucz Base32 przekształca się w dynamiczne 6-cyfrowe kody za pomocą algorytmu HMAC-SHA1 dynamic truncation. W 100% offline w Twojej przeglądarce.

Otwórz generator online