// Copyright 2012 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

/*
Package box authenticates and encrypts small messages using public-key cryptography.

Box uses Curve25519, XSalsa20 and Poly1305 to encrypt and authenticate
messages. The length of messages is not hidden.

It is the caller's responsibility to ensure the uniqueness of nonces—for
example, by using nonce 1 for the first message, nonce 2 for the second
message, etc. Nonces are long enough that randomly generated nonces have
negligible risk of collision.

Messages should be small because:

1. The whole message needs to be held in memory to be processed.

2. Using large messages pressures implementations on small machines to decrypt
and process plaintext before authenticating it. This is very dangerous, and
this API does not allow it, but a protocol that uses excessive message sizes
might present some implementations with no other choice.

3. Fixed overheads will be sufficiently amortised by messages as small as 8KB.

4. Performance may be improved by working with messages that fit into data caches.

Thus large amounts of data should be chunked so that each message is small.
(Each message still needs a unique nonce.) If in doubt, 16KB is a reasonable
chunk size.

This package is interoperable with NaCl: https://nacl.cr.yp.to/box.html.
Anonymous sealing/opening is an extension of NaCl defined by and interoperable
with libsodium:
https://libsodium.gitbook.io/doc/public-key_cryptography/sealed_boxes.
*/
package box // import "golang.org/x/crypto/nacl/box"

import (
	cryptorand "crypto/rand"
	"io"

	"golang.org/x/crypto/blake2b"
	"golang.org/x/crypto/curve25519"
	"golang.org/x/crypto/nacl/secretbox"
	"golang.org/x/crypto/salsa20/salsa"
)

const (
	// Overhead is the number of bytes of overhead when boxing a message.
	Overhead = secretbox.Overhead

	// AnonymousOverhead is the number of bytes of overhead when using anonymous
	// sealed boxes.
	AnonymousOverhead = Overhead + 32
)

// GenerateKey generates a new public/private key pair suitable for use with
// Seal and Open.
func GenerateKey(rand io.Reader) (publicKey, privateKey *[32]byte, err error) {
	publicKey = new([32]byte)
	privateKey = new([32]byte)
	_, err = io.ReadFull(rand, privateKey[:])
	if err != nil {
		publicKey = nil
		privateKey = nil
		return
	}

	curve25519.ScalarBaseMult(publicKey, privateKey)
	return
}

var zeros [16]byte

// Precompute calculates the shared key between peersPublicKey and privateKey
// and writes it to sharedKey. The shared key can be used with
// OpenAfterPrecomputation and SealAfterPrecomputation to speed up processing
// when using the same pair of keys repeatedly.
func Precompute(sharedKey, peersPublicKey, privateKey *[32]byte) {
	curve25519.ScalarMult(sharedKey, privateKey, peersPublicKey)
	salsa.HSalsa20(sharedKey, &zeros, sharedKey, &salsa.Sigma)
}

// Seal appends an encrypted and authenticated copy of message to out, which
// will be Overhead bytes longer than the original and must not overlap it. The
// nonce must be unique for each distinct message for a given pair of keys.
func Seal(out, message []byte, nonce *[24]byte, peersPublicKey, privateKey *[32]byte) []byte {
	var sharedKey [32]byte
	Precompute(&sharedKey, peersPublicKey, privateKey)
	return secretbox.Seal(out, message, nonce, &sharedKey)
}

// SealAfterPrecomputation performs the same actions as Seal, but takes a
// shared key as generated by Precompute.
func SealAfterPrecomputation(out, message []byte, nonce *[24]byte, sharedKey *[32]byte) []byte {
	return secretbox.Seal(out, message, nonce, sharedKey)
}

// Open authenticates and decrypts a box produced by Seal and appends the
// message to out, which must not overlap box. The output will be Overhead
// bytes smaller than box.
func Open(out, box []byte, nonce *[24]byte, peersPublicKey, privateKey *[32]byte) ([]byte, bool) {
	var sharedKey [32]byte
	Precompute(&sharedKey, peersPublicKey, privateKey)
	return secretbox.Open(out, box, nonce, &sharedKey)
}

// OpenAfterPrecomputation performs the same actions as Open, but takes a
// shared key as generated by Precompute.
func OpenAfterPrecomputation(out, box []byte, nonce *[24]byte, sharedKey *[32]byte) ([]byte, bool) {
	return secretbox.Open(out, box, nonce, sharedKey)
}

// SealAnonymous appends an encrypted and authenticated copy of message to out,
// which will be AnonymousOverhead bytes longer than the original and must not
// overlap it. This differs from Seal in that the sender is not required to
// provide a private key.
func SealAnonymous(out, message []byte, recipient *[32]byte, rand io.Reader) ([]byte, error) {
	if rand == nil {
		rand = cryptorand.Reader
	}
	ephemeralPub, ephemeralPriv, err := GenerateKey(rand)
	if err != nil {
		return nil, err
	}

	var nonce [24]byte
	if err := sealNonce(ephemeralPub, recipient, &nonce); err != nil {
		return nil, err
	}

	if total := len(out) + AnonymousOverhead + len(message); cap(out) < total {
		original := out
		out = make([]byte, 0, total)
		out = append(out, original...)
	}
	out = append(out, ephemeralPub[:]...)

	return Seal(out, message, &nonce, recipient, ephemeralPriv), nil
}

// OpenAnonymous authenticates and decrypts a box produced by SealAnonymous and
// appends the message to out, which must not overlap box. The output will be
// AnonymousOverhead bytes smaller than box.
func OpenAnonymous(out, box []byte, publicKey, privateKey *[32]byte) (message []byte, ok bool) {
	if len(box) < AnonymousOverhead {
		return nil, false
	}

	var ephemeralPub [32]byte
	copy(ephemeralPub[:], box[:32])

	var nonce [24]byte
	if err := sealNonce(&ephemeralPub, publicKey, &nonce); err != nil {
		return nil, false
	}

	return Open(out, box[32:], &nonce, &ephemeralPub, privateKey)
}

// sealNonce generates a 24 byte nonce that is a blake2b digest of the
// ephemeral public key and the receiver's public key.
func sealNonce(ephemeralPub, peersPublicKey *[32]byte, nonce *[24]byte) error {
	h, err := blake2b.New(24, nil)
	if err != nil {
		return err
	}

	if _, err = h.Write(ephemeralPub[:]); err != nil {
		return err
	}

	if _, err = h.Write(peersPublicKey[:]); err != nil {
		return err
	}

	h.Sum(nonce[:0])

	return nil
}
