Was ist TOTP und HOTP?

Zwei Schlagworte, die im Zusammenhang mit Zwei-Faktor Authentifizierung (2FA) immer wieder auftauchen sind HOTP und TOTP. Sie sind eine Alternative zu U2F, welches ich bereits vorgestellt habe.
HOTP und TOTP wurden von der Initiative for Open Authentication (OATH) definiert und von der IETF als RFC 4226 (HOTP, 2005) und RFC 6238 (TOTP, 2011) standardisiert.

HOTP steht für HMAC-based One-time Password. TOTP bedeutet Time-based One-time Password und basiert auf HOTP.

Beide Begriffe definieren Algorithmen, die eine sechs bis achtstellige Zahl generieren, die ein Benutzer als zweiten Faktor bei einer Anmeldung angeben kann.
Diese Zahl kann dem Benutzer beispielsweise per E-Mail oder SMS mitgeteilt werden. Auch gibt es Hardware-Geräte und Smartphone Apps die diese Codes generieren können.

HOTP

Der HOTP Algorithmus basiert auf einem Zähler, der jedes Mal, wenn eine neue Nummer generiert werden soll, eins hochgezählt wird. Diese Nummer wird zuerst mit HMAC und SHA-1 gehasht. Das resultierende Byte-Array wird anschliessend durch bit-shifting in eine Int32 Zahl umgewandelt und mittels Modulo (%) auf die gewünschte Länge (hier sechsstellig) gekürzt.

public string Hotp(byte[] key, int counter)
{
    var data = BitConverter.GetBytes(counter);

    if (BitConverter.IsLittleEndian)
    {
        Array.Reverse(data);
    }

    var hmac = new HMACSHA1(key);
    var hash = hmac.ComputeHash(data);

    var offset = hash[hash.Length - 1] & 0xF;
    var result = (hash[offset] & 0x7F) << 24 |
                 (hash[offset + 1] & 0xFF) << 16 |
                 (hash[offset + 2] & 0xFF) << 8 |
                 hash[offset + 3] & 0xFF;

    var hotp = result % (int)Math.Pow(10, 6);

    return hotp.ToString("D6");
}

TOTP

Wie bereits angesprochen, basiert TOTP auf HOTP. TOTP generiert alle 30 Sekunden eine neue Zahl. Dazu wird die Anzahl Sekunden zwischen Jetzt und der Unix-Epoche (1. Januar 1970) durch 30 geteilt. Diese Zahl wird dann für den HOTP Algorithmus verwendet.

public string Totp(byte[] key, DateTime time)
{
    var unixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
    var span = time.ToUniversalTime() - unixEpoch;
    var steps = (int)(span.TotalSeconds / 30);

    return Hotp(key, steps);
}

Damit TOTP mit einem App benützt werden kann, muss der geheime Schlüssel ausgetauscht werden. Dazu hat Google einen Standard geschaffen, der eine URL generiert, die als QR Code dargestellt wird, wobei der geheime Schlüssel Base32 encodiert wird.

otpauth://totp/{label}?secret={secretKey}&issuer={issuer}

In einem späteren Artikel werde ich zeigen, wie man Zwei-Faktor Authentifizierung in eine eigene Anwendung integriert.