Files
indra/pkg/message/segment_test.go
2022-11-08 11:01:23 +01:00

349 lines
7.5 KiB
Go

package message
import (
"bytes"
"crypto/cipher"
"crypto/rand"
"errors"
mrand "math/rand"
"testing"
"time"
"github.com/Indra-Labs/indra/pkg/ciph"
"github.com/Indra-Labs/indra/pkg/key/prv"
"github.com/Indra-Labs/indra/pkg/key/pub"
"github.com/Indra-Labs/indra/pkg/sha256"
)
func init() { mrand.Seed(time.Now().Unix()) }
func TestSplitJoin(t *testing.T) {
msgSize := 2 << 19
segSize := 1472
payload := make([]byte, msgSize)
var e error
var n int
if n, e = rand.Read(payload); check(e) && n != msgSize {
t.Error(e)
}
copy(payload, "payload")
pHash := sha256.Single(payload)
var sendPriv, reciPriv *prv.Key
var sendPub, reciPub *pub.Key
if sendPriv, e = prv.GenerateKey(); check(e) {
t.Error(e)
}
sendPub = pub.Derive(sendPriv)
if reciPriv, e = prv.GenerateKey(); check(e) {
t.Error(e)
}
reciPub = pub.Derive(reciPriv)
var blk1, blk2 cipher.Block
if blk1, e = ciph.GetBlock(sendPriv, reciPub); check(e) {
t.Error(e)
}
if blk2, e = ciph.GetBlock(reciPriv, sendPub); check(e) {
t.Error(e)
}
params := EP{
To: reciPub,
From: sendPriv,
Blk: blk1,
Parity: 0,
Seq: 0,
Length: len(payload),
Data: payload,
Pad: 0,
}
var splitted [][]byte
if splitted, e = Split(params, segSize); check(e) {
t.Error(e)
}
var pkts Packets
var keys []*pub.Key
for i := range splitted {
var pkt *Packet
var key *pub.Key
if pkt, key, e = Decode(splitted[i]); check(e) {
t.Error(e)
}
pkts = append(pkts, pkt.Decipher(blk2))
keys = append(keys, key)
}
prev := keys[0]
// check all keys are the same
for _, k := range keys[1:] {
if !prev.Equals(k) {
t.Error(e)
}
prev = k
}
var msg []byte
if msg, e = Join(pkts); check(e) {
t.Error(e)
}
rHash := sha256.Single(msg)
if bytes.Compare(pHash, rHash) != 0 {
t.Error(errors.New("message did not decode correctly"))
}
// rHash :=
// _, _, _ = pHash, sendPub, msg
}
func TestSplitJoinFEC(t *testing.T) {
msgSize := 2 << 17
segSize := 1472
var e error
var sendPriv, reciPriv *prv.Key
var reciPub *pub.Key
_ = reciPriv
var blk1, blk2 cipher.Block
if sendPriv, reciPriv, _, reciPub, blk1, blk2, e =
GenerateTestKeyPairs(); check(e) {
t.FailNow()
}
parity := []int{
1,
4,
16,
64,
128,
}
for i := range parity {
var payload []byte
var pHash sha256.Hash
if payload, pHash, e = GenerateTestMessage(msgSize); check(e) {
t.FailNow()
}
var punctures []int
// Generate a set of numbers of punctures starting from equal to
// parity in a halving sequence to reduce the number but see it
// function.
for punc := parity[i]; punc > 0; punc /= 2 {
punctures = append(punctures, punc)
}
// Reverse the ordering just because.
for p := 0; p < len(punctures)/2; p++ {
punctures[p], punctures[len(punctures)-p-1] =
punctures[len(punctures)-p-1], punctures[p]
}
log.I.Ln(punctures)
for p := range punctures {
log.I.Ln("parity", parity[i])
var splitted [][]byte
ep := EP{
To: reciPub,
From: sendPriv,
Blk: blk1,
Parity: parity[i],
Seq: 0,
Length: len(payload),
Data: payload,
Pad: 0,
}
if splitted, e = Split(ep, segSize); check(e) {
t.FailNow()
}
overhead := ep.GetOverhead()
segMap := NewSegments(len(ep.Data), segSize, overhead, ep.Parity)
for segs := range segMap {
start, end := segMap[segs].DStart, segMap[segs].PEnd
cnt := end - start
par := segMap[segs].DStart - segMap[segs].DEnd
// log.I.Ln("cnt", cnt)
a := make([][]byte, cnt)
for ss := range a {
a[ss] = splitted[start:end][ss]
}
mrand.Seed(int64(punctures[p]))
mrand.Shuffle(cnt,
func(i, j int) { a[i], a[j] = a[j], a[i] })
puncture := punctures[p]
if puncture > par {
puncture = par
}
log.I.F("puncturing %d elements of %d",
punctures[p], cnt)
for n := 0; n < puncture; n++ {
copy(a[n], make([]byte, 10))
}
}
var pkts Packets
var keys []*pub.Key
log.I.Ln("before decode", len(splitted))
for s := range splitted {
var pkt *Packet
var key *pub.Key
if pkt, key, e = Decode(splitted[s]); check(e) {
// we are puncturing, they some will fail to
// decode
log.I.Ln("skipping", s)
continue
}
pkts = append(pkts, pkt.Decipher(blk2))
keys = append(keys, key)
}
log.I.Ln("after decode", len(pkts))
var msg []byte
if msg, e = Join(pkts); check(e) {
t.FailNow()
}
rHash := sha256.Single(msg)
log.I.Ln("expected", len(payload), "got", len(msg))
log.I.S(pHash, rHash)
if bytes.Compare(pHash, rHash) != 0 {
t.Error(errors.New("message did not decode" +
" correctly"))
}
}
}
}
func TestSplit(t *testing.T) {
msgSize := 2 << 16
segSize := 4096
payload := make([]byte, msgSize)
var e error
var n int
if n, e = rand.Read(payload); check(e) && n != msgSize {
t.Error(e)
}
copy(payload[:7], "payload")
var sendPriv, reciPriv *prv.Key
var reciPub *pub.Key
if sendPriv, e = prv.GenerateKey(); check(e) {
t.Error(e)
}
if reciPriv, e = prv.GenerateKey(); check(e) {
t.Error(e)
}
reciPub = pub.Derive(reciPriv)
var blk1 cipher.Block
if blk1, e = ciph.GetBlock(sendPriv, reciPub); check(e) {
t.Error(e)
}
params := EP{
To: reciPub,
From: sendPriv,
Blk: blk1,
Parity: 96,
Seq: 0,
Length: len(payload),
Data: payload,
Pad: 0,
}
var splitted [][]byte
if splitted, e = Split(params, segSize); check(e) {
t.Error(e)
}
_ = splitted
}
func BenchmarkSplit(b *testing.B) {
msgSize := 2 << 16
segSize := 4096
payload := make([]byte, msgSize)
var e error
var n int
if n, e = rand.Read(payload); check(e) && n != msgSize {
b.Error(e)
}
copy(payload[:7], "payload")
for n := 0; n < b.N; n++ {
var sendPriv, reciPriv *prv.Key
var reciPub *pub.Key
if sendPriv, e = prv.GenerateKey(); check(e) {
b.Error(e)
}
// sendPub = pub.Derive(sendPriv)
if reciPriv, e = prv.GenerateKey(); check(e) {
b.Error(e)
}
reciPub = pub.Derive(reciPriv)
var blk1 cipher.Block
if blk1, e = ciph.GetBlock(sendPriv, reciPub); check(e) {
b.Error(e)
}
params := EP{
To: reciPub,
From: sendPriv,
Blk: blk1,
Parity: 64,
Seq: 0,
Length: len(payload),
Data: payload,
Pad: 0,
}
var splitted [][]byte
if splitted, e = Split(params, segSize); check(e) {
b.Error(e)
}
_ = splitted
}
}
func TestRemovePacket(t *testing.T) {
packets := make(Packets, 10)
for i := range packets {
packets[i] = &Packet{Seq: uint16(i)}
}
var seqs []uint16
for i := range packets {
seqs = append(seqs, packets[i].Seq)
}
log.I.Ln(seqs)
discard := []int{1, 5, 6}
log.I.Ln("discarding", discard)
for i := range discard {
// Subtracting the iterator accounts for the backwards shift of
// the shortened slice.
packets = RemovePacket(packets, discard[i]-i)
}
var seqs2 []uint16
for i := range packets {
seqs2 = append(seqs2, packets[i].Seq)
}
log.I.Ln(seqs2)
}
func GenerateTestMessage(msgSize int) (msg []byte, hash sha256.Hash, e error) {
msg = make([]byte, msgSize)
var n int
if n, e = rand.Read(msg); check(e) && n != msgSize {
return
}
copy(msg, "payload")
hash = sha256.Single(msg)
return
}
func GenerateTestKeyPairs() (sendPriv, reciPriv *prv.Key,
sendPub, reciPub *pub.Key, blk1, blk2 cipher.Block, e error) {
if sendPriv, e = prv.GenerateKey(); check(e) {
return
}
sendPub = pub.Derive(sendPriv)
if reciPriv, e = prv.GenerateKey(); check(e) {
return
}
reciPub = pub.Derive(reciPriv)
if blk1, e = ciph.GetBlock(sendPriv, reciPub); check(e) {
return
}
if blk2, e = ciph.GetBlock(reciPriv, sendPub); check(e) {
return
}
return
}