package totp import ( "testing" "time" ) func TestGenerateAndValidateCode_RoundTrip(t *testing.T) { secret, err := GenerateSecret() if err != nil { t.Fatalf("generate secret: %v", err) } now := time.Now() code, err := GenerateCode(secret, now) if err != nil { t.Fatalf("generate code: %v", err) } if len(code) != 6 { t.Fatalf("erwartet 6-stelligen code, habe %q", code) } ok, err := Validate(secret, code, now) if err != nil { t.Fatalf("validate: %v", err) } if !ok { t.Fatal("erwartet gueltigen code") } wrongCode := "000000" if code == wrongCode { wrongCode = "111111" } ok, err = Validate(secret, wrongCode, now) if err != nil { t.Fatalf("validate (falsch): %v", err) } if ok { t.Fatal("erwartet ungueltig fuer falschen code") } } // Akzeptanzkriterium/Pruefung 3: Zeitversatz-Toleranz dokumentiert (siehe // DefaultSkewSteps = 1 Schritt = 30s) und getestet. func TestValidate_ClockSkewTolerance(t *testing.T) { secret, err := GenerateSecret() if err != nil { t.Fatalf("generate secret: %v", err) } now := time.Now() // Code aus dem VORHERIGEN Zeitfenster (bis zu 30s in der Vergangenheit) // muss innerhalb der dokumentierten Toleranz noch akzeptiert werden. pastCode, err := GenerateCode(secret, now.Add(-25*time.Second)) if err != nil { t.Fatalf("generate code (past): %v", err) } ok, err := Validate(secret, pastCode, now) if err != nil { t.Fatalf("validate (past): %v", err) } if !ok { t.Fatal("erwartet gueltig innerhalb der dokumentierten skew-toleranz (25s)") } // Code weit ausserhalb der Toleranz (mehrere Schritte in der // Vergangenheit) muss abgelehnt werden. farPastCode, err := GenerateCode(secret, now.Add(-5*time.Minute)) if err != nil { t.Fatalf("generate code (far past): %v", err) } ok, err = Validate(secret, farPastCode, now) if err != nil { t.Fatalf("validate (far past): %v", err) } if ok { t.Fatal("erwartet ungueltig weit ausserhalb der skew-toleranz (5min)") } }