github.com/keybase/client/go@v0.0.0-20240520164431-4f512a4c85a3/teams/oracle_test.go (about) 1 package teams 2 3 import ( 4 "context" 5 "testing" 6 7 "github.com/keybase/client/go/kbtest" 8 "github.com/keybase/client/go/libkb" 9 keybase1 "github.com/keybase/client/go/protocol/keybase1" 10 "github.com/stretchr/testify/require" 11 "golang.org/x/crypto/nacl/box" 12 ) 13 14 func encryptWithTeamKey(t *testing.T, team *Team, data []byte, nonce [24]byte, 15 gen keybase1.PerTeamKeyGeneration) (ciphertext []byte, pubkey libkb.NaclDHKeyPublic) { 16 kp, err := team.encryptionKeyAtGen(context.Background(), gen) 17 require.NoError(t, err) 18 ciphertext = box.Seal(nil, data, &nonce, (*[32]byte)(&kp.Public), (*[32]byte)(kp.Private)) 19 pubkey = kp.Public 20 return ciphertext, pubkey 21 } 22 23 func TestTeamUnboxOracle(t *testing.T) { 24 tc := SetupTest(t, "team", 1) 25 defer tc.Cleanup() 26 27 _, err := kbtest.CreateAndSignupFakeUser("team", tc.G) 28 require.NoError(t, err) 29 30 teamname := createTeam(tc) 31 t.Logf("Created team %s", teamname) 32 33 team, err := Load(context.Background(), tc.G, keybase1.LoadTeamArg{ 34 Name: teamname, 35 ForceRepoll: true, 36 }) 37 require.NoError(t, err) 38 39 require.NoError(t, RotateKeyVisible(context.Background(), tc.G, team.ID)) 40 require.NoError(t, RotateKeyVisible(context.Background(), tc.G, team.ID)) 41 42 team, err = Load(context.Background(), tc.G, keybase1.LoadTeamArg{ 43 Name: teamname, 44 ForceRepoll: true, 45 }) 46 require.NoError(t, err) 47 48 mctx := libkb.NewMetaContextBackground(tc.G) 49 50 clearText := []byte{0, 1, 2, 3, 4, 5} 51 nonce := [24]byte{6, 7, 8, 9, 10} 52 buf, pub := encryptWithTeamKey(t, team, clearText, nonce, keybase1.PerTeamKeyGeneration(2)) 53 arg := keybase1.TryDecryptWithTeamKeyArg{ 54 TeamID: team.ID, 55 EncryptedData: buf, 56 Nonce: nonce, 57 PeersPublicKey: (keybase1.BoxPublicKey)(pub), 58 } 59 ret, err := TryDecryptWithTeamKey(mctx, arg) 60 require.NoError(t, err) 61 require.ElementsMatch(t, ret, clearText) 62 63 // Try again with MinGeneration argument. 64 arg.MinGeneration = keybase1.PerTeamKeyGeneration(2) 65 ret, err = TryDecryptWithTeamKey(mctx, arg) 66 require.NoError(t, err) 67 require.ElementsMatch(t, ret, clearText) 68 69 // Do same encryption scheme but with generation 1. 70 buf, pub = encryptWithTeamKey(t, team, clearText, nonce, keybase1.PerTeamKeyGeneration(1)) 71 arg.EncryptedData = buf 72 arg.MinGeneration = keybase1.PerTeamKeyGeneration(0) // default 73 arg.PeersPublicKey = (keybase1.BoxPublicKey)(pub) 74 ret, err = TryDecryptWithTeamKey(mctx, arg) 75 require.NoError(t, err) 76 require.ElementsMatch(t, ret, clearText) 77 } 78 79 func TestTeamOracleRepolling(t *testing.T) { 80 fus, tcs, cleanup := setupNTests(t, 2) 81 defer cleanup() 82 83 teamName, teamID := createTeam2(*tcs[0]) 84 t.Logf("Created team %s", teamName) 85 86 _, err := AddMember(context.Background(), tcs[0].G, teamName.String(), fus[1].Username, keybase1.TeamRole_ADMIN, nil) 87 require.NoError(t, err) 88 89 // Issue a team load as user 1 to get this version of the team to cache. 90 _, err = Load(context.Background(), tcs[1].G, keybase1.LoadTeamArg{ 91 Name: teamName.String(), 92 ForceRepoll: true, 93 }) 94 require.NoError(t, err) 95 96 // Rotate team as user 0 and encrypt with key 2. 97 require.NoError(t, RotateKeyVisible(context.Background(), tcs[0].G, teamID)) 98 team, err := Load(context.Background(), tcs[0].G, keybase1.LoadTeamArg{ 99 Name: teamName.String(), 100 ForceRepoll: true, 101 }) 102 require.NoError(t, err) 103 104 clearText := []byte{0, 1, 2, 3, 4, 5} 105 nonce := [24]byte{6, 7, 8, 9, 10} 106 buf, pub := encryptWithTeamKey(t, team, clearText, nonce, keybase1.PerTeamKeyGeneration(2)) 107 108 // Try to decrypt as user 1. User 1 does not have team with gen=2 109 // in cache, so `TryDecryptWithTeamKey` will have to take slower 110 // repoll path. 111 arg := keybase1.TryDecryptWithTeamKeyArg{ 112 TeamID: teamID, 113 EncryptedData: buf, 114 Nonce: nonce, 115 PeersPublicKey: (keybase1.BoxPublicKey)(pub), 116 } 117 ret, err := TryDecryptWithTeamKey(libkb.NewMetaContextBackground(tcs[1].G), arg) 118 require.NoError(t, err) 119 require.ElementsMatch(t, ret, clearText) 120 }