Frage

Ich versuche, mein Gehirn zu wickeln um einen 6-stellige / Zeichen nicht Fall zu erzeugen sensible Einmalpasswort abläuft.

Meine Quelle ist http://tools.ietf.org/html/rfc4226#section -5

Zuerst wird die Definition der Parameter

C       8-byte counter value, the moving factor.  This counter
       MUST be synchronized between the HOTP generator (client)
       and the HOTP validator (server).

K       shared secret between client and server; each HOTP
       generator has a different and unique secret K.

T       throttling parameter: the server will refuse connections
       from a user after T unsuccessful authentication attempts.

Dann haben wir den Algorithmus, um die HOTP zu erzeugen

As the output of the HMAC-SHA-1 calculation is 160 bits, we must
   truncate this value to something that can be easily entered by a
   user.

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

Dann haben wir Kürzen definiert als

String = String[0]...String[19]
 Let OffsetBits be the low-order 4 bits of String[19]
 Offset = StToNum(OffsetBits) // 0 <= OffSet <= 15
 Let P = String[OffSet]...String[OffSet+3]
 Return the Last 31 bits of P

Und dann wird ein Beispiel für einen 6-stellige HOTP angeboten

The following code example describes the extraction of a dynamic
binary code given that hmac_result is a byte array with the HMAC-
SHA-1 result:

    int offset   =  hmac_result[19] & 0xf ;
    int bin_code = (hmac_result[offset]  & 0x7f) << 24
       | (hmac_result[offset+1] & 0xff) << 16
       | (hmac_result[offset+2] & 0xff) <<  8
       | (hmac_result[offset+3] & 0xff) ;

Ich bin eher zu einem Verlust bei dem Versuch, diese in nützlich C # -Code zu konvertieren zum Erzeugen von Einmalpassworten. Ich habe bereits Code für einen auslaufenden HMAC wie folgt zu erstellen:

byte[] hashBytes = alg.ComputeHash(Encoding.UTF8.GetBytes(input));
byte[] result = new byte[8 + hashBytes.Length];

hashBytes.CopyTo(result, 8);
BitConverter.GetBytes(expireDate.Ticks).CopyTo(result, 0);

Ich bin nur nicht sicher, wie aus, dass zu gehen, bis 6 Ziffern wie in den obigen Algorithmen vorgeschlagen.

War es hilfreich?

Lösung

Sie haben zwei Probleme hier:

  1. Wenn Sie alphanumerische generieren, können Sie nicht an die RFC-konform sind - an diesem Punkt, können Sie einfach nehmen jede N Bytes und machen sie zu einem Hex-String und get alphanumerisches. Oder wandeln sie in die Basis 36 wenn Sie az wollen und 0-9. Abschnitt 5.4 der RFC Sie die Standard-HOTP berechnet für einen Satz Digit Parameter geben (man beachte, dass Digit ist ein Parameter, zusammen mit C, K und T). Wenn Sie die Wahl dieser Abschnitt zu ignorieren, dann brauchen Sie nicht, den Code zu konvertieren -. Nur verwenden, was Sie wollen

  2. Ihr "Ergebnis" Byte-Array hat die Ablaufzeit einfach in dem ersten 8 Bytes nach Hashing gestopft. Wenn Ihr Abschneiden auf 6-stellige alphanumerischen nicht dies sammelt zusammen mit Teilen des Hash, kann es auch überhaupt nicht berechnet werden. Es ist auch sehr einfach zu „Fälschung“ oder Replay - Hash das Geheimnis einmal, dann setzen, was Zecken Sie vor ihm wollen - nicht wirklich ein einmaliges Passwort. Beachten Sie, dass Parameter C im RFC soll die auslaufenden Fenster erfüllen und sollte an den Eingang vor Berechnung des Hash-Code hinzugefügt werden.

Andere Tipps

Für alle Interessierten, ich habe Figur aus einer Art und Weise zu bauen Ablauf in mein Einmal-Passwort. Der Ansatz ist die erzeugte Zeit zu nutzen, um die Minute nach unten (ohne Berücksichtigung von Sekunden, Millisekunden, etc.). Sobald Sie diesen Wert haben, verwenden Sie die Ticks des DateTime- als Zähler oder variable C.

otpLifespan ist meine HOTP Lebensdauer in Minuten.

DateTime current = new DateTime(DateTime.Now.Year, DateTime.Now.Month, 
    DateTime.Now.Day, DateTime.Now.Hour, DateTime.Now.Minute, 0);

for (int x = 0; x <= otpLifespan; x++)
{
    var result = NumericHOTP.Validate(hotp, key, 
        current.AddMinutes(-1 * x).Ticks);

    //return valid state if validation succeeded

    //return invalid state if the passed in value is invalid 
    //  (length, non-numeric, checksum invalid)
}

//return expired state

Meine auslaufenden HOTP erstreckt sich von meiner numerischen HOTP die eine statische Validierungsmethode hat, dass die Länge überprüft, stellt sie numerisch ist, überprüft die Prüfsumme, wenn es verwendet wird, und vergleicht schließlich die HOTP eingeleitet mit einem generierten ein.

Der einzige Nachteil ist, dass jedes Mal, wenn ein auslaufendes HOTP validieren, die Worst-Case-Szenario ist, n + 1 HOTP Werte zu überprüfen, wobei n die Lebensdauer in Minuten.

Das Java-Code Beispiel in dem Dokument umreißt RFC 4226 war ein sehr einfacher Einstieg in C #. Das einzige Stück wirklich musste ich jede Mühe in Umschreiben das Hashing-Verfahren war.

private static byte[] HashHMACSHA1(byte[] keyBytes, byte[] text)
{
    HMAC alg = new HMACSHA1(keyBytes);

    return alg.ComputeHash(text);
}

Ich hoffe, das hilft jemand versucht, eine Zeit Passwörter zu erzeugen.

sollten Dieser Code-Schnipsel tun, was Sie fragen:

  public class UniqueId
{
    public static string GetUniqueKey()
    {
        int maxSize = 6; // whatever length you want
        char[] chars = new char[62];
        string a;
        a = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
           char[] chars = new char[a.Length];
        chars = a.ToCharArray();
        int size = maxSize;
        byte[] data = new byte[1];
        RNGCryptoServiceProvider crypto = new RNGCryptoServiceProvider();
        crypto.GetNonZeroBytes(data);
        size = maxSize;
        data = new byte[size];
        crypto.GetNonZeroBytes(data);
        StringBuilder result = new StringBuilder(size);
        foreach (byte b in data)
        { result.Append(chars[b % (chars.Length - 1)]); }
        return result.ToString();
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top