Files

122 lines
3.7 KiB
Go

package credential
import (
"bytes"
"crypto/sha256"
"encoding/base64"
"strings"
"testing"
"github.com/aritmolab/thothii/tools/dwh-auth/internal/record"
)
func TestGenerateProducesCanonicalV1Material(t *testing.T) {
random := bytes.NewReader(bytes.Repeat([]byte{0x7f}, 44))
material, err := Generate(random)
if err != nil {
t.Fatalf("Generate() error = %v", err)
}
wantValue := strings.Join([]string{
Prefix,
"f39_f39_f39_f39_",
"f39_f39_f39_f39_f39_f39_f39_f39_f39_f39_f38",
}, ".")
if got, want := string(material.Value), wantValue; got != want {
t.Fatalf("Value = %q, want %q", got, want)
}
if got, want := len(material.Value), 70; got != want {
t.Fatalf("len(Value) = %d, want %d", got, want)
}
if got, want := material.KeyID, "f39_f39_f39_f39_"; got != want {
t.Fatalf("KeyID = %q, want %q", got, want)
}
segments := strings.Split(string(material.Value), ".")
if got, want := len(segments), 3; got != want {
t.Fatalf("segment count = %d, want %d", got, want)
}
if got, want := segments[0], Prefix; got != want {
t.Fatalf("prefix = %q, want %q", got, want)
}
if got, want := len(segments[1]), KeyIDEncodedLength; got != want {
t.Fatalf("key ID length = %d, want %d", got, want)
}
if got, want := len(segments[2]), SecretEncodedLength; got != want {
t.Fatalf("secret length = %d, want %d", got, want)
}
secret, err := base64.RawURLEncoding.DecodeString(segments[2])
if err != nil {
t.Fatalf("DecodeString(secret) error = %v", err)
}
if got, want := len(secret), 32; got != want {
t.Fatalf("decoded secret length = %d, want %d", got, want)
}
wantDigest := sha256.Sum256(material.Value)
if material.Digest != record.Digest(wantDigest) {
t.Fatalf("Digest = %x, want %x", material.Digest, wantDigest)
}
}
func TestVerifyV1AcceptsGeneratedMaterialAndRejectsChangedByte(t *testing.T) {
material, err := Generate(bytes.NewReader(bytes.Repeat([]byte{0x01}, 44)))
if err != nil {
t.Fatalf("Generate() error = %v", err)
}
if keyID, ok := VerifyV1(material.Value, material.Digest); !ok || keyID != material.KeyID {
t.Fatalf("VerifyV1() = (%q, %t), want (%q, true)", keyID, ok, material.KeyID)
}
changed := append([]byte(nil), material.Value...)
changed[len(changed)-1] ^= 1
if keyID, ok := VerifyV1(changed, material.Digest); ok || keyID != "" {
t.Fatalf("VerifyV1(changed) = (%q, %t), want (\"\", false)", keyID, ok)
}
}
func TestVerifyV1RejectsNonCanonicalValues(t *testing.T) {
material, err := Generate(bytes.NewReader(bytes.Repeat([]byte{0x02}, 44)))
if err != nil {
t.Fatalf("Generate() error = %v", err)
}
for _, value := range [][]byte{
append(append([]byte(nil), material.Value...), ','),
[]byte(string(material.Value) + "," + string(material.Value)),
[]byte(string(material.Value) + "." + material.KeyID),
[]byte(string(material.Value) + "="),
[]byte(" " + string(material.Value)),
bytes.Repeat([]byte{'a'}, MaxHeaderBytes+1),
} {
if keyID, ok := VerifyV1(value, material.Digest); ok || keyID != "" {
t.Fatalf("VerifyV1(%q) = (%q, %t), want (\"\", false)", value, keyID, ok)
}
}
}
func TestVerifyLegacyHashesOpaqueRawValueWithoutV1Parsing(t *testing.T) {
value := []byte("legacy opaque value /:[]")
sum := sha256.Sum256(value)
if !VerifyLegacy(value, record.Digest(sum)) {
t.Fatal("VerifyLegacy() = false, want true")
}
if VerifyLegacy([]byte("thtdwh_v1.not-a-valid-v1"), record.Digest(sum)) {
t.Fatal("VerifyLegacy() accepted a different raw value")
}
}
func TestVerifyLegacyRejectsInvalidOpaqueValues(t *testing.T) {
sum := sha256.Sum256([]byte("legacy"))
for _, value := range [][]byte{
nil,
bytes.Repeat([]byte{'a'}, MaxHeaderBytes+1),
[]byte("bad\nvalue"),
} {
if VerifyLegacy(value, record.Digest(sum)) {
t.Fatalf("VerifyLegacy(%q) = true, want false", value)
}
}
}