package backup import ( "bytes" "os" "path/filepath" "testing" ) func TestPasswordArchive(t *testing.T) { home := t.TempDir() dir := t.TempDir() if err := os.WriteFile(filepath.Join(home, ".credentials.yaml"), []byte("secret"), 0600); err != nil { t.Fatal(err) } first, second := filepath.Join(dir, "first"), filepath.Join(dir, "second") for _, path := range []string{first, second} { if err := CreateWithPassword(home, path, "old-password", Metadata{DSHVersion: "test"}); err != nil { t.Fatal(err) } } a, _ := os.ReadFile(first) b, _ := os.ReadFile(second) if bytes.Equal(a[:len(passwordMagic)+16], b[:len(passwordMagic)+16]) { t.Fatal("reused salt") } if bytes.Contains(a, []byte("secret")) { t.Fatal("plaintext") } if _, _, err := Prepare(first, "wrong-password", nil); err == nil { t.Fatal("accepted wrong password") } restore, cleanup, err := Prepare(first, "old-password", nil) if err != nil { t.Fatal(err) } defer cleanup() destination := t.TempDir() if err := restore(destination); err != nil { t.Fatal(err) } restored, _ := os.ReadFile(filepath.Join(destination, ".credentials.yaml")) if string(restored) != "secret" { t.Fatal(string(restored)) } a[len(passwordMagic)] ^= 1 os.WriteFile(second, a, 0600) if _, _, err := Prepare(second, "old-password", nil); err == nil { t.Fatal("accepted altered salt") } legacy := filepath.Join(dir, "legacy") key := bytes.Repeat([]byte{9}, 32) if err := Create(home, legacy, key); err != nil { t.Fatal(err) } restore, legacyCleanup, err := Prepare(legacy, "", key) if err != nil { t.Fatal(err) } defer legacyCleanup() if err := restore(t.TempDir()); err != nil { t.Fatal(err) } os.WriteFile(second, []byte(passwordMagic), 0600) if _, _, err := Prepare(second, "old-password", nil); err == nil { t.Fatal("accepted truncated header") } f, err := os.Create(second) if err != nil { t.Fatal(err) } f.Truncate(MaxEncryptedBytes + 1) f.Close() if _, _, err := Prepare(second, "old-password", nil); err == nil { t.Fatal("accepted oversized file") } }