cb4d88ebdd
- authenticator: HOTP RFC 4226 向量、Base32 往返、SecretData 往返 - crypto: WAGO1 加密解密往返、错误密码、空密码、无效载荷 - config: YAML 明文/加密读写、密码错误、.bak 轮换 - qr: EntryToOtpAuth 各 vendor、URI 往返、默认值省略
160 lines
3.5 KiB
Go
160 lines
3.5 KiB
Go
package qr
|
|
|
|
import (
|
|
"strings"
|
|
"testing"
|
|
|
|
"git.wxccs.org/iceking2nd/winauth-go/internal/config"
|
|
)
|
|
|
|
func TestEntryToOtpAuthGoogle(t *testing.T) {
|
|
e := config.Entry{
|
|
Name: "MyGoogle",
|
|
Vendor: "google",
|
|
SecretRaw: "0102030405\t6\tSHA1\t30",
|
|
}
|
|
oa, partial, err := EntryToOtpAuth(e)
|
|
if err != nil {
|
|
t.Fatalf("EntryToOtpAuth: %v", err)
|
|
}
|
|
if partial {
|
|
t.Error("Google should not be partial")
|
|
}
|
|
if oa.Type != "totp" {
|
|
t.Errorf("Type = %q, want totp", oa.Type)
|
|
}
|
|
if oa.Issuer != "Google" {
|
|
t.Errorf("Issuer = %q, want Google", oa.Issuer)
|
|
}
|
|
if oa.Label != "Google:MyGoogle" {
|
|
t.Errorf("Label = %q", oa.Label)
|
|
}
|
|
if oa.Digits != 6 {
|
|
t.Errorf("Digits = %d, want 6", oa.Digits)
|
|
}
|
|
if oa.Algorithm != "SHA1" {
|
|
t.Errorf("Algorithm = %q, want SHA1", oa.Algorithm)
|
|
}
|
|
}
|
|
|
|
func TestEntryToOtpAuthHOTP(t *testing.T) {
|
|
e := config.Entry{
|
|
Name: "Counter",
|
|
Vendor: "hotp",
|
|
SecretRaw: "AABBCCDD\t6\tSHA1\t30|10",
|
|
}
|
|
oa, _, err := EntryToOtpAuth(e)
|
|
if err != nil {
|
|
t.Fatalf("EntryToOtpAuth: %v", err)
|
|
}
|
|
if oa.Type != "hotp" {
|
|
t.Errorf("Type = %q, want hotp", oa.Type)
|
|
}
|
|
if oa.Counter != 10 {
|
|
t.Errorf("Counter = %d, want 10", oa.Counter)
|
|
}
|
|
}
|
|
|
|
func TestEntryToOtpAuthBattleNetPartial(t *testing.T) {
|
|
e := config.Entry{
|
|
Name: "BNet",
|
|
Vendor: "battlenet",
|
|
SecretRaw: "AABB\t8\tSHA1\t30|53455249414C",
|
|
}
|
|
oa, partial, err := EntryToOtpAuth(e)
|
|
if err != nil {
|
|
t.Fatalf("EntryToOtpAuth: %v", err)
|
|
}
|
|
if !partial {
|
|
t.Error("Battle.Net should be partial")
|
|
}
|
|
if oa.Digits != 8 {
|
|
t.Errorf("Digits = %d, want 8", oa.Digits)
|
|
}
|
|
}
|
|
|
|
func TestEntryToOtpAuthSteamPartial(t *testing.T) {
|
|
e := config.Entry{
|
|
Name: "Steam",
|
|
Vendor: "steam",
|
|
SecretRaw: "CCDD\t5\tSHA1\t30|73657269616C|646576696365",
|
|
}
|
|
_, partial, err := EntryToOtpAuth(e)
|
|
if err != nil {
|
|
t.Fatalf("EntryToOtpAuth: %v", err)
|
|
}
|
|
if !partial {
|
|
t.Error("Steam should be partial")
|
|
}
|
|
}
|
|
|
|
func TestEntryToOtpAuthEmptySecret(t *testing.T) {
|
|
e := config.Entry{Name: "Empty", Vendor: "google", SecretRaw: ""}
|
|
if _, _, err := EntryToOtpAuth(e); err == nil {
|
|
t.Error("expected error for empty secret")
|
|
}
|
|
}
|
|
|
|
func TestURIRoundTrip(t *testing.T) {
|
|
e := config.Entry{
|
|
Name: "Test",
|
|
Vendor: "google",
|
|
SecretRaw: "0102030405\t6\tSHA1\t30",
|
|
}
|
|
oa, _, err := EntryToOtpAuth(e)
|
|
if err != nil {
|
|
t.Fatalf("EntryToOtpAuth: %v", err)
|
|
}
|
|
uri := oa.URI()
|
|
|
|
// Parse it back
|
|
parsed, err := ParseOtpAuth(uri)
|
|
if err != nil {
|
|
t.Fatalf("ParseOtpAuth(%q): %v", uri, err)
|
|
}
|
|
if parsed.Type != "totp" {
|
|
t.Errorf("Type = %q, want totp", parsed.Type)
|
|
}
|
|
if parsed.SecretBase32 != oa.SecretBase32 {
|
|
t.Errorf("Secret mismatch: %q vs %q", parsed.SecretBase32, oa.SecretBase32)
|
|
}
|
|
}
|
|
|
|
func TestURIHOTP(t *testing.T) {
|
|
oa := &OtpAuth{
|
|
Type: "hotp",
|
|
Label: "MyHOTP",
|
|
SecretBase32: "JBSWY3DPEHPK3PXP",
|
|
Issuer: "Test",
|
|
Digits: 6,
|
|
Counter: 42,
|
|
}
|
|
uri := oa.URI()
|
|
if !strings.Contains(uri, "counter=42") {
|
|
t.Errorf("URI missing counter: %s", uri)
|
|
}
|
|
if !strings.HasPrefix(uri, "otpauth://hotp/") {
|
|
t.Errorf("URI wrong prefix: %s", uri)
|
|
}
|
|
}
|
|
|
|
func TestURIDefaultsOmitted(t *testing.T) {
|
|
oa := &OtpAuth{
|
|
Type: "totp",
|
|
SecretBase32: "AAAA",
|
|
Algorithm: "SHA1",
|
|
Digits: 6,
|
|
Period: 30,
|
|
}
|
|
uri := oa.URI()
|
|
if strings.Contains(uri, "algorithm") {
|
|
t.Errorf("SHA1 should be omitted: %s", uri)
|
|
}
|
|
if strings.Contains(uri, "digits") {
|
|
t.Errorf("digits=6 should be omitted: %s", uri)
|
|
}
|
|
if strings.Contains(uri, "period") {
|
|
t.Errorf("period=30 should be omitted: %s", uri)
|
|
}
|
|
}
|