github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/kbfs/libkbfs/crypto_local.go (about) 1 // Copyright 2016 Keybase Inc. All rights reserved. 2 // Use of this source code is governed by a BSD 3 // license that can be found in the LICENSE file. 4 5 package libkbfs 6 7 import ( 8 "github.com/keybase/client/go/kbfs/kbfscodec" 9 "github.com/keybase/client/go/kbfs/kbfscrypto" 10 "github.com/keybase/client/go/libkb" 11 "github.com/keybase/client/go/protocol/keybase1" 12 "github.com/pkg/errors" 13 "golang.org/x/net/context" 14 ) 15 16 type perTeamKeyPair struct { 17 privKey kbfscrypto.TLFPrivateKey 18 pubKey kbfscrypto.TLFPublicKey 19 } 20 21 type perTeamKeyPairs map[keybase1.PerTeamKeyGeneration]perTeamKeyPair 22 23 // CryptoLocal implements the Crypto interface by using a local 24 // signing key and a local crypt private key. 25 type CryptoLocal struct { 26 CryptoCommon 27 kbfscrypto.SigningKeySigner 28 cryptPrivateKey kbfscrypto.CryptPrivateKey 29 teamPrivateKeys map[keybase1.TeamID]perTeamKeyPairs 30 } 31 32 var _ Crypto = (*CryptoLocal)(nil) 33 34 // NewCryptoLocal constructs a new CryptoLocal instance with the given 35 // signing key. 36 func NewCryptoLocal(codec kbfscodec.Codec, 37 signingKey kbfscrypto.SigningKey, 38 cryptPrivateKey kbfscrypto.CryptPrivateKey, 39 blockCryptVersioner blockCryptVersioner) *CryptoLocal { 40 return &CryptoLocal{ 41 MakeCryptoCommon(codec, blockCryptVersioner), 42 kbfscrypto.SigningKeySigner{Key: signingKey}, 43 cryptPrivateKey, 44 make(map[keybase1.TeamID]perTeamKeyPairs), 45 } 46 } 47 48 // DecryptTLFCryptKeyClientHalf implements the Crypto interface for 49 // CryptoLocal. 50 func (c *CryptoLocal) DecryptTLFCryptKeyClientHalf(ctx context.Context, 51 publicKey kbfscrypto.TLFEphemeralPublicKey, 52 encryptedClientHalf kbfscrypto.EncryptedTLFCryptKeyClientHalf) ( 53 kbfscrypto.TLFCryptKeyClientHalf, error) { 54 return kbfscrypto.DecryptTLFCryptKeyClientHalf( 55 c.cryptPrivateKey, publicKey, encryptedClientHalf) 56 } 57 58 // DecryptTLFCryptKeyClientHalfAny implements the Crypto interface for 59 // CryptoLocal. 60 func (c *CryptoLocal) DecryptTLFCryptKeyClientHalfAny(ctx context.Context, 61 keys []EncryptedTLFCryptKeyClientAndEphemeral, _ bool) ( 62 clientHalf kbfscrypto.TLFCryptKeyClientHalf, index int, err error) { 63 if len(keys) == 0 { 64 return kbfscrypto.TLFCryptKeyClientHalf{}, -1, 65 errors.WithStack(NoKeysError{}) 66 } 67 var firstNonDecryptionErr error 68 for i, k := range keys { 69 clientHalf, err := c.DecryptTLFCryptKeyClientHalf( 70 ctx, k.EPubKey, k.ClientHalf) 71 if err != nil { 72 _, isDecryptionError := 73 errors.Cause(err).(libkb.DecryptionError) 74 if firstNonDecryptionErr == nil && !isDecryptionError { 75 firstNonDecryptionErr = err 76 } 77 continue 78 } 79 return clientHalf, i, nil 80 } 81 // This is to mimic the behavior in 82 // CryptoClient.DecryptTLFCryptKeyClientHalfAny, which is to, 83 // if all calls to prepareTLFCryptKeyClientHalf failed, return 84 // the first prep error, and otherwise to return the error 85 // from the service, which is usually libkb.DecryptionError. 86 if firstNonDecryptionErr != nil { 87 return kbfscrypto.TLFCryptKeyClientHalf{}, -1, 88 firstNonDecryptionErr 89 } 90 return kbfscrypto.TLFCryptKeyClientHalf{}, -1, 91 errors.WithStack(libkb.DecryptionError{}) 92 } 93 94 func (c *CryptoLocal) pubKeyForTeamKeyGeneration( 95 teamID keybase1.TeamID, keyGen keybase1.PerTeamKeyGeneration) ( 96 pubKey kbfscrypto.TLFPublicKey, err error) { 97 if c.teamPrivateKeys[teamID] == nil { 98 c.teamPrivateKeys[teamID] = make(perTeamKeyPairs) 99 } 100 101 teamKeys := c.teamPrivateKeys[teamID] 102 kp, ok := teamKeys[keyGen] 103 // If a key pair doesn't exist yet for this keygen, generate a 104 // random one. 105 if !ok { 106 pubKey, privKey, _, err := c.MakeRandomTLFKeys() 107 if err != nil { 108 return kbfscrypto.TLFPublicKey{}, err 109 } 110 kp = perTeamKeyPair{privKey, pubKey} 111 c.teamPrivateKeys[teamID][keyGen] = kp 112 } 113 114 return kp.pubKey, nil 115 } 116 117 // DecryptTeamMerkleLeaf implements the Crypto interface for 118 // CryptoLocal. 119 func (c *CryptoLocal) DecryptTeamMerkleLeaf( 120 ctx context.Context, teamID keybase1.TeamID, 121 publicKey kbfscrypto.TLFEphemeralPublicKey, 122 encryptedMerkleLeaf kbfscrypto.EncryptedMerkleLeaf, 123 minKeyGen keybase1.PerTeamKeyGeneration) (decryptedData []byte, err error) { 124 perTeamKeys := c.teamPrivateKeys[teamID] 125 maxKeyGen := keybase1.PerTeamKeyGeneration(len(perTeamKeys)) 126 for i := minKeyGen; i <= maxKeyGen; i++ { 127 decryptedData, err := kbfscrypto.DecryptMerkleLeaf( 128 perTeamKeys[i].privKey, publicKey, encryptedMerkleLeaf) 129 if err == nil { 130 return decryptedData, nil 131 } 132 } 133 134 return nil, errors.WithStack(libkb.DecryptionError{}) 135 } 136 137 // Shutdown implements the Crypto interface for CryptoLocal. 138 func (c *CryptoLocal) Shutdown() {}