From d0accd1f805c37e57b5cfa5642a5271c69c63cf6 Mon Sep 17 00:00:00 2001 From: David Vennik Date: Sun, 11 Dec 2022 22:55:17 +0100 Subject: [PATCH] Massive restructure of message addressing scheme and eliminating cruft from packet --- pkg/message/message.go | 60 +++++++++++-------------------------- pkg/message/message_test.go | 10 ++----- pkg/wire/wire.go | 57 ++++++++++++++++++++++------------- version.go | 8 ++--- 4 files changed, 60 insertions(+), 75 deletions(-) diff --git a/pkg/message/message.go b/pkg/message/message.go index 16c79908..c0eae196 100644 --- a/pkg/message/message.go +++ b/pkg/message/message.go @@ -28,9 +28,6 @@ var ( // container with parameters for Reed Solomon Forward Error Correction and // contains previously seen cipher keys so the correspondent can free them. type Message struct { - // Type is the type of message, Forward or Return, and for future - // expansion can also carry a code to specify a different cipher mode. - Type byte // Seq specifies the segment number of the message, 4 bytes long. Seq uint16 // Length is the number of segments in the batch @@ -52,75 +49,52 @@ func (p *Message) GetOverhead() int { const Overhead = slice.Uint16Len + slice.Uint32Len + 1 + KeyEnd -// Packets is a slice of pointers to packets. -type Packets []*Message - -// sort.Interface implementation. - -func (p Packets) Len() int { return len(p) } -func (p Packets) Less(i, j int) bool { return p[i].Seq < p[j].Seq } -func (p Packets) Swap(i, j int) { p[i], p[j] = p[j], p[i] } - -// EP defines the parameters for creating a (split) packet given a set of keys, -// cipher, and data. To, From, Blk and Data are required, Parity is optional, -// set it to define a level of Reed Solomon redundancy on the split packets. -// Seen should be populated to send a signal to the other side of keys that have -// been seen at time of constructing this packet that can now be discarded as -// they will not be used to generate a cipher again. -type EP struct { - Type byte - To *address.Sender - From *prv.Key - Length int - Data []byte +type Addresses struct { + To *address.Sender + From *prv.Key } -// GetOverhead returns the amount of the message that will not be part of the -// payload. -func (ep EP) GetOverhead() int { - return Overhead +func Address(To *address.Sender, From *prv.Key) *Addresses { + return &Addresses{To: To, From: From} } const ( CheckEnd = 4 - TypeEnd = CheckEnd + 1 - NonceEnd = TypeEnd + nonce.IVLen + NonceEnd = CheckEnd + nonce.IVLen AddressEnd = NonceEnd + address.Len KeyEnd = AddressEnd + pub.KeyLen - - ForwardMessage byte = iota - ReturnMessage ) // Encode creates a Message, encrypts the payload using the given private from // key and the public to key, serializes the form, signs the bytes and appends // the signature to the end. -func Encode(ep EP) (pkt []byte, e error) { +func Encode(To *address.Sender, From *prv.Key, d []byte) (pkt []byte, + e error) { + var blk cipher.Block - if blk = ciph.GetBlock(ep.From, ep.To.Key); check(e) { + if blk = ciph.GetBlock(From, To.Key); check(e) { return } nonc := nonce.New() var to address.Cloaked - to, e = ep.To.GetCloak() + to, e = To.GetCloak() Length := slice.NewUint32() - slice.EncodeUint32(Length, ep.Length) + slice.EncodeUint32(Length, len(d)) // Concatenate the message pieces together into a single byte slice. pkt = slice.Cat( // f.Nonce[:], // 16 bytes \ // f.To[:], // 8 bytes | make([]byte, KeyEnd), Length, // 4 bytes - ep.Data, + d, ) // Encrypt the encrypted part of the data. ciph.Encipher(blk, nonc, pkt[KeyEnd:]) // Sign the packet. var pubKey pub.Bytes - pubKey = pub.Derive(ep.From).ToBytes() - pkt[CheckEnd] = ep.Type + pubKey = pub.Derive(From).ToBytes() // Copy nonce, address, check and signature over top of the header. - copy(pkt[TypeEnd:NonceEnd], nonc[:]) + copy(pkt[CheckEnd:NonceEnd], nonc[:]) copy(pkt[NonceEnd:AddressEnd], to[:]) copy(pkt[AddressEnd:KeyEnd], pubKey[:]) // last bot not least, the packet check header, which protects the @@ -179,10 +153,10 @@ func Decode(d []byte, from *pub.Key, to *prv.Key) (f *Message, e error) { // Trim off the signature and hash, we already have the key and have // validated the checksum. - f = &Message{Type: d[CheckEnd]} + f = &Message{} // copy the nonce var nonc nonce.IV - copy(nonc[:], d[TypeEnd:NonceEnd]) + copy(nonc[:], d[CheckEnd:NonceEnd]) var blk cipher.Block if blk = ciph.GetBlock(to, from); check(e) { return diff --git a/pkg/message/message_test.go b/pkg/message/message_test.go index 2c09bb04..7e256806 100644 --- a/pkg/message/message_test.go +++ b/pkg/message/message_test.go @@ -29,14 +29,8 @@ func TestEncode_Decode(t *testing.T) { } addr := address.FromPubKey(rP) var pkt []byte - params := EP{ - Type: ForwardMessage, - To: addr, - From: sp, - Data: payload, - Length: msgSize, - } - if pkt, e = Encode(params); check(e) { + + if pkt, e = Encode(addr, sp, payload); check(e) { t.Error(e) } var to address.Cloaked diff --git a/pkg/wire/wire.go b/pkg/wire/wire.go index 9af33dba..5664394c 100644 --- a/pkg/wire/wire.go +++ b/pkg/wire/wire.go @@ -1,11 +1,11 @@ package wire import ( - "crypto/cipher" "net" "github.com/Indra-Labs/indra/pkg/ifc" "github.com/Indra-Labs/indra/pkg/key/pub" + "github.com/Indra-Labs/indra/pkg/message" "github.com/Indra-Labs/indra/pkg/nonce" ) @@ -15,10 +15,6 @@ const MagicLen = 3 type MessageMagic string -func GetMagic(s string) (mm MessageMagic) { - return MessageMagic(s[:MagicLen]) -} - type Message interface { Encode() (o ifc.Message) } @@ -34,17 +30,18 @@ var ( // Forward is just an IP address and a wrapper for another message. type Forward struct { - cipher.Block + *message.Addresses net.IP Message } -func (rm *Forward) Encode() (o ifc.Message) { - ipLen := len(rm.IP) - msg := rm.Message.Encode() +func (fw *Forward) Encode() (o ifc.Message) { + ipLen := len(fw.IP) + msg := fw.Message.Encode() + msg, _ = message.Encode(fw.To, fw.From, msg) fwd := make([]byte, ipLen+1) fwd[0] = byte(ipLen) - copy(fwd[1:], rm.IP) + copy(fwd[1:], fw.IP) o = append(append(ifc.Message(ForwardMagic), fwd...), msg...) return @@ -57,7 +54,7 @@ func DecodeForward(msg ifc.Message) (rm *Forward, e error) { // Exit messages are the layer of a message after two Forward packets that // provides an exit address and type Exit struct { - cipher.Block + *message.Addresses // Port identifies the type of service as well as being the port used // by the service to be relayed to. Notice there is no IP address, this // is because Indranet only forwards to exits of decentralised services @@ -74,7 +71,9 @@ type Exit struct { Message } -func (rm *Exit) Encode() (o ifc.Message) { +func (ex *Exit) Encode() (o ifc.Message) { + msg := ex.Message.Encode() + msg, _ = message.Encode(ex.To, ex.From, msg) return } @@ -87,14 +86,16 @@ func DecodeExit(msg ifc.Message) (rm *Exit, e error) { // encrypting the first 16 bytes of the header and if one of the magic bytes is // not found type Return struct { - cipher.Block + *message.Addresses nonce.ID // IP is the address of the next relay in the return leg of a circuit. net.IP Message } -func (rm *Return) Encode() (o ifc.Message) { +func (rt *Return) Encode() (o ifc.Message) { + msg := rt.Message.Encode() + msg, _ = message.Encode(rt.To, rt.From, msg) return } @@ -107,13 +108,15 @@ func DecodeReturn(msg ifc.Message) (rm *Return, e error) { // of Forward messages, ensuring that the node cannot discover where this comes // from but allows a Return public key to be provided for a Purchase. type Cipher struct { - cipher.Block + *message.Addresses nonce.ID Key pub.Bytes Forward } -func (rm *Cipher) Encode() (o ifc.Message) { +func (ci *Cipher) Encode() (o ifc.Message) { + msg := ci.Forward.Encode() + msg, _ = message.Encode(ci.To, ci.From, msg) return } @@ -130,13 +133,15 @@ func DecodeCipher(msg ifc.Message) (rm *Cipher, e error) { // forwards through two hops to the router that will issue the Session, plus two // more Return layers for carrying the Session back to the client. type Purchase struct { - cipher.Block + *message.Addresses Bytes int Receipt ifc.Message Return } -func (rm *Purchase) Encode() (o ifc.Message) { +func (pr *Purchase) Encode() (o ifc.Message) { + msg := pr.Return.Encode() + msg, _ = message.Encode(pr.To, pr.From, msg) return } @@ -151,16 +156,28 @@ func DecodePurchase(msg ifc.Message) (rm *Purchase, e error) { // relay that issues a Session, ensuring that the Exit cannot see the inner // layers of the Return messages. type Session struct { - cipher.Block + *message.Addresses ForwardKey pub.Bytes ReturnKey pub.Bytes Return } -func (rm *Session) Encode() (o ifc.Message) { +func (se *Session) Encode() (o ifc.Message) { + msg := se.Return.Encode() + msg, _ = message.Encode(se.To, se.From, msg) return } func DecodeSession(msg ifc.Message) (rm *Session, e error) { return } + +type Raw struct { + *message.Addresses + Bytes []byte +} + +func (r Raw) Encode() (o ifc.Message) { + o, _ = message.Encode(r.To, r.From, r.Bytes) + return +} diff --git a/version.go b/version.go index 5bb54abb..5195e7dc 100644 --- a/version.go +++ b/version.go @@ -13,11 +13,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 = "94f170b7663d743c9c50335024d42590750f0a69" + ParentGitCommit = "a40766089d9ead6c8b7ed52a500aa5f91c72b882" // BuildTime stores the time when the current binary was built. - BuildTime = "2022-12-11T22:02:30+01:00" + BuildTime = "2022-12-11T22:55:17+01:00" // SemVer lists the (latest) git tag on the build. - SemVer = "v0.0.181" + SemVer = "v0.0.182" // 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. @@ -25,7 +25,7 @@ var ( // Minor is the minor number from the tag. Minor = 0 // Patch is the patch version number from the tag. - Patch = 181 + Patch = 182 ) // Version returns a pretty printed version information string.