Why: collaborative KeePass use needs one arbiter of "who wrote last" that never sees a master password, plus access control that follows an org chart. What: stdlib-only Go server. Metadata is a single JSON document with one writer and atomic commit; KDBX payloads are versioned blobs on disk. Access comes from a group tree where a grant on a group reaches every member below it. Login is password+TOTP, invite links, or OIDC through a browser-approved device flow. Pushes carry If-Match and are arbitrated by a per-database merge strategy (server-wins by default). Updates are pushed to clients over SSE. Proved: go test ./internal/... covers RFC 6238 vectors, ACL inheritance and isolation, store rollback, blob pruning, every push verdict, and an end-to-end HTTP pass over login, conflict, force, read-only grants, invite redemption, TOTP enrolment, device login and the event stream.
47 lines
1.0 KiB
Go
47 lines
1.0 KiB
Go
package totp
|
|
|
|
import (
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
// RFC 6238 appendix B, SHA1 test vectors for the ASCII key "12345678901234567890".
|
|
func TestRFC6238Vectors(t *testing.T) {
|
|
const secret = "GEZDGNBVGY3TQOJQGEZDGNBVGY3TQOJQ" // base32 of the RFC key
|
|
for _, tc := range []struct {
|
|
unix int64
|
|
want string
|
|
}{
|
|
{59, "287082"},
|
|
{1111111109, "081804"},
|
|
{1111111111, "050471"},
|
|
{1234567890, "005924"},
|
|
{2000000000, "279037"},
|
|
} {
|
|
got, err := Code(secret, time.Unix(tc.unix, 0))
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if got != tc.want {
|
|
t.Errorf("Code at %d = %s, want %s", tc.unix, got, tc.want)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestCheckAcceptsDriftAndRejectsJunk(t *testing.T) {
|
|
s := NewSecret()
|
|
now := time.Now()
|
|
c, _ := Code(s, now)
|
|
if !Check(s, c, now.Add(29*time.Second)) {
|
|
t.Fatal("code within drift window rejected")
|
|
}
|
|
if Check(s, c, now.Add(5*time.Minute)) {
|
|
t.Fatal("stale code accepted")
|
|
}
|
|
for _, bad := range []string{"", "12345", "abcdef", "1234567"} {
|
|
if Check(s, bad, now) {
|
|
t.Fatalf("junk code %q accepted", bad)
|
|
}
|
|
}
|
|
}
|