func deriveKey(ctx context.Context, mk, nonce []byte, size uint8) ([]byte, error) {
	err := ctxutil.ErrIfDone(ctx)
	if err != nil {
		return nil, err
	}
	h := blake2b.NewMAC(size, nonce)  
	h.Sum(mk)
	return h.Sum(nil), nil
}
deriveKey Derives a single use key from the given master key via blake2b
and a nonce.
package crypto
import (
	"context"
	"crypto/rand"
	"encoding/json"
	"errors"
	"strconv"
	"unsafe"
	"github.com/dchest/blake2b"
	"github.com/keybase/go-triplesec"
	"golang.org/x/crypto/ed25519"
	"golang.org/x/crypto/nacl/box"
	"golang.org/x/crypto/nacl/secretbox"
	"github.com/manifoldco/go-base64"
	"github.com/manifoldco/torus-cli/identity"
	"github.com/manifoldco/torus-cli/primitive"
	"github.com/manifoldco/torus-cli/daemon/crypto/secure"
	"github.com/manifoldco/torus-cli/daemon/ctxutil"
	"github.com/manifoldco/torus-cli/daemon/session"
)
const (
	nonceSize = 16
	blakeSize = 16
)
var ErrMissingPassphrase = errors.New("Missing passphrase; cannot unseal master key")
type SignatureKeyPair struct {
	Public  ed25519.PublicKey
	Private []byte
	PNonce  []byte
}
type EncryptionKeyPair struct {
	Public  [32]byte
	Private []byte
	PNonce  []byte
}
type KeyPairs struct {
	Signature  SignatureKeyPair
	Encryption EncryptionKeyPair
}
type Engine struct {
	sess  session.Session
	guard *secure.Guard
}
func NewEngine(sess session.Session, g *secure.Guard) *Engine {
	return &Engine{sess: sess, guard: g}
}
func (e *Engine) Seal(ctx context.Context, pt []byte) ([]byte, []byte, error) {
	mk, err := e.unsealMasterKey(ctx)
	defer mk.Destroy()
	if err != nil {
		return nil, nil, err
	}
	err = ctxutil.ErrIfDone(ctx)
	if err != nil {
		return nil, nil, err
	}
	nonce := make([]byte, nonceSize)
	_, err = rand.Read(nonce)
	if err != nil {
		return nil, nil, err
	}
	dk, err := deriveKey(ctx, mk.Buffer(), nonce, blakeSize)
	if err != nil {
		return nil, nil, err
	}
	ts, err := newTriplesec(ctx, dk)
	if err != nil {
		return nil, nil, err
	}
	err = ctxutil.ErrIfDone(ctx)
	if err != nil {
		return nil, nil, err
	}
	ct, err := ts.Encrypt(pt)
	return ct, nonce, err
}
func (e *Engine) Unseal(ctx context.Context, ct, nonce []byte) (*secure.Secret, error) {
	mk, err := e.unsealMasterKey(ctx)
	defer mk.Destroy()
	if err != nil {
		return nil, err
	}
	dk, err := deriveKey(ctx, mk.Buffer(), nonce, blakeSize)
	if err != nil {
		return nil, err
	}
	ts, err := newTriplesec(ctx, dk)
	if err != nil {
		return nil, err
	}
	err = ctxutil.ErrIfDone(ctx)
	if err != nil {
		return nil, err
	}
	b, err := ts.Decrypt(ct)
	if err != nil {
		return nil, err
	}
	return e.guard.Secret(b)
}
func (e *Engine) Box(ctx context.Context, pt *secure.Secret, privKP *EncryptionKeyPair,
	pubKey []byte) ([]byte, []byte, error) {
	err := ctxutil.ErrIfDone(ctx)
	if err != nil {
		return nil, nil, err
	}
	nonce := [24]byte{}
	_, err = rand.Read(nonce[:])
	if err != nil {
		return nil, nil, err
	}
	privKey, err := e.Unseal(ctx, privKP.Private, privKP.PNonce)
	if err != nil {
		return nil, nil, err
	}
	defer privKey.Destroy()
	privkb := (*[32]byte)(unsafe.Pointer(&privKey.Buffer()[0]))
	pubkb := [32]byte{}
	copy(pubkb[:], pubKey)
	err = ctxutil.ErrIfDone(ctx)
	if err != nil {
		return nil, nil, err
	}
	return box.Seal([]byte{}, pt.Buffer(), &nonce, &pubkb, privkb), nonce[:], nil
}
func (e *Engine) Unbox(ctx context.Context, ct, nonce []byte,
	privKP *EncryptionKeyPair, pubKey []byte) (*secure.Secret, error) {
	privKey, err := e.Unseal(ctx, privKP.Private, privKP.PNonce)
	if err != nil {
		return nil, err
	}
	defer privKey.Destroy()
	nonceb := [24]byte{}
	copy(nonceb[:], nonce)
	privkb := (*[32]byte)(unsafe.Pointer(&privKey.Buffer()[0]))
	pubkb := [32]byte{}
	copy(pubkb[:], pubKey)
	err = ctxutil.ErrIfDone(ctx)
	if err != nil {
		return nil, err
	}
	pt, success := box.Open([]byte{}, ct, &nonceb, &pubkb, privkb)
	if !success {
		return nil, errors.New("Failed to decrypt ciphertext")
	}
	return e.guard.Secret(pt)
}
func (e *Engine) BoxCredential(ctx context.Context, pt, encMec, mecNonce []byte,
	privKP *EncryptionKeyPair, pubKey []byte) ([]byte, []byte, []byte, error) {
	err := ctxutil.ErrIfDone(ctx)
	if err != nil {
		return nil, nil, nil, err
	}
	nonces := make([]byte, 48)
	_, err = rand.Read(nonces)
	if err != nil {
		return nil, nil, nil, err
	}
	cekNonce := nonces[:24]
	nonce := [24]byte{}
	copy(nonce[:], nonces[24:])
	mek, err := e.Unbox(ctx, encMec, mecNonce, privKP, pubKey)
	if err != nil {
		return nil, nil, nil, err
	}
	defer mek.Destroy()
	cek, err := deriveKey(ctx, mek.Buffer(), cekNonce, 32)
	if err != nil {
		return nil, nil, nil, err
	}
	cekb := [32]byte{}
	copy(cekb[:], cek)
	err = ctxutil.ErrIfDone(ctx)
	if err != nil {
		return nil, nil, nil, err
	}
	ct := secretbox.Seal([]byte{}, pt, &nonce, &cekb)
	return cekNonce, nonce[:], ct, err
}
func (e *Engine) UnboxCredential(ctx context.Context, ct, encMec, mecNonce,
	cekNonce, ctNonce []byte, privKP *EncryptionKeyPair, pubKey []byte) ([]byte, error) {
	mek, err := e.Unbox(ctx, encMec, mecNonce, privKP, pubKey)
	if err != nil {
		return nil, err
	}
	defer mek.Destroy()
	cek, err := deriveKey(ctx, mek.Buffer(), cekNonce, 32)
	if err != nil {
		return nil, err
	}
	cekb := [32]byte{}
	copy(cekb[:], cek)
	ctNonceb := [24]byte{}
	copy(ctNonceb[:], ctNonce)
	err = ctxutil.ErrIfDone(ctx)
	if err != nil {
		return nil, err
	}
	pt, success := secretbox.Open([]byte{}, ct, &ctNonceb, &cekb)
	if !success {
		return nil, errors.New("Failed to decrypt ciphertext")
	}
	return pt, nil
}
type Unsealer interface {
	WithUnboxer(context.Context, []byte, []byte, func(Unboxer) error) error
}
type unsealerImpl struct {
	engine  *Engine
	privkey *secure.Secret
	pubkey  []byte
}
func (u *unsealerImpl) WithUnboxer(ctx context.Context, encMec, mecNonce []byte,
	fn func(Unboxer) error) error {
	nonce := [24]byte{}
	copy(nonce[:], mecNonce)
	privkb := (*[32]byte)(unsafe.Pointer(&u.privkey.Buffer()[0]))
	pubkb := [32]byte{}
	copy(pubkb[:], u.pubkey)
	err := ctxutil.ErrIfDone(ctx)
	if err != nil {
		return err
	}
	mek, success := box.Open([]byte{}, encMec, &nonce, &pubkb, privkb)
	if !success {
		return errors.New("Failed to decrypt keyring")
	}
	s, err := u.engine.guard.Secret(mek)
	if err != nil {
		return err
	}
	defer s.Destroy()
	unboxer := unboxerImpl{mek: s}
	return fn(&unboxer)
}
type Unboxer interface {
	Unbox(context.Context, []byte, []byte, []byte) ([]byte, error)
}
type unboxerImpl struct {
	mek *secure.Secret
}
func (u *unboxerImpl) Unbox(ctx context.Context, ct, cekNonce, ctNonce []byte) ([]byte, error) {
	cek, err := deriveKey(ctx, u.mek.Buffer(), cekNonce, 32)
	if err != nil {
		return nil, err
	}
	cekb := [32]byte{}
	copy(cekb[:], cek)
	ctNonceb := [24]byte{}
	copy(ctNonceb[:], ctNonce)
	err = ctxutil.ErrIfDone(ctx)
	if err != nil {
		return nil, err
	}
	pt, success := secretbox.Open([]byte{}, ct, &ctNonceb, &cekb)
	if !success {
		return nil, errors.New("Failed to decrypt ciphertext")
	}
	return pt, nil
}
func (e *Engine) WithUnboxer(ctx context.Context, encMec, mecNonce []byte,
	privKP *EncryptionKeyPair, pubKey []byte, fn func(Unboxer) error) error {
	mek, err := e.Unbox(ctx, encMec, mecNonce, privKP, pubKey)
	if err != nil {
		return err
	}
	defer mek.Destroy()
	err = ctxutil.ErrIfDone(ctx)
	if err != nil {
		return err
	}
	u := unboxerImpl{mek: mek}
	return fn(&u)
}
func (e *Engine) WithUnsealer(ctx context.Context, privKP *EncryptionKeyPair,
	pubKey []byte, fn func(Unsealer) error) error {
	privKey, err := e.Unseal(ctx, privKP.Private, privKP.PNonce)
	if err != nil {
		return err
	}
	defer privKey.Destroy()
	err = ctxutil.ErrIfDone(ctx)
	if err != nil {
		return err
	}
	u := unsealerImpl{privkey: privKey, pubkey: pubKey, engine: e}
	return fn(&u)
}
func (e *Engine) CloneMembership(ctx context.Context, encMec, mecNonce []byte, privKP *EncryptionKeyPair, encPubKey, targetPubKey []byte) ([]byte, []byte, error) {
	mek, err := e.Unbox(ctx, encMec, mecNonce, privKP, encPubKey)
	if err != nil {
		return nil, nil, err
	}
	defer mek.Destroy()
	return e.Box(ctx, mek, privKP, targetPubKey)
}
func (e *Engine) GenerateKeyPairs(ctx context.Context) (*KeyPairs, error) {
	kp := &KeyPairs{}
	err := ctxutil.ErrIfDone(ctx)
	if err != nil {
		return nil, err
	}
	pubSig, privSig, err := ed25519.GenerateKey(rand.Reader)
	if err != nil {
		return nil, err
	}
	sealedSig, nonceSig, err := e.Seal(ctx, privSig)
	if err != nil {
		return nil, err
	}
	kp.Signature.Private = sealedSig
	kp.Signature.Public = pubSig
	kp.Signature.PNonce = nonceSig
	err = ctxutil.ErrIfDone(ctx)
	if err != nil {
		return nil, err
	}
	pubEnc, privEnc, err := box.GenerateKey(rand.Reader)
	if err != nil {
		return nil, err
	}
	sealedEnc, nonceEnc, err := e.Seal(ctx, (*privEnc)[:])
	if err != nil {
		return nil, err
	}
	kp.Encryption.Private = sealedEnc
	kp.Encryption.Public = *pubEnc
	kp.Encryption.PNonce = nonceEnc
	return kp, nil
}
func (e *Engine) Sign(ctx context.Context, s SignatureKeyPair, b []byte) ([]byte, error) {
	pk, err := e.Unseal(ctx, s.Private, s.PNonce)
	if err != nil {
		return nil, err
	}
	defer pk.Destroy()
	err = ctxutil.ErrIfDone(ctx)
	if err != nil {
		return nil, err
	}
	return ed25519.Sign(pk.Buffer(), b), nil
}
func (e *Engine) Verify(ctx context.Context, s SignatureKeyPair, b, sig []byte) (bool, error) {
	err := ctxutil.ErrIfDone(ctx)
	if err != nil {
		return false, err
	}
	return ed25519.Verify(s.Public, b, sig), nil
}
func (e *Engine) signAndID(ctx context.Context, body identity.Immutable,
	sigID *identity.ID, sigKP *SignatureKeyPair) (*identity.ID, *primitive.Signature, error) {
	err := ctxutil.ErrIfDone(ctx)
	if err != nil {
		return nil, nil, err
	}
	b, err := json.Marshal(&body)
	if err != nil {
		return nil, nil, err
	}
	s, err := e.Sign(ctx, *sigKP, append([]byte(strconv.Itoa(body.Version())), b...))
	if err != nil {
		return nil, nil, err
	}
	sig := primitive.Signature{
		PublicKeyID: sigID,
		Algorithm:   EdDSA,
		Value:       base64.New(s),
	}
	id, err := identity.NewImmutable(body, &sig)
	if err != nil {
		return nil, nil, err
	}
	return &id, &sig, err
}
func (e *Engine) unsealMasterKey(ctx context.Context) (*secure.Secret, error) {
	if !e.sess.HasPassphrase() {
		return nil, ErrMissingPassphrase
	}
	ts, err := newTriplesec(ctx, e.sess.Passphrase())
	if err != nil {
		return nil, err
	}
	masterKey, err := e.sess.MasterKey()
	if err != nil {
		return nil, err
	}
	err = ctxutil.ErrIfDone(ctx)
	if err != nil {
		return nil, err
	}
	mk, err := ts.Decrypt(*masterKey)
	if err != nil {
		return nil, err
	}
	return e.guard.Secret(mk)
}
func newTriplesec(ctx context.Context, k []byte) (*triplesec.Cipher, error) {
	err := ctxutil.ErrIfDone(ctx)
	if err != nil {
		return nil, err
	}
	ts, err := triplesec.NewCipher(k, nil)
	if err != nil {
		return nil, err
	}
	return ts, nil
}
func (e *Engine) ChangePassword(ctx context.Context, newPassword string) (*primitive.UserPassword, *primitive.MasterKey, *primitive.LoginPublicKey, error) {
	cmk, err := e.unsealMasterKey(ctx)
	defer cmk.Destroy()
	if err != nil {
		return nil, nil, nil, err
	}
	b := cmk.Buffer()
	pw, master, err := EncryptPasswordObject(ctx, newPassword, &b)
	if err != nil {
		return nil, nil, nil, err
	}
	s, err := base64.NewFromString(pw.Salt)
	if err != nil {
		return nil, nil, nil, err
	}
	keypair, err := DeriveLoginKeypair(ctx, []byte(newPassword), s)
	if err != nil {
		return nil, nil, nil, err
	}
	return pw, master, &primitive.LoginPublicKey{
		Salt:  keypair.Salt(),
		Value: keypair.PublicKey(),
		Alg:   EdDSA,
	}, nil
}