Now cipher, confirmation and exit encode/decode
This commit is contained in:
@@ -133,6 +133,11 @@ func NoisePad(l int) (noise []byte) {
|
||||
|
||||
type Cursor int
|
||||
|
||||
func NewCursor() (c *Cursor) {
|
||||
var cc Cursor
|
||||
return &cc
|
||||
}
|
||||
|
||||
func (c *Cursor) Inc(v int) Cursor {
|
||||
*c += Cursor(v)
|
||||
return *c
|
||||
|
||||
@@ -1,15 +1,19 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"math/rand"
|
||||
"testing"
|
||||
|
||||
"github.com/Indra-Labs/indra/pkg/key/prv"
|
||||
"github.com/Indra-Labs/indra/pkg/key/pub"
|
||||
"github.com/Indra-Labs/indra/pkg/nonce"
|
||||
"github.com/Indra-Labs/indra/pkg/sha256"
|
||||
"github.com/Indra-Labs/indra/pkg/slice"
|
||||
"github.com/Indra-Labs/indra/pkg/testutils"
|
||||
"github.com/Indra-Labs/indra/pkg/types"
|
||||
"github.com/Indra-Labs/indra/pkg/wire/cipher"
|
||||
"github.com/Indra-Labs/indra/pkg/wire/confirmation"
|
||||
"github.com/Indra-Labs/indra/pkg/wire/exit"
|
||||
log2 "github.com/cybriq/proc/pkg/log"
|
||||
)
|
||||
|
||||
@@ -18,12 +22,10 @@ func TestOnionSkins_Cipher(t *testing.T) {
|
||||
var e error
|
||||
hdrP, pldP := GetTwoPrvKeys(t)
|
||||
hdr, pld := pub.Derive(hdrP), pub.Derive(pldP)
|
||||
log.I.S(hdr, pld)
|
||||
n := nonce.NewID()
|
||||
log.I.S(n)
|
||||
// n := nonce.NewID()
|
||||
on := OnionSkins{}.
|
||||
Cipher(hdr, pld).
|
||||
Confirmation(n).
|
||||
// Confirmation(n).
|
||||
Assemble()
|
||||
onb := EncodeOnion(on)
|
||||
var sc slice.Cursor
|
||||
@@ -32,19 +34,26 @@ func TestOnionSkins_Cipher(t *testing.T) {
|
||||
if onc, e = PeelOnion(onb, c); check(e) {
|
||||
t.FailNow()
|
||||
}
|
||||
log.I.S(onc.(*cipher.OnionSkin))
|
||||
var oncn types.Onion
|
||||
if oncn, e = PeelOnion(onb, c); check(e) {
|
||||
var ci *cipher.OnionSkin
|
||||
var ok bool
|
||||
if ci, ok = onc.(*cipher.OnionSkin); !ok {
|
||||
t.Error("did not unwrap expected type")
|
||||
t.FailNow()
|
||||
}
|
||||
if !ci.Header.Equals(hdr) {
|
||||
t.Error("header key did not unwrap correctly")
|
||||
t.FailNow()
|
||||
}
|
||||
if !ci.Payload.Equals(pld) {
|
||||
t.Error("payload key did not unwrap correctly")
|
||||
t.FailNow()
|
||||
}
|
||||
log.I.S(oncn.(*confirmation.OnionSkin))
|
||||
}
|
||||
|
||||
func TestOnionSkins_Confirmation(t *testing.T) {
|
||||
log2.CodeLoc = true
|
||||
var e error
|
||||
n := nonce.NewID()
|
||||
log.I.S(n)
|
||||
on := OnionSkins{}.
|
||||
Confirmation(n).
|
||||
Assemble()
|
||||
@@ -55,11 +64,60 @@ func TestOnionSkins_Confirmation(t *testing.T) {
|
||||
if oncn, e = PeelOnion(onb, c); check(e) {
|
||||
t.FailNow()
|
||||
}
|
||||
log.I.S(oncn.(*confirmation.OnionSkin))
|
||||
var cf *confirmation.OnionSkin
|
||||
var ok bool
|
||||
if cf, ok = oncn.(*confirmation.OnionSkin); !ok {
|
||||
t.Error("did not unwrap expected type")
|
||||
t.FailNow()
|
||||
}
|
||||
if cf.ID != n {
|
||||
t.Error("confirmation ID did not unwrap correctly")
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
|
||||
func TestOnionSkins_Exit(t *testing.T) {
|
||||
|
||||
log2.CodeLoc = true
|
||||
var e error
|
||||
var msg slice.Bytes
|
||||
prvs, pubs := GetCipherSet(t)
|
||||
ciphers := GenCiphers(prvs, pubs)
|
||||
var hash sha256.Hash
|
||||
if msg, hash, e = testutils.GenerateTestMessage(512); check(e) {
|
||||
t.Error(e)
|
||||
t.FailNow()
|
||||
}
|
||||
p := uint16(rand.Uint32())
|
||||
on := OnionSkins{}.
|
||||
Exit(p, prvs, pubs, msg).
|
||||
Assemble()
|
||||
onb := EncodeOnion(on)
|
||||
c := slice.NewCursor()
|
||||
var onex types.Onion
|
||||
if onex, e = PeelOnion(onb, c); check(e) {
|
||||
t.FailNow()
|
||||
}
|
||||
var ex *exit.OnionSkin
|
||||
var ok bool
|
||||
if ex, ok = onex.(*exit.OnionSkin); !ok {
|
||||
t.Error("did not unwrap expected type")
|
||||
t.FailNow()
|
||||
}
|
||||
if ex.Port != p {
|
||||
t.Error("exit port did not unwrap correctly")
|
||||
t.FailNow()
|
||||
}
|
||||
for i := range ex.Ciphers {
|
||||
if ex.Ciphers[i] != ciphers[i] {
|
||||
t.Errorf("cipher %d did not unwrap correctly", i)
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
plH := sha256.Single(ex.Bytes)
|
||||
if plH != hash {
|
||||
t.Errorf("exit message did not unwrap correctly")
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
|
||||
func TestOnionSkins_Forward(t *testing.T) {
|
||||
@@ -100,3 +158,12 @@ func GetTwoPrvKeys(t *testing.T) (prv1, prv2 *prv.Key) {
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func GetCipherSet(t *testing.T) (prvs [3]*prv.Key, pubs [3]*pub.Key) {
|
||||
for i := range prvs {
|
||||
prv1, prv2 := GetTwoPrvKeys(t)
|
||||
prvs[i] = prv1
|
||||
pubs[i] = pub.Derive(prv2)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -10,12 +10,13 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
log = log2.GetLogger(indra.PathBase)
|
||||
check = log.E.Chk
|
||||
MagicString = "ex"
|
||||
Magic = slice.Bytes(MagicString)
|
||||
MinLen = magicbytes.Len + slice.Uint16Len + 3*sha256.Len
|
||||
_ types.Onion = &OnionSkin{}
|
||||
log = log2.GetLogger(indra.PathBase)
|
||||
check = log.E.Chk
|
||||
MagicString = "ex"
|
||||
Magic = slice.Bytes(MagicString)
|
||||
MinLen = magicbytes.Len + slice.Uint16Len +
|
||||
3*sha256.Len + slice.Uint32Len
|
||||
_ types.Onion = &OnionSkin{}
|
||||
)
|
||||
|
||||
// OnionSkin exit messages are the layer of a message after two Forward packets that
|
||||
@@ -40,8 +41,7 @@ type OnionSkin struct {
|
||||
func (x *OnionSkin) Inner() types.Onion { return x.Onion }
|
||||
func (x *OnionSkin) Insert(o types.Onion) { x.Onion = o }
|
||||
func (x *OnionSkin) Len() int {
|
||||
return MinLen + x.Bytes.Len() +
|
||||
x.Onion.Len()
|
||||
return MinLen + x.Bytes.Len() + x.Onion.Len()
|
||||
}
|
||||
|
||||
func (x *OnionSkin) Encode(b slice.Bytes, c *slice.Cursor) {
|
||||
@@ -51,7 +51,7 @@ func (x *OnionSkin) Encode(b slice.Bytes, c *slice.Cursor) {
|
||||
copy(b[*c:c.Inc(slice.Uint16Len)], port)
|
||||
copy(b[*c:c.Inc(sha256.Len)], x.Ciphers[0][:])
|
||||
copy(b[*c:c.Inc(sha256.Len)], x.Ciphers[1][:])
|
||||
copy(b[*c:c.Inc(sha256.Len)], x.Ciphers[1][:])
|
||||
copy(b[*c:c.Inc(sha256.Len)], x.Ciphers[2][:])
|
||||
bytesLen := slice.NewUint32()
|
||||
slice.EncodeUint32(bytesLen, len(x.Bytes))
|
||||
copy(b[*c:c.Inc(slice.Uint32Len)], bytesLen)
|
||||
@@ -60,10 +60,10 @@ func (x *OnionSkin) Encode(b slice.Bytes, c *slice.Cursor) {
|
||||
}
|
||||
|
||||
func (x *OnionSkin) Decode(b slice.Bytes, c *slice.Cursor) (e error) {
|
||||
if len(b[*c:]) < MinLen {
|
||||
if len(b[*c:]) < MinLen-magicbytes.Len {
|
||||
return magicbytes.TooShort(len(b[*c:]), MinLen, string(Magic))
|
||||
}
|
||||
x.Port = uint16(slice.DecodeUint16(b[*c:slice.Uint16Len]))
|
||||
x.Port = uint16(slice.DecodeUint16(b[*c:c.Inc(slice.Uint16Len)]))
|
||||
for i := range x.Ciphers {
|
||||
bytes := b[*c:c.Inc(sha256.Len)]
|
||||
copy(x.Ciphers[i][:], bytes)
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"net"
|
||||
|
||||
"github.com/Indra-Labs/indra/pkg/key/address"
|
||||
"github.com/Indra-Labs/indra/pkg/key/ecdh"
|
||||
"github.com/Indra-Labs/indra/pkg/key/prv"
|
||||
"github.com/Indra-Labs/indra/pkg/key/pub"
|
||||
"github.com/Indra-Labs/indra/pkg/nonce"
|
||||
@@ -15,6 +16,7 @@ import (
|
||||
"github.com/Indra-Labs/indra/pkg/wire/exit"
|
||||
"github.com/Indra-Labs/indra/pkg/wire/forward"
|
||||
"github.com/Indra-Labs/indra/pkg/wire/message"
|
||||
"github.com/Indra-Labs/indra/pkg/wire/noop"
|
||||
"github.com/Indra-Labs/indra/pkg/wire/purchase"
|
||||
"github.com/Indra-Labs/indra/pkg/wire/reply"
|
||||
"github.com/Indra-Labs/indra/pkg/wire/response"
|
||||
@@ -22,37 +24,64 @@ import (
|
||||
"github.com/Indra-Labs/indra/pkg/wire/token"
|
||||
)
|
||||
|
||||
func GenCiphers(prvs [3]*prv.Key, pubs [3]*pub.Key) (ciphers [3]sha256.Hash) {
|
||||
for i := range prvs {
|
||||
ciphers[i] = ecdh.Compute(prvs[i], pubs[i])
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type OnionSkins []types.Onion
|
||||
|
||||
func (o OnionSkins) Cipher(hdr, pld *pub.Key) OnionSkins {
|
||||
return append(o, &cipher.OnionSkin{Header: hdr, Payload: pld})
|
||||
return append(o, &cipher.OnionSkin{
|
||||
Header: hdr,
|
||||
Payload: pld,
|
||||
Onion: &noop.OnionSkin{},
|
||||
})
|
||||
}
|
||||
func (o OnionSkins) Confirmation(id nonce.ID) OnionSkins {
|
||||
return append(o, &confirmation.OnionSkin{ID: id})
|
||||
}
|
||||
func (o OnionSkins) Exit(port uint16, ciphers [3]sha256.Hash,
|
||||
|
||||
func (o OnionSkins) Exit(port uint16, prvs [3]*prv.Key, pubs [3]*pub.Key,
|
||||
payload slice.Bytes) OnionSkins {
|
||||
|
||||
return append(o, &exit.OnionSkin{Port: port, Ciphers: ciphers, Bytes: payload})
|
||||
return append(o, &exit.OnionSkin{
|
||||
Port: port,
|
||||
Ciphers: GenCiphers(prvs, pubs),
|
||||
Bytes: payload,
|
||||
Onion: &noop.OnionSkin{},
|
||||
})
|
||||
}
|
||||
func (o OnionSkins) Forward(ip net.IP) OnionSkins {
|
||||
return append(o, &forward.OnionSkin{IP: ip})
|
||||
return append(o, &forward.OnionSkin{IP: ip, Onion: &noop.OnionSkin{}})
|
||||
}
|
||||
func (o OnionSkins) Message(to *address.Sender, from *prv.Key) OnionSkins {
|
||||
return append(o, &message.OnionSkin{To: to, From: from})
|
||||
return append(o, &message.OnionSkin{
|
||||
To: to,
|
||||
From: from,
|
||||
Onion: &noop.OnionSkin{},
|
||||
})
|
||||
}
|
||||
func (o OnionSkins) Purchase(nBytes uint64, ciphers [3]sha256.Hash) OnionSkins {
|
||||
return append(o, &purchase.OnionSkin{NBytes: nBytes, Ciphers: ciphers})
|
||||
return append(o, &purchase.OnionSkin{
|
||||
NBytes: nBytes,
|
||||
Ciphers: ciphers,
|
||||
Onion: &noop.OnionSkin{},
|
||||
})
|
||||
}
|
||||
func (o OnionSkins) Reply(ip net.IP) OnionSkins {
|
||||
return append(o, &reply.OnionSkin{IP: ip})
|
||||
return append(o, &reply.OnionSkin{IP: ip, Onion: &noop.OnionSkin{}})
|
||||
}
|
||||
func (o OnionSkins) Response(res slice.Bytes) OnionSkins {
|
||||
return append(o, response.OnionSkin(res))
|
||||
}
|
||||
func (o OnionSkins) Session(fwd, rtn *pub.Key) OnionSkins {
|
||||
return append(o, &session.OnionSkin{
|
||||
HeaderKey: fwd, PayloadKey: rtn,
|
||||
HeaderKey: fwd,
|
||||
PayloadKey: rtn,
|
||||
Onion: &noop.OnionSkin{},
|
||||
})
|
||||
}
|
||||
func (o OnionSkins) Token(tok sha256.Hash) OnionSkins {
|
||||
|
||||
20
pkg/wire/noop/noop.go
Normal file
20
pkg/wire/noop/noop.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package noop
|
||||
|
||||
import (
|
||||
"github.com/Indra-Labs/indra/pkg/slice"
|
||||
"github.com/Indra-Labs/indra/pkg/types"
|
||||
)
|
||||
|
||||
type OnionSkin struct {
|
||||
}
|
||||
|
||||
func (x *OnionSkin) Inner() types.Onion { return nil }
|
||||
func (x *OnionSkin) Insert(o types.Onion) {}
|
||||
func (x *OnionSkin) Len() int { return 0 }
|
||||
|
||||
func (x *OnionSkin) Encode(b slice.Bytes, c *slice.Cursor) {
|
||||
}
|
||||
|
||||
func (x *OnionSkin) Decode(b slice.Bytes, c *slice.Cursor) (e error) {
|
||||
return
|
||||
}
|
||||
@@ -145,23 +145,21 @@ func SendExit(payload slice.Bytes, port uint16, client node.Node,
|
||||
replies[i] = set.Next()
|
||||
}
|
||||
|
||||
// The ciphers represent the combination of the same From key and the
|
||||
// payload keys combined, which the receiver knows means the header uses
|
||||
// HeaderKey and the message underneath use a different cipher in place
|
||||
// of the HeaderKey, the PayloadKey it corresponds to.
|
||||
ciphers := [3]sha256.Hash{
|
||||
ecdh.Compute(replies[2], client.PayloadKey),
|
||||
ecdh.Compute(replies[1], hop[4].PayloadKey),
|
||||
ecdh.Compute(replies[0], hop[3].PayloadKey),
|
||||
}
|
||||
|
||||
var prvs [3]*prv.Key
|
||||
var pubs [3]*pub.Key
|
||||
prvs[0] = replies[2]
|
||||
prvs[1] = replies[1]
|
||||
prvs[2] = replies[0]
|
||||
pubs[0] = client.PayloadKey
|
||||
pubs[1] = hop[4].PayloadKey
|
||||
pubs[2] = hop[3].PayloadKey
|
||||
return OnionSkins{}.
|
||||
Message(address.FromPubKey(hop[0].HeaderKey), set.Next()).
|
||||
Forward(hop[1].IP).
|
||||
Message(address.FromPubKey(hop[1].HeaderKey), set.Next()).
|
||||
Forward(hop[2].IP).
|
||||
Message(address.FromPubKey(hop[2].HeaderKey), set.Next()).
|
||||
Exit(port, ciphers, payload).
|
||||
Exit(port, prvs, pubs, payload).
|
||||
Reply(hop[3].IP).
|
||||
Message(address.FromPubKey(hop[3].HeaderKey), replies[0]).
|
||||
Reply(hop[4].IP).
|
||||
|
||||
@@ -46,7 +46,7 @@ func (x *OnionSkin) Encode(b slice.Bytes, c *slice.Cursor) {
|
||||
}
|
||||
|
||||
func (x *OnionSkin) Decode(b slice.Bytes, c *slice.Cursor) (e error) {
|
||||
if len(b[*c:]) < MinLen {
|
||||
if len(b[*c:]) < MinLen-magicbytes.Len {
|
||||
return magicbytes.TooShort(len(b[*c:]), MinLen, string(Magic))
|
||||
}
|
||||
x.NBytes = slice.DecodeUint64(
|
||||
|
||||
@@ -10,11 +10,11 @@ var (
|
||||
// GitRef is the gitref, as in refs/heads/branchname.
|
||||
GitRef = "refs/heads/main"
|
||||
// ParentGitCommit is the commit hash of the parent HEAD.
|
||||
ParentGitCommit = "5ae9415225a073e9535ff3c005243e8c59ba8e89"
|
||||
ParentGitCommit = "4a1ab0f39c1c71fa5f9e0045ec701f671643ec6e"
|
||||
// BuildTime stores the time when the current binary was built.
|
||||
BuildTime = "2022-12-24T11:17:07Z"
|
||||
BuildTime = "2022-12-24T12:28:37Z"
|
||||
// SemVer lists the (latest) git tag on the build.
|
||||
SemVer = "v0.0.227"
|
||||
SemVer = "v0.0.228"
|
||||
// PathBase is the path base returned from runtime caller.
|
||||
PathBase = "/home/loki/src/github.com/Indra-Labs/indra/"
|
||||
// Major is the major number from the tag.
|
||||
@@ -22,7 +22,7 @@ var (
|
||||
// Minor is the minor number from the tag.
|
||||
Minor = 0
|
||||
// Patch is the patch version number from the tag.
|
||||
Patch = 227
|
||||
Patch = 228
|
||||
)
|
||||
|
||||
// Version returns a pretty printed version information string.
|
||||
|
||||
Reference in New Issue
Block a user