github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/teams/oracle.go (about)

     1  package teams
     2  
     3  import (
     4  	"github.com/keybase/client/go/libkb"
     5  	"github.com/keybase/client/go/protocol/keybase1"
     6  	"golang.org/x/crypto/nacl/box"
     7  )
     8  
     9  func TryDecryptWithTeamKey(mctx libkb.MetaContext, arg keybase1.TryDecryptWithTeamKeyArg) (ret []byte, err error) {
    10  	loadArg := keybase1.LoadTeamArg{
    11  		ID:          arg.TeamID,
    12  		Public:      arg.TeamID.IsPublic(),
    13  		ForceRepoll: false,
    14  		Refreshers: keybase1.TeamRefreshers{
    15  			NeedKeyGeneration: arg.MinGeneration,
    16  		},
    17  	}
    18  	team, err := Load(mctx.Ctx(), mctx.G(), loadArg)
    19  	if err != nil {
    20  		return nil, err
    21  	}
    22  
    23  	mctx.Debug("Loaded team %q, max key generation is %d", team.ID, team.Generation())
    24  
    25  	tryKeys := func(min keybase1.PerTeamKeyGeneration) (ret []byte, found bool, err error) {
    26  		if min == 0 {
    27  			// per team keys start from generation 1.
    28  			min = 1
    29  		}
    30  		for gen := team.Generation(); gen >= min; gen-- {
    31  			key, err := team.encryptionKeyAtGen(mctx.Ctx(), gen)
    32  			if err != nil {
    33  				mctx.Debug("Failed to get key gen %d: %v", gen, err)
    34  				switch err.(type) {
    35  				case libkb.NotFoundError:
    36  					continue
    37  				default:
    38  					return nil, false, err
    39  				}
    40  			}
    41  
    42  			mctx.Debug("Trying to unbox with key gen %d", gen)
    43  			decryptedData, ok := box.Open(nil, arg.EncryptedData, (*[24]byte)(&arg.Nonce),
    44  				(*[32]byte)(&arg.PeersPublicKey), (*[32]byte)(key.Private))
    45  			if !ok {
    46  				continue
    47  			}
    48  
    49  			mctx.Debug("Success! Decrypted using encryption key gen=%d", gen)
    50  			return decryptedData, true, nil
    51  		}
    52  
    53  		// No error, but didn't find the right key either.
    54  		return nil, false, nil
    55  	}
    56  
    57  	ret, found, err := tryKeys(arg.MinGeneration)
    58  	if err != nil {
    59  		// Error during key searching.
    60  		return nil, err
    61  	}
    62  	if found {
    63  		// Success - found the right key.
    64  		return ret, nil
    65  	}
    66  
    67  	mctx.Debug("Repolling team")
    68  
    69  	// Repoll the team and if we get more keys, try again.
    70  	loadArg.Refreshers = keybase1.TeamRefreshers{}
    71  	loadArg.ForceRepoll = true
    72  	team, err = Load(mctx.Ctx(), mctx.G(), loadArg)
    73  	if err != nil {
    74  		return nil, err
    75  	}
    76  	mctx.Debug("Reloaded team %q, max key generation is %d", team.ID, team.Generation())
    77  	ret, found, err = tryKeys(1)
    78  	if err != nil {
    79  		return nil, err
    80  	}
    81  	if found {
    82  		return ret, nil
    83  	}
    84  	return nil, libkb.DecryptionError{}
    85  }