github.com/keybase/client/go@v0.0.0-20240309051027-028f7c731f8b/kbfs/kbfscrypto/encrypted_data.go (about)

     1  // Copyright 2017 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 kbfscrypto
     6  
     7  import (
     8  	"bytes"
     9  	"encoding/hex"
    10  	"fmt"
    11  	"reflect"
    12  
    13  	"github.com/keybase/client/go/kbfs/cache"
    14  	"github.com/keybase/client/go/kbfs/kbfscodec"
    15  	"github.com/keybase/client/go/kbfs/kbfshash"
    16  	"github.com/keybase/client/go/libkb"
    17  	"github.com/pkg/errors"
    18  	"golang.org/x/crypto/nacl/box"
    19  	"golang.org/x/crypto/nacl/secretbox"
    20  )
    21  
    22  // EncryptionVer denotes a version for the encryption method.
    23  type EncryptionVer int
    24  
    25  const (
    26  	// EncryptionSecretbox is the encryption version that uses
    27  	// nacl/secretbox or nacl/box.
    28  	EncryptionSecretbox EncryptionVer = 1
    29  	// EncryptionSecretboxWithKeyNonce is the encryption version that
    30  	// uses nacl/secretbox or nacl/box, with a nonce derived from a
    31  	// secret key.
    32  	EncryptionSecretboxWithKeyNonce EncryptionVer = 2
    33  )
    34  
    35  func (v EncryptionVer) String() string {
    36  	switch v {
    37  	case EncryptionSecretbox:
    38  		return "EncryptionSecretbox"
    39  	case EncryptionSecretboxWithKeyNonce:
    40  		return "EncryptionSecretboxWithKeyNonce"
    41  	default:
    42  		return fmt.Sprintf("EncryptionVer(%d)", v)
    43  	}
    44  }
    45  
    46  // ToHashType returns the type of the hash that should be used for the
    47  // given encryption version.
    48  func (v EncryptionVer) ToHashType() kbfshash.HashType {
    49  	switch v {
    50  	case EncryptionSecretbox:
    51  		return kbfshash.SHA256Hash
    52  	case EncryptionSecretboxWithKeyNonce:
    53  		return kbfshash.SHA256HashV2
    54  	default:
    55  		return kbfshash.InvalidHash
    56  	}
    57  }
    58  
    59  // encryptedData is encrypted data with a nonce and a version.
    60  type encryptedData struct {
    61  	// Exported only for serialization purposes. Should only be
    62  	// used by implementations of Crypto.
    63  	Version       EncryptionVer `codec:"v"`
    64  	EncryptedData []byte        `codec:"e"`
    65  	Nonce         []byte        `codec:"n"`
    66  }
    67  
    68  // Size implements the cache.Measurable interface.
    69  func (ed encryptedData) Size() int {
    70  	return cache.IntSize /* ed.Version */ +
    71  		cache.PtrSize + len(ed.EncryptedData) + cache.PtrSize + len(ed.Nonce)
    72  }
    73  
    74  func (ed encryptedData) String() string {
    75  	if reflect.DeepEqual(ed, encryptedData{}) {
    76  		return "EncryptedData{}"
    77  	}
    78  	return fmt.Sprintf("%s{data=%s, nonce=%s}",
    79  		ed.Version, hex.EncodeToString(ed.EncryptedData),
    80  		hex.EncodeToString(ed.Nonce))
    81  }
    82  
    83  func (ed encryptedData) Nonce24() (nonce [24]byte, err error) {
    84  	if len(ed.Nonce) != len(nonce) {
    85  		return nonce, errors.WithStack(InvalidNonceError{ed.Nonce})
    86  	}
    87  	copy(nonce[:], ed.Nonce)
    88  	return nonce, nil
    89  }
    90  
    91  // encryptDataWithNonce encrypts the given data with the given
    92  // symmetric key and nonce.
    93  func encryptDataWithNonce(
    94  	data []byte, key [32]byte, nonce [24]byte, ver EncryptionVer) (
    95  	encryptedData, error) {
    96  	sealedData := secretbox.Seal(nil, data, &nonce, &key)
    97  
    98  	return encryptedData{
    99  		Version:       ver,
   100  		Nonce:         nonce[:],
   101  		EncryptedData: sealedData,
   102  	}, nil
   103  }
   104  
   105  // encryptData encrypts the given data with the given symmetric key.
   106  func encryptData(data []byte, key [32]byte) (encryptedData, error) {
   107  	var nonce [24]byte
   108  	err := RandRead(nonce[:])
   109  	if err != nil {
   110  		return encryptedData{}, err
   111  	}
   112  
   113  	return encryptDataWithNonce(data, key, nonce, EncryptionSecretbox)
   114  }
   115  
   116  // decryptData decrypts the given encrypted data with the given
   117  // symmetric key and nonce.
   118  func decryptData(
   119  	encryptedData encryptedData, key [32]byte, nonce [24]byte) ([]byte, error) {
   120  	switch encryptedData.Version {
   121  	case EncryptionSecretbox:
   122  		// We're good, no nonce check needed.
   123  	case EncryptionSecretboxWithKeyNonce:
   124  		if !bytes.Equal(nonce[:], encryptedData.Nonce) {
   125  			return nil, errors.WithStack(InvalidNonceError{encryptedData.Nonce})
   126  		}
   127  	default:
   128  		return nil, errors.WithStack(
   129  			UnknownEncryptionVer{encryptedData.Version})
   130  	}
   131  
   132  	decryptedData, ok := secretbox.Open(
   133  		nil, encryptedData.EncryptedData, &nonce, &key)
   134  	if !ok {
   135  		return nil, errors.WithStack(
   136  			libkb.DecryptionError{Cause: libkb.ErrorCause{Err: errors.New("Cannot open secret box")}})
   137  	}
   138  
   139  	return decryptedData, nil
   140  }
   141  
   142  // EncryptedTLFCryptKeyClientHalf is an encrypted
   143  // TLFCryptKeyClientHalf object.
   144  type EncryptedTLFCryptKeyClientHalf struct {
   145  	encryptedData
   146  }
   147  
   148  // EncryptTLFCryptKeyClientHalf encrypts a TLFCryptKeyClientHalf
   149  // using both a TLF's ephemeral private key and a device pubkey.
   150  func EncryptTLFCryptKeyClientHalf(
   151  	privateKey TLFEphemeralPrivateKey, publicKey CryptPublicKey,
   152  	clientHalf TLFCryptKeyClientHalf) (
   153  	encryptedClientHalf EncryptedTLFCryptKeyClientHalf, err error) {
   154  	var nonce [24]byte
   155  	err = RandRead(nonce[:])
   156  	if err != nil {
   157  		return EncryptedTLFCryptKeyClientHalf{}, err
   158  	}
   159  
   160  	keypair, err := libkb.ImportKeypairFromKID(publicKey.KID())
   161  	if err != nil {
   162  		return EncryptedTLFCryptKeyClientHalf{}, errors.WithStack(err)
   163  	}
   164  
   165  	dhKeyPair, ok := keypair.(libkb.NaclDHKeyPair)
   166  	if !ok {
   167  		return EncryptedTLFCryptKeyClientHalf{}, errors.WithStack(
   168  			libkb.KeyCannotEncryptError{})
   169  	}
   170  
   171  	clientHalfData := clientHalf.Data()
   172  	privateKeyData := privateKey.Data()
   173  	encryptedBytes := box.Seal(nil, clientHalfData[:], &nonce, (*[32]byte)(&dhKeyPair.Public), &privateKeyData)
   174  
   175  	return EncryptedTLFCryptKeyClientHalf{
   176  		encryptedData{
   177  			Version:       EncryptionSecretbox,
   178  			EncryptedData: encryptedBytes,
   179  			Nonce:         nonce[:],
   180  		},
   181  	}, nil
   182  }
   183  
   184  // EncryptedPrivateMetadata is an encrypted PrivateMetadata object.
   185  type EncryptedPrivateMetadata struct {
   186  	encryptedData
   187  }
   188  
   189  // EncryptEncodedPrivateMetadata encrypts an encoded PrivateMetadata
   190  // object.
   191  func EncryptEncodedPrivateMetadata(encodedPrivateMetadata []byte, key TLFCryptKey) (
   192  	encryptedPrivateMetadata EncryptedPrivateMetadata, err error) {
   193  	encryptedData, err := encryptData(encodedPrivateMetadata, key.Data())
   194  	if err != nil {
   195  		return EncryptedPrivateMetadata{}, err
   196  	}
   197  
   198  	return EncryptedPrivateMetadata{encryptedData}, nil
   199  }
   200  
   201  // DecryptPrivateMetadata decrypts a PrivateMetadata object, but does
   202  // not decode it.
   203  func DecryptPrivateMetadata(
   204  	encryptedPrivateMetadata EncryptedPrivateMetadata, key TLFCryptKey) (
   205  	[]byte, error) {
   206  	if encryptedPrivateMetadata.encryptedData.Version ==
   207  		EncryptionSecretboxWithKeyNonce {
   208  		// Only blocks should have v2 encryption.
   209  		return nil, errors.WithStack(InvalidEncryptionVer{
   210  			encryptedPrivateMetadata.encryptedData.Version})
   211  	}
   212  
   213  	nonce, err := encryptedPrivateMetadata.encryptedData.Nonce24()
   214  	if err != nil {
   215  		return nil, err
   216  	}
   217  
   218  	return decryptData(
   219  		encryptedPrivateMetadata.encryptedData, key.Data(), nonce)
   220  }
   221  
   222  // EncryptedBlock is an encrypted Block object.
   223  type EncryptedBlock struct {
   224  	encryptedData
   225  }
   226  
   227  // EncryptPaddedEncodedBlock encrypts a padded, encoded block.
   228  func EncryptPaddedEncodedBlock(
   229  	paddedEncodedBlock []byte, tlfCryptKey TLFCryptKey,
   230  	blockServerHalf BlockCryptKeyServerHalf, ver EncryptionVer) (
   231  	encryptedBlock EncryptedBlock, err error) {
   232  	var ed encryptedData
   233  	switch ver {
   234  	case EncryptionSecretbox:
   235  		key := UnmaskBlockCryptKey(blockServerHalf, tlfCryptKey)
   236  		ed, err = encryptData(paddedEncodedBlock, key.Data())
   237  		if err != nil {
   238  			return EncryptedBlock{}, err
   239  		}
   240  	case EncryptionSecretboxWithKeyNonce:
   241  		key := MakeBlockHashKey(blockServerHalf, tlfCryptKey)
   242  		ed, err = encryptDataWithNonce(
   243  			paddedEncodedBlock, key.cryptKey(), key.nonce(),
   244  			EncryptionSecretboxWithKeyNonce)
   245  		if err != nil {
   246  			return EncryptedBlock{}, err
   247  		}
   248  	default:
   249  		return EncryptedBlock{}, errors.WithStack(UnknownEncryptionVer{ver})
   250  	}
   251  
   252  	return EncryptedBlock{ed}, nil
   253  }
   254  
   255  // DecryptBlock decrypts a block, but does not unpad or decode it.
   256  func DecryptBlock(
   257  	encryptedBlock EncryptedBlock, tlfCryptKey TLFCryptKey,
   258  	blockServerHalf BlockCryptKeyServerHalf) ([]byte, error) {
   259  	switch encryptedBlock.encryptedData.Version {
   260  	case EncryptionSecretbox:
   261  		nonce, err := encryptedBlock.encryptedData.Nonce24()
   262  		if err != nil {
   263  			return nil, err
   264  		}
   265  
   266  		key := UnmaskBlockCryptKey(blockServerHalf, tlfCryptKey)
   267  		return decryptData(encryptedBlock.encryptedData, key.Data(), nonce)
   268  	case EncryptionSecretboxWithKeyNonce:
   269  		key := MakeBlockHashKey(blockServerHalf, tlfCryptKey)
   270  		return decryptData(
   271  			encryptedBlock.encryptedData, key.cryptKey(), key.nonce())
   272  	default:
   273  		return nil, errors.WithStack(
   274  			InvalidEncryptionVer{encryptedBlock.encryptedData.Version})
   275  	}
   276  }
   277  
   278  // EncryptedTLFCryptKeys is an encrypted TLFCryptKey array.
   279  type EncryptedTLFCryptKeys struct {
   280  	encryptedData
   281  }
   282  
   283  // EncryptTLFCryptKeys encrypts a TLFCryptKey array.
   284  func EncryptTLFCryptKeys(codec kbfscodec.Codec, oldKeys []TLFCryptKey, key TLFCryptKey) (
   285  	encryptedTLFCryptKeys EncryptedTLFCryptKeys, err error) {
   286  	encodedKeys, err := codec.Encode(oldKeys)
   287  	if err != nil {
   288  		return EncryptedTLFCryptKeys{}, err
   289  	}
   290  
   291  	encryptedData, err := encryptData(encodedKeys, key.Data())
   292  	if err != nil {
   293  		return EncryptedTLFCryptKeys{}, err
   294  	}
   295  
   296  	return EncryptedTLFCryptKeys{encryptedData}, nil
   297  }
   298  
   299  // DecryptTLFCryptKeys decrypts a TLFCryptKey array, but does not
   300  // decode it.
   301  func DecryptTLFCryptKeys(
   302  	codec kbfscodec.Codec, encryptedTLFCryptKeys EncryptedTLFCryptKeys, key TLFCryptKey) (
   303  	[]TLFCryptKey, error) {
   304  	if encryptedTLFCryptKeys.encryptedData.Version ==
   305  		EncryptionSecretboxWithKeyNonce {
   306  		// Only blocks should have v2 encryption.
   307  		return nil, errors.WithStack(
   308  			InvalidEncryptionVer{encryptedTLFCryptKeys.encryptedData.Version})
   309  	}
   310  
   311  	nonce, err := encryptedTLFCryptKeys.encryptedData.Nonce24()
   312  	if err != nil {
   313  		return nil, err
   314  	}
   315  
   316  	encodedKeys, err := decryptData(
   317  		encryptedTLFCryptKeys.encryptedData, key.Data(), nonce)
   318  	if err != nil {
   319  		return nil, err
   320  	}
   321  
   322  	var oldKeys []TLFCryptKey
   323  	err = codec.Decode(encodedKeys, &oldKeys)
   324  	if err != nil {
   325  		return nil, err
   326  	}
   327  
   328  	return oldKeys, nil
   329  }
   330  
   331  // EncryptedMerkleLeaf is an encrypted MerkleLeaf object.
   332  type EncryptedMerkleLeaf struct {
   333  	encryptedData
   334  }
   335  
   336  // MakeEncryptedMerkleLeaf constructs an EncryptedMerkleLeaf.
   337  func MakeEncryptedMerkleLeaf(
   338  	version EncryptionVer, data []byte, nonce *[24]byte) EncryptedMerkleLeaf {
   339  	return EncryptedMerkleLeaf{
   340  		encryptedData{
   341  			Version:       version,
   342  			EncryptedData: data,
   343  			Nonce:         nonce[:],
   344  		},
   345  	}
   346  }
   347  
   348  // PrepareMerkleLeaf verifies the correctness of the given leaf, and
   349  // returns its nonce.
   350  func PrepareMerkleLeaf(encryptedMerkleLeaf EncryptedMerkleLeaf) (
   351  	nonce [24]byte, err error) {
   352  	if encryptedMerkleLeaf.Version != EncryptionSecretbox {
   353  		return nonce,
   354  			errors.WithStack(UnknownEncryptionVer{
   355  				Ver: encryptedMerkleLeaf.Version})
   356  	}
   357  
   358  	if len(encryptedMerkleLeaf.Nonce) != len(nonce) {
   359  		return nonce,
   360  			errors.WithStack(InvalidNonceError{
   361  				Nonce: encryptedMerkleLeaf.Nonce})
   362  	}
   363  	copy(nonce[:], encryptedMerkleLeaf.Nonce)
   364  	return nonce, nil
   365  }
   366  
   367  // DecryptMerkleLeaf decrypts an EncryptedMerkleLeaf using the given
   368  // private TLF key and ephemeral public key.
   369  func DecryptMerkleLeaf(
   370  	privateKey TLFPrivateKey, publicKey TLFEphemeralPublicKey,
   371  	encryptedMerkleLeaf EncryptedMerkleLeaf) ([]byte, error) {
   372  	nonce, err := PrepareMerkleLeaf(encryptedMerkleLeaf)
   373  	if err != nil {
   374  		return nil, err
   375  	}
   376  
   377  	publicKeyData := publicKey.Data()
   378  	privateKeyData := privateKey.Data()
   379  	decryptedData, ok := box.Open(nil, encryptedMerkleLeaf.EncryptedData,
   380  		&nonce, &publicKeyData, &privateKeyData)
   381  	if !ok {
   382  		return nil, errors.WithStack(
   383  			libkb.DecryptionError{Cause: libkb.ErrorCause{Err: errors.New("Cannot open box")}})
   384  	}
   385  	return decryptedData, nil
   386  }