219 lines
4.9 KiB
Go
219 lines
4.9 KiB
Go
|
package otp
|
||
|
|
||
|
import "testing"
|
||
|
|
||
|
var rfc4226Secret = "12345678901234567890"
|
||
|
var rfc4226Codes = []string{
|
||
|
"755224",
|
||
|
"287082",
|
||
|
"359152",
|
||
|
"969429",
|
||
|
"338314",
|
||
|
"254676",
|
||
|
"287922",
|
||
|
"162583",
|
||
|
"399871",
|
||
|
"520489",
|
||
|
}
|
||
|
|
||
|
var baseRFC4226URL = "otpauth://hotp/IETF:ReferenceImplementation?counter=0&digits=6&issuer=IETF&secret=GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ"
|
||
|
|
||
|
func TestRFC4226OTP(t *testing.T) {
|
||
|
|
||
|
issuer := "IETF"
|
||
|
label := "ReferenceImplementation"
|
||
|
|
||
|
o := NewHOTPKeyOptions()
|
||
|
o.Secret = []byte(rfc4226Secret)
|
||
|
o.Issuer = issuer
|
||
|
o.Label = label
|
||
|
h := NewHOTPKey(o)
|
||
|
|
||
|
code, counter := h.IntegrityCheck()
|
||
|
if code != rfc4226Codes[counter] {
|
||
|
t.Logf("Invalid HOTP code for counter %d", counter)
|
||
|
t.Logf("\tExpected:\t%s\n", rfc4226Codes[counter])
|
||
|
t.Logf("\tActual: \t%s\n", code)
|
||
|
t.FailNow()
|
||
|
}
|
||
|
|
||
|
for counter, code := range rfc4226Codes[1:] {
|
||
|
generated := h.OTP()
|
||
|
if code != generated {
|
||
|
t.Logf("Invalid HOTP code for counter %d", counter)
|
||
|
t.Logf("\tExpected:\t%s\n", code)
|
||
|
t.Logf("\tActual: \t%s\n", generated)
|
||
|
t.FailNow()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if h.Issuer() != issuer {
|
||
|
t.Log("Invalid Issuer found")
|
||
|
t.Logf("\tExpected:\t%s\n", issuer)
|
||
|
t.Logf("\tActual: \t%s\n", h.Issuer())
|
||
|
t.FailNow()
|
||
|
}
|
||
|
|
||
|
if h.Label() != label {
|
||
|
t.Log("Invalid Issuer found")
|
||
|
t.Logf("\tExpected:\t%s\n", label)
|
||
|
t.Logf("\tActual: \t%s\n", h.Label())
|
||
|
t.FailNow()
|
||
|
}
|
||
|
|
||
|
if h.Type() != HOTP {
|
||
|
t.Log("Invalid Key type found")
|
||
|
t.Logf("\tExpected:\t%s\n", HOTP)
|
||
|
t.Logf("\tActual: \t%s\n", h.Type())
|
||
|
t.FailNow()
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
func TestRFC4226CustomCounter(t *testing.T) {
|
||
|
|
||
|
issuer := "IETF"
|
||
|
label := "ReferenceImplementation"
|
||
|
|
||
|
o := NewHOTPKeyOptions()
|
||
|
o.Secret = []byte(rfc4226Secret)
|
||
|
o.Issuer = issuer
|
||
|
o.Label = label
|
||
|
h := NewHOTPKey(o)
|
||
|
|
||
|
code, counter := h.IntegrityCheck()
|
||
|
if code != rfc4226Codes[counter] {
|
||
|
t.Logf("Invalid HOTP code for counter %d", counter)
|
||
|
t.Logf("\tExpected:\t%s\n", rfc4226Codes[counter])
|
||
|
t.Logf("\tActual: \t%s\n", code)
|
||
|
t.FailNow()
|
||
|
}
|
||
|
|
||
|
for counter, code := range rfc4226Codes[1:] {
|
||
|
if !h.Verify(code, uint64(counter)) {
|
||
|
t.Logf("Invalid HOTP code for counter %d", counter)
|
||
|
t.Logf("\tExpected:\t%s\n", code)
|
||
|
t.FailNow()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
func TestRFC4226FromURL(t *testing.T) {
|
||
|
|
||
|
h, err := FromURL(baseRFC4226URL)
|
||
|
if err != nil {
|
||
|
t.Log(err.Error())
|
||
|
t.FailNow()
|
||
|
}
|
||
|
|
||
|
k := h.(*HOTPKey)
|
||
|
code, counter := k.IntegrityCheck()
|
||
|
if code != rfc4226Codes[counter] {
|
||
|
t.Logf("Invalid HOTP code for counter %d", counter)
|
||
|
t.Logf("\tExpected:\t%s\n", rfc4226Codes[counter])
|
||
|
t.Logf("\tActual: \t%s\n", code)
|
||
|
t.FailNow()
|
||
|
}
|
||
|
|
||
|
for counter, code := range rfc4226Codes[1:] {
|
||
|
generated := h.OTP()
|
||
|
if code != generated {
|
||
|
t.Logf("Invalid HOTP code for counter %d", counter)
|
||
|
t.Logf("\tExpected:\t%s\n", code)
|
||
|
t.Logf("\tActual: \t%s\n", generated)
|
||
|
t.FailNow()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
func TestRFC4226ToURL(t *testing.T) {
|
||
|
|
||
|
o := NewHOTPKeyOptions()
|
||
|
o.Secret = []byte(rfc4226Secret)
|
||
|
o.Issuer = "IETF"
|
||
|
o.Label = "ReferenceImplementation"
|
||
|
h := NewHOTPKey(o)
|
||
|
|
||
|
if h.URL() != baseRFC4226URL {
|
||
|
t.Log("Invalid URL from RFC 4226 reference HOTP key")
|
||
|
t.Logf("\tExpected:\t%s\n", baseRFC4226URL)
|
||
|
t.Logf("\tActual: \t%s\n", h.URL())
|
||
|
t.FailNow()
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
func TestRFC4226Verify(t *testing.T) {
|
||
|
|
||
|
o := NewHOTPKeyOptions()
|
||
|
o.Secret = []byte(rfc4226Secret)
|
||
|
h := NewHOTPKey(o)
|
||
|
|
||
|
for counter, code := range rfc4226Codes {
|
||
|
if !h.Verify(code) {
|
||
|
t.Logf("Invalid HOTP code for counter %d", counter)
|
||
|
t.Logf("\tExpected:\t%s\n", code)
|
||
|
t.FailNow()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
func TestRFC4226CustomValidate(t *testing.T) {
|
||
|
secret := []byte(rfc4226Secret)
|
||
|
for counter, code := range rfc4226Codes {
|
||
|
|
||
|
if !ValidateCustom(secret, uint64(counter), code) {
|
||
|
t.Logf("Invalid HOTP code for counter %d", counter)
|
||
|
t.Logf("\tExpected:\t%s\n", code)
|
||
|
t.FailNow()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
func TestRFC4226CustomCode(t *testing.T) {
|
||
|
secret := []byte(rfc4226Secret)
|
||
|
for counter, code := range rfc4226Codes {
|
||
|
|
||
|
generated := CustomCode(secret, uint64(counter), uint(len(code)))
|
||
|
if code != generated {
|
||
|
t.Logf("Invalid HOTP code for counter %d", counter)
|
||
|
t.Logf("\tExpected:\t%s\n", code)
|
||
|
t.Logf("\tActual: \t%s\n", generated)
|
||
|
t.FailNow()
|
||
|
}
|
||
|
}
|
||
|
|
||
|
}
|
||
|
|
||
|
func TestHOTPVerify(t *testing.T) {
|
||
|
k := NewHOTPKey()
|
||
|
first := k.OTP()
|
||
|
if !k.Verify(first) { //successful verify increments counter
|
||
|
t.Logf("HOTP key %s failed to properly verify the first code - %s", k.URL(), first)
|
||
|
t.FailNow()
|
||
|
}
|
||
|
|
||
|
if !k.Verify(first) { //successful verify increments counter
|
||
|
t.Logf("HOTP key %s failed to properly verify the first code - %s", k.URL(), first)
|
||
|
t.Logf("First code should still be verified because of AllowedSkew")
|
||
|
t.FailNow()
|
||
|
}
|
||
|
|
||
|
if k.Verify(first) { //Key should have advanced to the next code
|
||
|
t.Logf("HOTP key %s should not have verified the first code - %s", k.URL(), first)
|
||
|
t.FailNow()
|
||
|
}
|
||
|
|
||
|
k.SetSkew(3)
|
||
|
if !k.Verify(first) { //successful verify increments counter
|
||
|
t.Logf("HOTP key %s failed to properly verify the first code - %s", k.URL(), first)
|
||
|
t.Logf("First code should still be verified because of AllowedSkew")
|
||
|
t.FailNow()
|
||
|
}
|
||
|
|
||
|
}
|