package accesskey_test import ( "errors" "maps" "slices" "testing" datekeys "g.activething.com/go/DateKeys" "g.activething.com/go/DateKeys/accesskey" "g.activething.com/go/DateKeys/internal/cbortest" ) // Spec §41, §43, §58: BODY_CBOR is a closed map with strictly ascending // unsigned integer keys and every required key, and verification_metadata is // the closed map {0: capsule_digest}. func TestDecodeBodyStructure(t *testing.T) { good, _ := loadDKK(t, "time_and_key_portable") body, err := cbortest.UnmarshalMap(good[accesskey.PreludeSize:]) if err != nil { t.Fatal(err) } encode := func(v any) []byte { b, err := cbortest.Marshal(v) if err != nil { t.Fatal(err) } return b } with := func(edit func(m map[uint64]any)) []byte { m := maps.Clone(body) edit(m) return encode(m) } // Keys 4 and 5 in each other's place. var swapped cbortest.Pairs for _, k := range slices.Sorted(maps.Keys(body)) { switch k { case 4: k = 5 case 5: k = 4 } swapped = append(swapped, k, body[k]) } a, b := []any{map[uint64]any{0: "a", 1: uint64(1)}}, []any{map[uint64]any{0: "b", 1: uint64(1)}} for name, in := range map[string][]byte{ "missing credential_id": with(func(m map[uint64]any) { delete(m, 2) }), "missing access_material": with(func(m map[uint64]any) { delete(m, 5) }), "credential_id as text": with(func(m map[uint64]any) { m[2] = "x" }), "ten entries": with(func(m map[uint64]any) { m[7], m[8], m[9], m[10] = a, b, "x", "y" }), "keys 4 and 5 swapped": encode(swapped), "text key": encode(cbortest.Pairs{uint64(0), accesskey.TypeTag, uint64(1), uint64(1), "2", make([]byte, 16)}), "verification with key 1": with(func(m map[uint64]any) { m[6] = map[uint64]any{1: make([]byte, 32)} }), "verification with two keys": with(func(m map[uint64]any) { m[6] = map[uint64]any{0: make([]byte, 32), 1: uint64(0)} }), "verification as a byte string": with(func(m map[uint64]any) { m[6] = make([]byte, 32) }), "verification with a text key": with(func(m map[uint64]any) { m[6] = cbortest.Pairs{"0", make([]byte, 32)} }), "capsule_digest of type text": with(func(m map[uint64]any) { m[6] = map[uint64]any{0: "digest"} }), "capsule_digest of 33 bytes": with(func(m map[uint64]any) { m[6] = map[uint64]any{0: make([]byte, 33)} }), "access_type of type byte string": with(func(m map[uint64]any) { m[4] = []byte("x25519") }), } { if _, err := accesskey.DecodeBody(in); !errors.Is(err, datekeys.ErrNonCanonicalCBOR) { t.Errorf("%s: %v", name, err) } } }