func (sss *signcryptSealStream) init(
	receiverBoxKeys []BoxPublicKey, receiverSymmetricKeys []ReceiverSymmetricKey,
	ephemeralKeyCreator EphemeralKeyCreator, rng signcryptRNG) error {
	if err := checkSigncryptReceivers(receiverBoxKeys, receiverSymmetricKeys); err != nil {
		return err
	}
	receivers, err := rng.shuffleReceivers(receiverBoxKeys, receiverSymmetricKeys)
	if err != nil {
		return err
	}
	ephemeralKey, err := ephemeralKeyCreator.CreateEphemeralKey()
	if err != nil {
		return err
	}
	eh := SigncryptionHeader{
		FormatName: FormatName,
		Version:    sss.version,
		Type:       MessageTypeSigncryption,
		Ephemeral:  ephemeralKey.GetPublicKey().ToKID(),
	}
	encryptionKey, err := rng.createSymmetricKey()
	if err != nil {
		return err
	}
	sss.encryptionKey = *encryptionKey
	nonce := nonceForSenderKeySecretBox()
	if sss.signingKey == nil {
		eh.SenderSecretbox = secretbox.Seal([]byte{}, make([]byte, ed25519.PublicKeySize), (*[24]byte)(&nonce), (*[32]byte)(&sss.encryptionKey))
	} else {
		signingPublicKeyBytes := sss.signingKey.GetPublicKey().ToKID()
		if len(signingPublicKeyBytes) != ed25519.PublicKeySize {
			panic("unexpected signing key length, anonymity bit will leak")
		}
		eh.SenderSecretbox = secretbox.Seal([]byte{}, sss.signingKey.GetPublicKey().ToKID(), (*[24]byte)(&nonce), (*[32]byte)(&sss.encryptionKey))
	}
	for i, r := range receivers {
		eh.Receivers = append(eh.Receivers, r.makeReceiverKeys(ephemeralKey, sss.encryptionKey, uint64(i)))
	}
	headerBytes, err := encodeToBytes(eh)
	if err != nil {
		return err
	}
	sss.headerHash = sha512.Sum512(headerBytes)
	err = sss.encoder.Encode(headerBytes)
	if err != nil {
		return err
	}
	return nil
}
This generates the payload key, and encrypts it for all the different
recipients of the two different types. Symmetric key recipients and DH key
recipients use different types of identifiers, but they are the same length,
and should both be indistinguishable from random noise.
package saltpack
import (
	"bytes"
	"crypto/hmac"
	cryptorand "crypto/rand"
	"crypto/sha512"
	"fmt"
	"io"
	"golang.org/x/crypto/ed25519"
	"golang.org/x/crypto/nacl/secretbox"
)
type signcryptSealStream struct {
	version         Version
	output          io.Writer
	encoder         encoder
	encryptionKey   SymmetricKey
	signingKey      SigningSecretKey
	senderAnonymous bool
	buffer          bytes.Buffer
	headerHash      headerHash
	numBlocks encryptionBlockNumber  
	didHeader bool
	eof       bool
	err       error
}
func (sss *signcryptSealStream) Write(plaintext []byte) (int, error) {
	if sss.err != nil {
		return 0, sss.err
	}
	var ret int
	if ret, sss.err = sss.buffer.Write(plaintext); sss.err != nil {
		return 0, sss.err
	}
	for sss.buffer.Len() > encryptionBlockSize {
		sss.err = sss.signcryptBlock(false)
		if sss.err != nil {
			return 0, sss.err
		}
	}
	return ret, nil
}
func (sss *signcryptSealStream) signcryptBlock(isFinal bool) error {
	plaintext := sss.buffer.Next(encryptionBlockSize)
	if isFinal && (sss.buffer.Len() != 0) {
		panic(fmt.Sprintf("isFinal=true and (sss.buffer.Len()=%d != 0)", sss.buffer.Len()))
	}
	if err := sss.numBlocks.check(); err != nil {
		return err
	}
	nonce := nonceForChunkSigncryption(sss.headerHash, isFinal, sss.numBlocks)
	var detachedSig []byte
	if sss.signingKey == nil {
		detachedSig = make([]byte, ed25519.SignatureSize)
	} else {
		signatureInput := computeSigncryptionSignatureInput(sss.headerHash, nonce, isFinal, plaintext)
		var err error
		detachedSig, err = sss.signingKey.Sign(signatureInput)
		if err != nil {
			return err
		}
	}
	attachedSig := append(detachedSig, plaintext...)
	ciphertext := secretbox.Seal([]byte{}, attachedSig, (*[24]byte)(&nonce), (*[32]byte)(&sss.encryptionKey))
	assertEncodedChunkState(sss.version, ciphertext, secretbox.Overhead, uint64(sss.numBlocks), isFinal)
	block := signcryptionBlock{
		PayloadCiphertext: ciphertext,
		IsFinal:           isFinal,
	}
	if err := sss.encoder.Encode(block); err != nil {
		return err
	}
	sss.numBlocks++
	return nil
}
func derivedEphemeralKeyFromBoxKeys(public BoxPublicKey, private BoxSecretKey) *SymmetricKey {
	sharedSecretBox := private.Box(public, nonceForDerivedSharedKey(), make([]byte, 32))
	derivedKey, err := symmetricKeyFromSlice(sharedSecretBox[len(sharedSecretBox)-32:])
	if err != nil {
		panic(err)  
	}
	return derivedKey
}
func keyIdentifierFromDerivedKey(derivedKey *SymmetricKey, recipientIndex uint64) []byte {
	keyIdentifierDigest := hmac.New(sha512.New, []byte(signcryptionBoxKeyIdentifierContext))
	keyIdentifierDigest.Write(derivedKey[:])
	nonce := nonceForPayloadKeyBoxV2(recipientIndex)
	keyIdentifierDigest.Write(nonce[:])
	return keyIdentifierDigest.Sum(nil)[0:32]
}
type receiverKeysMaker interface {
	makeReceiverKeys(ephemeralPriv BoxSecretKey, payloadKey SymmetricKey, index uint64) receiverKeys
}
type receiverBoxKey struct {
	pk BoxPublicKey
}
func (r receiverBoxKey) makeReceiverKeys(ephemeralPriv BoxSecretKey, payloadKey SymmetricKey, index uint64) receiverKeys {
	derivedKey := derivedEphemeralKeyFromBoxKeys(r.pk, ephemeralPriv)
	identifier := keyIdentifierFromDerivedKey(derivedKey, index)
	nonce := nonceForPayloadKeyBoxV2(index)
	payloadKeyBox := secretbox.Seal(
		nil,
		payloadKey[:],
		(*[24]byte)(&nonce),
		(*[32]byte)(derivedKey))
	return receiverKeys{
		ReceiverKID:   identifier,
		PayloadKeyBox: payloadKeyBox,
	}
}
type ReceiverSymmetricKey struct {
	Key SymmetricKey
	Identifier []byte
}
func (r ReceiverSymmetricKey) makeReceiverKeys(ephemeralPriv BoxSecretKey, payloadKey SymmetricKey, index uint64) receiverKeys {
	derivedKeyDigest := hmac.New(sha512.New, []byte(signcryptionSymmetricKeyContext))
	derivedKeyDigest.Write(ephemeralPriv.GetPublicKey().ToKID())
	derivedKeyDigest.Write(r.Key[:])
	derivedKey, err := rawBoxKeyFromSlice(derivedKeyDigest.Sum(nil)[0:32])
	if err != nil {
		panic(err)  
	}
	nonce := nonceForPayloadKeyBoxV2(index)
	payloadKeyBox := secretbox.Seal(
		nil,
		payloadKey[:],
		(*[24]byte)(&nonce),
		(*[32]byte)(derivedKey))
	return receiverKeys{
		ReceiverKID:   r.Identifier,
		PayloadKeyBox: payloadKeyBox,
	}
}
func checkSigncryptReceiverCount(receiverBoxKeyCount, receiverSymmetricKeyCount int) error {
	c1 := int64(receiverBoxKeyCount)
	c2 := int64(receiverSymmetricKeyCount)
	if c1 < 0 {
		panic("Bogus recieverBoxKeyCount")
	}
	if c2 < 0 {
		panic("Bogus recieverSymmetricKeyCount")
	}
	if c1 > maxReceiverCount {
		return ErrBadReceivers
	}
	if c2 > maxReceiverCount {
		return ErrBadReceivers
	}
	c := c1 + c2
	if c <= 0 || c > maxReceiverCount {
		return ErrBadReceivers
	}
	return nil
}
func checkSigncryptReceivers(receiverBoxKeys []BoxPublicKey, receiverSymmetricKeys []ReceiverSymmetricKey) error {
	err := checkSigncryptReceiverCount(len(receiverBoxKeys), len(receiverSymmetricKeys))
	if err != nil {
		return err
	}
	receiverSet := make(map[string]bool)
	for _, receiver := range receiverBoxKeys {
		kid := receiver.ToKID()
		kidString := string(kid)
		if receiverSet[kidString] {
			return ErrRepeatedKey(kid)
		}
		receiverSet[kidString] = true
	}
	for _, receiver := range receiverSymmetricKeys {
		kid := receiver.Identifier
		kidString := string(kid)
		if receiverSet[kidString] {
			return ErrRepeatedKey(kid)
		}
		receiverSet[kidString] = true
	}
	return nil
}
func shuffleSigncryptReceivers(receiverBoxKeys []BoxPublicKey, receiverSymmetricKeys []ReceiverSymmetricKey) ([]receiverKeysMaker, error) {
	totalLen := len(receiverBoxKeys) + len(receiverSymmetricKeys)
	shuffled := make([]receiverKeysMaker, totalLen)
	for i, r := range receiverBoxKeys {
		shuffled[i] = receiverBoxKey{r}
	}
	for i, r := range receiverSymmetricKeys {
		shuffled[i+len(receiverBoxKeys)] = r
	}
	err := csprngShuffle(cryptorand.Reader, len(shuffled), func(i, j int) {
		shuffled[i], shuffled[j] = shuffled[j], shuffled[i]
	})
	if err != nil {
		return nil, err
	}
	return shuffled, nil
}
type signcryptRNG interface {
	createSymmetricKey() (*SymmetricKey, error)
	shuffleReceivers(receiverBoxKeys []BoxPublicKey, receiverSymmetricKeys []ReceiverSymmetricKey) ([]receiverKeysMaker, error)
}