func DCMix(pads *Vec, m []byte, slot int) *Vec {
	dcmix := *pads
	dcmix.Data = make([]byte, len(pads.Data))
	copy(dcmix.Data, pads.Data)
	slotm := dcmix.M(slot)
	if len(m) != len(slotm) {
		panic("message sizes are not equal")
	}
	for i := range m {
		slotm[i] ^= m[i]
	}
	return &dcmix
}
DCMix creates the DC-net vector of message m xor'd into m's reserved
anonymous slot position of the pads DC-net pads.  Panics if len(m) is not the
vector's message size.
package dcnet
import (
	"bytes"
	"encoding/binary"
	"fmt"
	"math/big"
	"strings"
	"decred.org/cspp/chacha20prng"
	"decred.org/cspp/x25519"
	"github.com/decred/dcrd/crypto/blake256"
)
func SRMixPads(kp [][]byte, my int) []*big.Int {
	h := blake256.New()
	scratch := make([]byte, 8)
	pads := make([]*big.Int, len(kp))
	partialPad := new(big.Int)
	for j := 0; j < len(kp); j++ {
		pads[j] = new(big.Int)
		for i := 0; i < len(kp); i++ {
			if my == i {
				continue
			}
			binary.LittleEndian.PutUint64(scratch, uint64(j)+1)
			h.Reset()
			h.Write(kp[i])
			h.Write(scratch)
			digest := h.Sum(nil)
			partialPad.SetBytes(digest)
			if my > i {
				pads[j].Add(pads[j], partialPad)
			} else {
				pads[j].Sub(pads[j], partialPad)
			}
		}
		pads[j].Mod(pads[j], F)
	}
	return pads
}
func SRMix(m *big.Int, pads []*big.Int) []*big.Int {
	mix := make([]*big.Int, len(pads))
	exp := new(big.Int)
	for i := int64(0); i < int64(len(mix)); i++ {
		mexp := new(big.Int).Exp(m, exp.SetInt64(i+1), nil)
		mix[i] = mexp.Add(mexp, pads[i])
		mix[i].Mod(mix[i], F)
	}
	return mix
}
func AddVectors(vs ...[]*big.Int) []*big.Int {
	sums := make([]*big.Int, len(vs))
	for i := range sums {
		sums[i] = new(big.Int)
		for j := range vs {
			sums[i].Add(sums[i], vs[j][i])
		}
		sums[i].Mod(sums[i], F)
	}
	return sums
}
func Coefficients(S []*big.Int) []*big.Int {
	n := len(S) + 1
	a := make([]*big.Int, n)
	a[len(a)-1] = big.NewInt(-1)
	a[len(a)-1].Add(a[len(a)-1], F)  
	scratch := new(big.Int)
	for i := 0; i < len(a)-1; i++ {
		a[n-2-i] = new(big.Int)
		for j := 0; j <= i; j++ {
			a[n-2-i].Add(a[n-2-i], scratch.Mul(a[n-1-i+j], S[j]))
		}
		xinv := scratch.ModInverse(scratch.SetInt64(int64(i)+1), F)
		xinv.Neg(xinv)
		a[n-2-i].Mul(a[n-2-i], xinv)
		a[n-2-i].Mod(a[n-2-i], F)
	}
	return a
}
func IsRoot(m *big.Int, a []*big.Int) bool {
	sum := new(big.Int)
	scratch := new(big.Int)
	for i := range a {
		scratch.Exp(m, scratch.SetInt64(int64(i)), F)
		scratch.Mul(scratch, a[i])
		sum.Add(sum, scratch)
	}
	sum.Mod(sum, F)
	return sum.Sign() == 0
}
type Vec struct {
	N     int
	Msize int
	Data  []byte
}
func NewVec(n, msize int) *Vec {
	return &Vec{
		N:     n,
		Msize: msize,
		Data:  make([]byte, n*msize),
	}
}
func (v *Vec) IsDim(n, msize int) bool {
	return v.N == n && v.Msize == msize && len(v.Data) == n*msize
}
func (v *Vec) Equals(other *Vec) bool {
	return other.IsDim(v.N, v.Msize) && bytes.Equal(other.Data, v.Data)
}
func (v *Vec) M(i int) []byte {
	return v.Data[i*v.Msize : i*v.Msize+v.Msize]
}
func (v *Vec) String() string {
	b := new(strings.Builder)
	b.Grow(2 + v.N*(2*v.Msize+1))
	b.WriteString("[")
	for i := 0; i < v.N; i++ {
		if i != 0 {
			b.WriteString(" ")
		}
		fmt.Fprintf(b, "%x", v.M(i))
	}
	b.WriteString("]")
	return b.String()
}
func SharedKeys(secrets []*x25519.KX, publics []*x25519.Public, sid []byte, msize, run, start, mcount int) (sr [][][]byte, dc [][]*Vec) {
	sr = make([][][]byte, mcount)
	dc = make([][]*Vec, mcount)
	mtot := len(publics)
	for i := 0; i < mcount; i++ {
		my := start + i
		sr[i] = make([][]byte, mtot)
		dc[i] = make([]*Vec, mtot)
		for from, pub := range publics {
			if from == my {
				continue
			}
			h := blake256.New()
			h.Write(sid)
			h.Write(secrets[i].SharedKey(pub))
			prngSeed := h.Sum(nil)
			prng := chacha20prng.New(prngSeed, uint32(run))
			sr[i][from] = prng.Next(32)
			dc[i][from] = &Vec{
				N:     mtot,
				Msize: msize,
				Data:  prng.Next(mtot * msize),
			}
		}
	}
	return
}
func DCMixPads(kp []*Vec, msize, my int) *Vec {
	n := len(kp)
	pads := &Vec{
		N:     n,
		Msize: msize,
		Data:  make([]byte, n*msize),
	}
	for i := range kp {
		if i == my {
			continue
		}
		pads.Xor(pads, kp[i])
	}
	return pads
}