github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/kbfs/libkbfs/crypto_common.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  	"crypto/rand"
     9  
    10  	"github.com/keybase/client/go/kbfs/data"
    11  	"github.com/keybase/client/go/kbfs/kbfsblock"
    12  	"github.com/keybase/client/go/kbfs/kbfscodec"
    13  	"github.com/keybase/client/go/kbfs/kbfscrypto"
    14  	"github.com/keybase/client/go/kbfs/kbfsmd"
    15  	"github.com/keybase/client/go/kbfs/tlf"
    16  	"github.com/pkg/errors"
    17  	"golang.org/x/crypto/nacl/box"
    18  )
    19  
    20  // CryptoCommon contains many of the function implementations need for
    21  // the Crypto interface, which can be reused by other implementations.
    22  type CryptoCommon struct {
    23  	codec               kbfscodec.Codec
    24  	blockCryptVersioner blockCryptVersioner
    25  }
    26  
    27  var _ cryptoPure = (*CryptoCommon)(nil)
    28  
    29  // MakeCryptoCommon returns a default CryptoCommon object.
    30  func MakeCryptoCommon(
    31  	codec kbfscodec.Codec,
    32  	blockCryptVersioner blockCryptVersioner) CryptoCommon {
    33  	return CryptoCommon{codec, blockCryptVersioner}
    34  }
    35  
    36  // MakeRandomTlfID implements the Crypto interface for CryptoCommon.
    37  func (c CryptoCommon) MakeRandomTlfID(t tlf.Type) (tlf.ID, error) {
    38  	return tlf.MakeRandomID(t)
    39  }
    40  
    41  // MakeRandomBranchID implements the Crypto interface for CryptoCommon.
    42  func (c CryptoCommon) MakeRandomBranchID() (kbfsmd.BranchID, error) {
    43  	return kbfsmd.MakeRandomBranchID()
    44  }
    45  
    46  // MakeTemporaryBlockID implements the Crypto interface for CryptoCommon.
    47  func (c CryptoCommon) MakeTemporaryBlockID() (kbfsblock.ID, error) {
    48  	return kbfsblock.MakeTemporaryID()
    49  }
    50  
    51  // MakeBlockRefNonce implements the Crypto interface for CryptoCommon.
    52  func (c CryptoCommon) MakeBlockRefNonce() (nonce kbfsblock.RefNonce, err error) {
    53  	return kbfsblock.MakeRefNonce()
    54  }
    55  
    56  // MakeRandomBlockCryptKeyServerHalf implements the Crypto interface
    57  // for CryptoCommon.
    58  func (c CryptoCommon) MakeRandomBlockCryptKeyServerHalf() (
    59  	kbfscrypto.BlockCryptKeyServerHalf, error) {
    60  	return kbfscrypto.MakeRandomBlockCryptKeyServerHalf()
    61  }
    62  
    63  // MakeRandomTLFEphemeralKeys implements the Crypto interface for
    64  // CryptoCommon.
    65  func (c CryptoCommon) MakeRandomTLFEphemeralKeys() (
    66  	kbfscrypto.TLFEphemeralPublicKey, kbfscrypto.TLFEphemeralPrivateKey,
    67  	error) {
    68  	return kbfscrypto.MakeRandomTLFEphemeralKeys()
    69  }
    70  
    71  // MakeRandomTLFKeys implements the Crypto interface for CryptoCommon.
    72  func (c CryptoCommon) MakeRandomTLFKeys() (kbfscrypto.TLFPublicKey,
    73  	kbfscrypto.TLFPrivateKey, kbfscrypto.TLFCryptKey, error) {
    74  	publicKey, privateKey, err := box.GenerateKey(rand.Reader)
    75  	if err != nil {
    76  		return kbfscrypto.TLFPublicKey{}, kbfscrypto.TLFPrivateKey{},
    77  			kbfscrypto.TLFCryptKey{}, errors.WithStack(err)
    78  	}
    79  
    80  	pubKey := kbfscrypto.MakeTLFPublicKey(*publicKey)
    81  	privKey := kbfscrypto.MakeTLFPrivateKey(*privateKey)
    82  
    83  	cryptKey, err := kbfscrypto.MakeRandomTLFCryptKey()
    84  	if err != nil {
    85  		return kbfscrypto.TLFPublicKey{}, kbfscrypto.TLFPrivateKey{},
    86  			kbfscrypto.TLFCryptKey{}, err
    87  	}
    88  
    89  	return pubKey, privKey, cryptKey, nil
    90  }
    91  
    92  // EncryptPrivateMetadata implements the Crypto interface for CryptoCommon.
    93  func (c CryptoCommon) EncryptPrivateMetadata(
    94  	pmd PrivateMetadata, key kbfscrypto.TLFCryptKey) (
    95  	encryptedPmd kbfscrypto.EncryptedPrivateMetadata, err error) {
    96  	encodedPmd, err := c.codec.Encode(pmd)
    97  	if err != nil {
    98  		return kbfscrypto.EncryptedPrivateMetadata{}, err
    99  	}
   100  
   101  	return kbfscrypto.EncryptEncodedPrivateMetadata(encodedPmd, key)
   102  }
   103  
   104  // DecryptPrivateMetadata implements the Crypto interface for CryptoCommon.
   105  func (c CryptoCommon) DecryptPrivateMetadata(
   106  	encryptedPmd kbfscrypto.EncryptedPrivateMetadata, key kbfscrypto.TLFCryptKey) (
   107  	PrivateMetadata, error) {
   108  	encodedPrivateMetadata, err := kbfscrypto.DecryptPrivateMetadata(
   109  		encryptedPmd, key)
   110  	if err != nil {
   111  		return PrivateMetadata{}, err
   112  	}
   113  
   114  	var pmd PrivateMetadata
   115  	err = c.codec.Decode(encodedPrivateMetadata, &pmd)
   116  	if err != nil {
   117  		return PrivateMetadata{}, err
   118  	}
   119  
   120  	return pmd, nil
   121  }
   122  
   123  // EncryptBlock implements the Crypto interface for CryptoCommon.
   124  func (c CryptoCommon) EncryptBlock(
   125  	block data.Block, tlfCryptKey kbfscrypto.TLFCryptKey,
   126  	blockServerHalf kbfscrypto.BlockCryptKeyServerHalf) (
   127  	plainSize int, encryptedBlock kbfscrypto.EncryptedBlock, err error) {
   128  	encodedBlock, err := c.codec.Encode(block)
   129  	if err != nil {
   130  		return -1, kbfscrypto.EncryptedBlock{}, err
   131  	}
   132  
   133  	paddedBlock, err := kbfscrypto.PadBlock(encodedBlock)
   134  	if err != nil {
   135  		return -1, kbfscrypto.EncryptedBlock{}, err
   136  	}
   137  
   138  	encryptedBlock, err =
   139  		kbfscrypto.EncryptPaddedEncodedBlock(
   140  			paddedBlock, tlfCryptKey, blockServerHalf,
   141  			c.blockCryptVersioner.BlockCryptVersion())
   142  	if err != nil {
   143  		return -1, kbfscrypto.EncryptedBlock{}, err
   144  	}
   145  
   146  	plainSize = len(encodedBlock)
   147  	return plainSize, encryptedBlock, nil
   148  }
   149  
   150  // DecryptBlock implements the Crypto interface for CryptoCommon.
   151  func (c CryptoCommon) DecryptBlock(
   152  	encryptedBlock kbfscrypto.EncryptedBlock,
   153  	tlfCryptKey kbfscrypto.TLFCryptKey,
   154  	blockServerHalf kbfscrypto.BlockCryptKeyServerHalf, block data.Block) error {
   155  	var paddedBlock []byte
   156  	paddedBlock, err := kbfscrypto.DecryptBlock(
   157  		encryptedBlock, tlfCryptKey, blockServerHalf)
   158  	if err != nil {
   159  		return err
   160  	}
   161  
   162  	encodedBlock, err := kbfscrypto.DepadBlock(paddedBlock)
   163  	if err != nil {
   164  		return err
   165  	}
   166  
   167  	err = c.codec.Decode(encodedBlock, &block)
   168  	if err != nil {
   169  		return errors.WithStack(BlockDecodeError{err})
   170  	}
   171  	return nil
   172  }