github.com/keybase/client/go@v0.0.0-20241007131713-f10651d043c8/libkb/saltpack_enc.go (about)

     1  // Copyright 2015 Keybase, Inc. All rights reserved. Use of
     2  // this source code is governed by the included BSD license.
     3  
     4  package libkb
     5  
     6  import (
     7  	"errors"
     8  	"io"
     9  
    10  	"github.com/keybase/saltpack"
    11  )
    12  
    13  type SaltpackEncryptArg struct {
    14  	Source             io.Reader
    15  	Sink               io.WriteCloser
    16  	Receivers          []NaclDHKeyPublic
    17  	Sender             NaclDHKeyPair
    18  	SenderSigning      NaclSigningKeyPair
    19  	Binary             bool
    20  	EncryptionOnlyMode bool
    21  	SymmetricReceivers []saltpack.ReceiverSymmetricKey
    22  	SaltpackVersion    saltpack.Version
    23  
    24  	VisibleRecipientsForTesting bool
    25  }
    26  
    27  // SaltpackEncrypt reads from the given source, encrypts it for the given
    28  // receivers from the given sender, and writes it to sink.  If
    29  // Binary is false, the data written to sink will be armored.
    30  func SaltpackEncrypt(m MetaContext, arg *SaltpackEncryptArg) error {
    31  	var receiverBoxKeys []saltpack.BoxPublicKey
    32  	for _, k := range arg.Receivers {
    33  		// Since signcryption became the default, we never use visible
    34  		// recipients in encryption mode, except in tests.
    35  		if arg.VisibleRecipientsForTesting {
    36  			receiverBoxKeys = append(receiverBoxKeys, naclBoxPublicKey(k))
    37  		} else {
    38  			receiverBoxKeys = append(receiverBoxKeys, hiddenNaclBoxPublicKey(k))
    39  		}
    40  	}
    41  
    42  	var bsk saltpack.BoxSecretKey
    43  	if !arg.Sender.IsNil() {
    44  		bsk = naclBoxSecretKey(arg.Sender)
    45  	}
    46  
    47  	// If the version is unspecified, default to the current version.
    48  	saltpackVersion := arg.SaltpackVersion
    49  	if saltpackVersion == (saltpack.Version{}) {
    50  		saltpackVersion = saltpack.CurrentVersion()
    51  	}
    52  
    53  	var plainsink io.WriteCloser
    54  	var err error
    55  	if !arg.EncryptionOnlyMode {
    56  		if arg.SaltpackVersion.Major == 1 {
    57  			return errors.New("specifying saltpack version 1 requires repudiable authentication")
    58  		}
    59  		var signer saltpack.SigningSecretKey
    60  		if !arg.SenderSigning.IsNil() {
    61  			signer = saltSigner{arg.SenderSigning}
    62  		}
    63  		if arg.Binary {
    64  			plainsink, err = saltpack.NewSigncryptSealStream(arg.Sink, emptyKeyring{}, signer, receiverBoxKeys, arg.SymmetricReceivers)
    65  		} else {
    66  			plainsink, err = saltpack.NewSigncryptArmor62SealStream(arg.Sink, emptyKeyring{}, signer, receiverBoxKeys, arg.SymmetricReceivers, KeybaseSaltpackBrand)
    67  		}
    68  	} else {
    69  		if arg.Binary {
    70  			plainsink, err = saltpack.NewEncryptStream(saltpackVersion, arg.Sink, bsk, receiverBoxKeys)
    71  		} else {
    72  			plainsink, err = saltpack.NewEncryptArmor62Stream(saltpackVersion, arg.Sink, bsk, receiverBoxKeys, KeybaseSaltpackBrand)
    73  		}
    74  	}
    75  	if err != nil {
    76  		return err
    77  	}
    78  
    79  	n, err := io.Copy(plainsink, arg.Source)
    80  	if err != nil {
    81  		return err
    82  	}
    83  
    84  	m.Debug("Encrypt: wrote %d bytes", n)
    85  
    86  	if err := plainsink.Close(); err != nil {
    87  		return err
    88  	}
    89  	return arg.Sink.Close()
    90  }