tka: implement State and applying AUMs

Signed-off-by: Tom DNetto <tom@tailscale.com>
This commit is contained in:
Tom DNetto
2022-07-06 13:15:13 -07:00
committed by Tom
parent 1cfd96cdc2
commit 3709074e55
5 changed files with 677 additions and 42 deletions

View File

@ -10,10 +10,12 @@ import (
"github.com/fxamacker/cbor/v2"
"github.com/google/go-cmp/cmp"
"golang.org/x/crypto/blake2s"
)
func TestSerialization(t *testing.T) {
uint2 := uint(2)
var fakeAUMHash AUMHash
tcs := []struct {
Name string
@ -94,44 +96,45 @@ func TestSerialization(t *testing.T) {
0x04, // |- major type 0 (int), value 4 (byte 4)
},
},
// TODO(tom): Uncomment once a future PR brings in the State type.
// {
// "Checkpoint",
// AUM{MessageKind: AUMCheckpoint, PrevAUMHash: []byte{1, 2}, State: &State{
// LastAUMHash: []byte{3, 4},
// Keys: []Key{
// {Kind: Key25519, Public: []byte{5, 6}},
// },
// }},
// []byte{
// 0xa3, // major type 5 (map), 3 items
// 0x01, // |- major type 0 (int), value 1 (first key, MessageKind)
// 0x06, // |- major type 0 (int), value 6 (first value, AUMCheckpoint)
// 0x02, // |- major type 0 (int), value 2 (second key, PrevAUMHash)
// 0x42, // |- major type 2 (byte string), 2 items (second value)
// 0x01, // |- major type 0 (int), value 1 (byte 1)
// 0x02, // |- major type 0 (int), value 2 (byte 2)
// 0x05, // |- major type 0 (int), value 5 (third key, State)
// 0xa3, // |- major type 5 (map), 3 items (third value, State type)
// 0x01, // |- major type 0 (int), value 1 (first key, LastAUMHash)
// 0x42, // |- major type 2 (byte string), 2 items (first value)
// 0x03, // |- major type 0 (int), value 3 (byte 3)
// 0x04, // |- major type 0 (int), value 4 (byte 4)
// 0x02, // |- major type 0 (int), value 2 (second key, DisablementSecrets)
// 0xf6, // |- major type 7 (val), value null (second value, nil)
// 0x03, // |- major type 0 (int), value 3 (third key, Keys)
// 0x81, // |- major type 4 (array), value 1 (one item in array)
// 0xa3, // |- major type 5 (map), 3 items (Key type)
// 0x01, // |- major type 0 (int), value 1 (first key, Kind)
// 0x01, // |- major type 0 (int), value 1 (first value, Key25519)
// 0x02, // |- major type 0 (int), value 2 (second key, Votes)
// 0x00, // |- major type 0 (int), value 0 (second value, 0)
// 0x03, // |- major type 0 (int), value 3 (third key, Public)
// 0x42, // |- major type 2 (byte string), 2 items (third value)
// 0x05, // |- major type 0 (int), value 5 (byte 5)
// 0x06, // |- major type 0 (int), value 6 (byte 6)
// },
// },
{
"Checkpoint",
AUM{MessageKind: AUMCheckpoint, PrevAUMHash: []byte{1, 2}, State: &State{
LastAUMHash: &fakeAUMHash,
Keys: []Key{
{Kind: Key25519, Public: []byte{5, 6}},
},
}},
append(
append([]byte{
0xa3, // major type 5 (map), 3 items
0x01, // |- major type 0 (int), value 1 (first key, MessageKind)
0x06, // |- major type 0 (int), value 6 (first value, AUMCheckpoint)
0x02, // |- major type 0 (int), value 2 (second key, PrevAUMHash)
0x42, // |- major type 2 (byte string), 2 items (second value)
0x01, // |- major type 0 (int), value 1 (byte 1)
0x02, // |- major type 0 (int), value 2 (byte 2)
0x05, // |- major type 0 (int), value 5 (third key, State)
0xa3, // |- major type 5 (map), 3 items (third value, State type)
0x01, // |- major type 0 (int), value 1 (first key, LastAUMHash)
0x58, 0x20, // |- major type 2 (byte string), 32 items (first value)
},
bytes.Repeat([]byte{0}, 32)...),
[]byte{
0x02, // |- major type 0 (int), value 2 (second key, DisablementSecrets)
0xf6, // |- major type 7 (val), value null (second value, nil)
0x03, // |- major type 0 (int), value 3 (third key, Keys)
0x81, // |- major type 4 (array), value 1 (one item in array)
0xa3, // |- major type 5 (map), 3 items (Key type)
0x01, // |- major type 0 (int), value 1 (first key, Kind)
0x01, // |- major type 0 (int), value 1 (first value, Key25519)
0x02, // |- major type 0 (int), value 2 (second key, Votes)
0x00, // |- major type 0 (int), value 0 (second value, 0)
0x03, // |- major type 0 (int), value 3 (third key, Public)
0x42, // |- major type 2 (byte string), 2 items (third value)
0x05, // |- major type 0 (int), value 5 (byte 5)
0x06, // |- major type 0 (int), value 6 (byte 6)
}...),
},
{
"Signature",
AUM{MessageKind: AUMAddKey, Signatures: []Signature{{KeyID: []byte{1}}}},
@ -171,6 +174,77 @@ func TestSerialization(t *testing.T) {
}
}
func TestAUMWeight(t *testing.T) {
var fakeKeyID [blake2s.Size]byte
testingRand(t, 1).Read(fakeKeyID[:])
pub, _ := testingKey25519(t, 1)
key := Key{Kind: Key25519, Public: pub, Votes: 2}
pub, _ = testingKey25519(t, 2)
key2 := Key{Kind: Key25519, Public: pub, Votes: 2}
tcs := []struct {
Name string
AUM AUM
State State
Want uint
}{
{
"Empty",
AUM{},
State{},
0,
},
{
"Key unknown",
AUM{
Signatures: []Signature{{KeyID: fakeKeyID[:]}},
},
State{},
0,
},
{
"Unary key",
AUM{
Signatures: []Signature{{KeyID: key.ID()}},
},
State{
Keys: []Key{key},
},
2,
},
{
"Multiple keys",
AUM{
Signatures: []Signature{{KeyID: key.ID()}, {KeyID: key2.ID()}},
},
State{
Keys: []Key{key, key2},
},
4,
},
{
"Double use",
AUM{
Signatures: []Signature{{KeyID: key.ID()}, {KeyID: key.ID()}},
},
State{
Keys: []Key{key},
},
2,
},
}
for _, tc := range tcs {
t.Run(tc.Name, func(t *testing.T) {
got := tc.AUM.Weight(tc.State)
if got != tc.Want {
t.Errorf("Weight() = %d, want %d", got, tc.Want)
}
})
}
}
func TestAUMHashes(t *testing.T) {
// .Hash(): a hash over everything.
// .SigHash(): a hash over everything except the signatures.