Drafted all onion message layer types

and including automation for constructing and encrypting onion layers
This commit is contained in:
David Vennik
2022-12-13 09:23:51 +01:00
parent d0accd1f80
commit aeb44fe48b
13 changed files with 372 additions and 233 deletions

View File

@@ -5,6 +5,7 @@ import (
"unsafe"
"github.com/Indra-Labs/indra"
"github.com/Indra-Labs/indra/pkg/slice"
log2 "github.com/cybriq/proc/pkg/log"
)
@@ -14,18 +15,17 @@ var (
)
type Transport interface {
Send(b Message)
Receive() <-chan Message
Send(b Bytes)
Receive() <-chan Bytes
}
type Message []byte
type Bytes []byte
func ToMessage(b []byte) (msg Message) { return b }
func (m Message) ToBytes() []byte { return m }
func (m Message) Copy() (o Message) {
o = make(Message, len(m))
copy(o, m)
return
func ToBytes(b []byte) (msg Bytes) { return b }
func (m Bytes) ToBytes() []byte { return m }
func (m Bytes) Len() int { return len(m) }
func (m Bytes) Copy(start, end *slice.Cursor, bytes Bytes) {
copy(m[*start:*end], bytes[:*end-*start])
}
type U64Slice []uint64
@@ -42,7 +42,7 @@ func (u U64Slice) Copy() (o U64Slice) {
// intended to be used with short byte slices like cipher nonces and hashes, so
// it usually won't trigger allocations off stack and very often won't trigger
// a copy on stack, saving a lot of time in a short, oft repeated operations.
func (m Message) ToU64Slice() (u U64Slice) {
func (m Bytes) ToU64Slice() (u U64Slice) {
mLen := uint64(len(m))
uLen := int(mLen / 8)
mMod := mLen % 8
@@ -84,10 +84,10 @@ func (u U64Slice) XOR(v U64Slice) {
}
}
func (u U64Slice) ToMessage() (m Message) {
func (u U64Slice) ToMessage() (m Bytes) {
// length is encoded into the last element
mLen := int(u[len(u)-1])
m = make(Message, 0, 0)
m = make(Bytes, 0, 0)
// With the slice now long enough to be safely converted to []uint64
// plus an extra uint64 to store the original length we can coerce the
// type using unsafe.

View File

@@ -10,7 +10,7 @@ import (
func TestMessage_ToU64Slice(t *testing.T) {
var e error
var msg1 Message
var msg1 Bytes
if msg1, _, e = testutils.GenerateTestMessage(33); check(e) {
t.Error(e)
t.FailNow()
@@ -25,21 +25,21 @@ func TestMessage_ToU64Slice(t *testing.T) {
func TestU64Slice_XOR(t *testing.T) {
var e error
var msg1 Message
var msg1 Bytes
if msg1, _, e = testutils.GenerateTestMessage(33); check(e) {
t.Error(e)
t.FailNow()
}
hash1 := sha256.Single(msg1)
uMsg1 := msg1.ToU64Slice()
var msg2 Message
var msg2 Bytes
if msg2, _, e = testutils.GenerateTestMessage(33); check(e) {
t.Error(e)
t.FailNow()
}
// log.I.S(msg2)
uMsg2 := msg2.ToU64Slice()
var msg3 Message
var msg3 Bytes
if msg3, _, e = testutils.GenerateTestMessage(33); check(e) {
t.Error(e)
t.FailNow()
@@ -56,3 +56,15 @@ func TestU64Slice_XOR(t *testing.T) {
t.FailNow()
}
}
func TestBytes_Copy(t *testing.T) {
var e error
var msg Bytes
if msg, _, e = testutils.GenerateTestMessage(33); check(e) {
t.Error(e)
t.FailNow()
}
buf := make(Bytes, 65)
buf.Copy(10, 20, msg)
log.I.S(msg, buf)
}

View File

@@ -70,11 +70,12 @@ func FromBytes(pkb pub.Bytes) (s *Sender, e error) {
// generates the 5 bytes at the end of the Cloaked code. In this way the
// source public key it relates to is hidden to any who don't have this public
// key, which only the parties know.
func (s Sender) GetCloak() (c Cloaked, e error) {
func (s Sender) GetCloak() (c Cloaked) {
var blinder Blinder
var n int
var e error
if n, e = rand.Read(blinder[:]); check(e) && n != BlindLen {
return
panic("no entropy")
}
c = Cloak(blinder, s.Key.ToBytes())
return
@@ -83,7 +84,7 @@ func (s Sender) GetCloak() (c Cloaked, e error) {
func Cloak(b Blinder, key pub.Bytes) (c Cloaked) {
h := sha256.Single(append(b[:], key[:]...))
copy(c[:BlindLen], b[:BlindLen])
copy(c[HashLen:], h[:HashLen])
copy(c[BlindLen:BlindLen+HashLen], h[:HashLen])
return
}

View File

@@ -17,7 +17,7 @@ func TestAddress(t *testing.T) {
r := NewReceiver(sendPriv)
s := FromPubKey(r.Pub)
var cloaked Cloaked
cloaked, e = s.GetCloak()
cloaked = s.GetCloak()
if !r.Match(cloaked) {
t.Error("failed to recognise cloaked address")
}

View File

@@ -38,17 +38,6 @@ type Message struct {
Data []byte
}
// GetOverhead returns the packet frame overhead given the settings found in the
// packet.
func (p *Message) GetOverhead() int {
return Overhead
}
// Overhead is the base overhead on a packet, use GetOverhead to add any extra
// as found in a Message.
const Overhead = slice.Uint16Len +
slice.Uint32Len + 1 + KeyEnd
type Addresses struct {
To *address.Sender
From *prv.Key
@@ -77,7 +66,7 @@ func Encode(To *address.Sender, From *prv.Key, d []byte) (pkt []byte,
}
nonc := nonce.New()
var to address.Cloaked
to, e = To.GetCloak()
to = To.GetCloak()
Length := slice.NewUint32()
slice.EncodeUint32(Length, len(d))
// Concatenate the message pieces together into a single byte slice.
@@ -105,7 +94,7 @@ func Encode(To *address.Sender, From *prv.Key, d []byte) (pkt []byte,
}
// GetKeys returns the To field of the message in order, checks the packet
// checksum and recovers the public key signing it.
// checksum and recovers the public key.
//
// After this, if the matching private key to the cloaked address returned is
// found, it is combined with the public key to generate the cipher and the

View File

@@ -9,6 +9,7 @@ import (
"encoding/binary"
"github.com/Indra-Labs/indra"
"github.com/Indra-Labs/indra/pkg/ifc"
"github.com/Indra-Labs/indra/pkg/sha256"
log2 "github.com/cybriq/proc/pkg/log"
)
@@ -55,11 +56,20 @@ func Cat(chunks ...[]byte) (pkt []byte) {
return
}
var put64 = binary.LittleEndian.PutUint64
var get64 = binary.LittleEndian.Uint64
var put32 = binary.LittleEndian.PutUint32
var get32 = binary.LittleEndian.Uint32
var put16 = binary.LittleEndian.PutUint16
var get16 = binary.LittleEndian.Uint16
// DecodeUint64 returns an int containing the little endian encoded 64-bit value
// stored in a 4 byte long slice
func DecodeUint64(b []byte) uint64 { return get64(b) }
// EncodeUint64 puts an int into a uint32 and then into 8 byte long slice.
func EncodeUint64(b []byte, n uint64) { put64(b, n) }
// DecodeUint32 returns an int containing the little endian encoded 32bit value
// stored in a 4 byte long slice
func DecodeUint32(b []byte) int { return int(get32(b)) }
@@ -89,17 +99,15 @@ func DecodeUint16(b []byte) int { return int(get16(b)) }
// EncodeUint16 puts an int into a uint32 and then into 2 byte long slice.
func EncodeUint16(b []byte, n int) { put16(b, uint16(n)) }
const Uint64Len = 8
const Uint32Len = 4
const Uint24Len = 3
const Uint16Len = 2
type Size32 []byte
type Size24 []byte
type Size16 []byte
func NewUint32() Size32 { return make(Size32, Uint32Len) }
func NewUint24() Size24 { return make(Size24, Uint24Len) }
func NewUint16() Size16 { return make(Size16, Uint16Len) }
func NewUint64() ifc.Bytes { return make(ifc.Bytes, Uint64Len) }
func NewUint32() ifc.Bytes { return make(ifc.Bytes, Uint32Len) }
func NewUint24() ifc.Bytes { return make(ifc.Bytes, Uint24Len) }
func NewUint16() ifc.Bytes { return make(ifc.Bytes, Uint16Len) }
func NoisePad(l int) (noise []byte) {
var seed sha256.Hash
@@ -121,3 +129,10 @@ func NoisePad(l int) (noise []byte) {
}
return
}
type Cursor int
func (c *Cursor) Inc(v int) *Cursor {
*c += Cursor(v)
return c
}

View File

@@ -4,13 +4,13 @@ import (
"github.com/Indra-Labs/indra/pkg/ifc"
)
type Sim chan ifc.Message
type Sim chan ifc.Bytes
func (d Sim) Send(b ifc.Message) {
func (d Sim) Send(b ifc.Bytes) {
d <- b
}
func (d Sim) Receive() <-chan ifc.Message {
func (d Sim) Receive() <-chan ifc.Bytes {
return d
}

View File

@@ -4,13 +4,13 @@ import (
"github.com/Indra-Labs/indra/pkg/ifc"
)
type Dispatcher chan ifc.Message
type Dispatcher chan ifc.Bytes
func (d Dispatcher) Send(b ifc.Message) {
func (d Dispatcher) Send(b ifc.Bytes) {
d <- b
}
func (d Dispatcher) Receive() <-chan ifc.Message {
func (d Dispatcher) Receive() <-chan ifc.Bytes {
return d
}

305
pkg/wire/onionskins.go Normal file
View File

@@ -0,0 +1,305 @@
package wire
import (
"crypto/cipher"
"net"
"github.com/Indra-Labs/indra"
"github.com/Indra-Labs/indra/pkg/ciph"
"github.com/Indra-Labs/indra/pkg/ifc"
"github.com/Indra-Labs/indra/pkg/key/address"
"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"
log2 "github.com/cybriq/proc/pkg/log"
)
var (
log = log2.GetLogger(indra.PathBase)
check = log.E.Chk
)
// MagicLen is 3 to make it nearly impossible that the wrong cipher will yield a
// valid Magic string as listed below.
const MagicLen = 3
type Onion interface {
Encode(o ifc.Bytes, c *slice.Cursor)
Len() int
}
var (
ForwardMagic = ifc.Bytes("fwd")
ExitMagic = ifc.Bytes("exi")
ReturnMagic = ifc.Bytes("rtn")
CipherMagic = ifc.Bytes("cif")
PurchaseMagic = ifc.Bytes("prc")
SessionMagic = ifc.Bytes("ses")
AcknowledgementMagic = ifc.Bytes("ack")
ResponseMagic = ifc.Bytes("res")
TokenMagic = ifc.Bytes("tok")
)
// Message is the generic top level wrapper for an Onion. All following messages
// are wrapped inside this.
type Message struct {
To *address.Sender
From *prv.Key
// The following field is only populated in the outermost layer.
ifc.Bytes
Onion
}
// NewOnion creates a new Onion. It accepts a recursively structured message
// layering definition which all parts know their length, and it stores a buffer.
//
// Note that this is only required at the top level, following messages inside
// the passed message do not need initialisation as there is only one buffer
// needed for the entire message, though each layer is started by a Message.
//
// Example usage:
/*
o := NewOnion(&Message{
To: to,
From: from,
Onion: &Message{
To: to,
From: from,
Onion: &Forward{
IP: 10.0.0.1,
// ...
}
}
*/
// Of course normally onions would not be decoratively structured like this,
// except Cipher and "ping" messages which have a fixed layer structure.
//
// Note that the cursor is created here as it can't be easily embedded through
// layers of messages wrapped in each other, so this function must be called,
// and then Encode method can be called separately with nil for the bytes and
// this returned cursor variable. The Bytes don't need to be passed in as the
// top level created by this constructor generates one after interrogating all
// the layers for their length values.
func NewOnion(msg *Message) (o Onion, c *slice.Cursor) {
c = new(slice.Cursor)
msg.Bytes = make(ifc.Bytes, msg.Len())
return msg, c
}
const OnionHeaderLen = 4 + nonce.IVLen + address.Len + pub.KeyLen
func (on *Message) Len() int { return MagicLen + OnionHeaderLen + on.Onion.Len() }
func (on *Message) Encode(o ifc.Bytes, c *slice.Cursor) {
// The first level message contains the Bytes, but the inner layers do
// not. The inner layers will be passed this buffer, but the first needs
// to have it copied from its original location.
if o == nil {
o = on.Bytes
}
// We write the checksum last so save the cursor position here.
checkStart := *c
checkEnd := checkStart + 4
// Generate a new nonce and copy it in.
n := nonce.New()
o.Copy(c.Inc(4), c.Inc(nonce.IVLen), n[:])
// Derive the cloaked key and copy it in.
to := on.To.GetCloak()
o.Copy(c, c.Inc(address.Len), to[:])
// Call the tree of onions to perform their encoding.
on.Onion.Encode(o, c)
// Then we can encrypt the message segment
var e error
var blk cipher.Block
if blk = ciph.GetBlock(on.From, on.To.Key); check(e) {
panic(e)
}
ciph.Encipher(blk, n, o[checkEnd:])
// Get the hash of the message and truncate it to the checksum at the
// start of the message. Every layer of the onion has a Message and an
// onion inside it, the Message takes care of the encryption. This saves
// on complications as every layer is header first, message after, with
// wrapped messages inside each message afterwards.
hash := sha256.Single(o[checkEnd:])
copy(o[checkStart:checkEnd], hash[:4])
}
// Forward is just an IP address and a wrapper for another message.
type Forward struct {
net.IP
Onion
}
func (fw *Forward) Len() int { return MagicLen + len(fw.IP) + 1 + fw.Onion.Len() }
func (fw *Forward) Encode(o ifc.Bytes, c *slice.Cursor) {
o.Copy(c, c.Inc(MagicLen), ForwardMagic)
o[*c] = byte(len(fw.IP))
o.Copy(c.Inc(1), c.Inc(len(fw.IP)), ifc.Bytes(fw.IP))
fw.Onion.Encode(o, c)
}
// Exit messages are the layer of a message after two Forward packets that
// provides an exit address and
type Exit struct {
// 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
// also running on the same machine. This service could be a proxy, of
// course, if configured this way. This could be done by tunneling from
// a local Socks5 proxy into Indranet and the exit node also having
// this.
Port uint16
// Cipher is a set of 3 symmetric ciphers that are to be used in their
// given order over the reply message from the service.
Cipher [3]sha256.Hash
// Bytes are the message to be passed to the exit service.
ifc.Bytes
// Return is the encoded message with the three hops using the Return
// keys for the relevant relays, encrypted progressively. Note that this
// message uses a different Cipher than the one above
Return
}
func (ex *Exit) Len() int {
return MagicLen + slice.Uint16Len + 3*sha256.Len + ex.Bytes.Len() +
ex.Return.Len()
}
func (ex *Exit) Encode(o ifc.Bytes, c *slice.Cursor) {
o.Copy(c, c.Inc(MagicLen), ExitMagic)
port := slice.NewUint16()
slice.EncodeUint16(port, int(ex.Port))
o.Copy(c, c.Inc(slice.Uint16Len), port)
o.Copy(c, c.Inc(sha256.Len), ex.Cipher[0][:])
o.Copy(c, c.Inc(sha256.Len), ex.Cipher[1][:])
o.Copy(c, c.Inc(sha256.Len), ex.Cipher[1][:])
bytesLen := slice.NewUint32()
slice.EncodeUint32(bytesLen, len(ex.Bytes))
o.Copy(c, c.Inc(slice.Uint32Len), bytesLen)
o.Copy(c, c.Inc(len(ex.Bytes)), ex.Bytes)
ex.Return.Encode(o, c)
}
// Return messages are distinct from Forward messages in that the header
// encryption uses a different secret than the payload. The magic bytes signal
// this to the relay that receives this, which then looks up the Return key
// matching the To address in the message header.
type Return struct {
// IP is the address of the next relay in the return leg of a circuit.
net.IP
Onion
}
func (rt *Return) Len() int { return MagicLen + len(rt.IP) + 1 + rt.Onion.Len() }
func (rt *Return) Encode(o ifc.Bytes, c *slice.Cursor) {
o.Copy(c, c.Inc(MagicLen), ReturnMagic)
o[*c] = byte(len(rt.IP))
o.Copy(c.Inc(1), c.Inc(len(rt.IP)), ifc.Bytes(rt.IP))
rt.Onion.Encode(o, c)
}
// Cipher delivers a public key to be used in association with a Return
// specifically in the situation of a node bootstrapping that doesn't have
// sessions yet. The ID allows the client to associate the Cipher to the
// Purchase.
type Cipher struct {
nonce.ID
Key pub.Bytes
Forward
}
func (ci *Cipher) Len() int { return MagicLen + pub.KeyLen + ci.Forward.Len() }
func (ci *Cipher) Encode(o ifc.Bytes, c *slice.Cursor) {
o.Copy(c, c.Inc(nonce.IDLen), ci.ID[:])
o.Copy(c, c.Inc(MagicLen), CipherMagic)
o.Copy(c.Inc(1), c.Inc(sha256.Len), ci.Key[:])
ci.Forward.Encode(o, c)
}
// Purchase is a message that is sent after first forwarding a Lighting payment
// of an amount corresponding to the number of bytes requested based on the
// price advertised for Exit traffic by a relay. The Receipt is the confirmation
// after requesting an Invoice for the amount and then paying it.
//
// This message contains a Return message, which enables payments to proxy
// 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.
//
// Purchases have an ID created by the client.
type Purchase struct {
Value uint64
Return
}
func (pr *Purchase) Len() int {
return MagicLen + slice.Uint64Len + pr.Return.Len()
}
func (pr *Purchase) Encode(o ifc.Bytes, c *slice.Cursor) {
o.Copy(c, c.Inc(MagicLen), PurchaseMagic)
value := slice.NewUint64()
slice.EncodeUint64(value, pr.Value)
o.Copy(c, c.Inc(slice.Uint64Len), value)
pr.Return.Encode(o, c)
}
// Session is a message containing two public keys which identify to a relay the
// session to account bytes on, this is wrapped in two Return message layers by
// the seller. Forward keys are used for encryption in Forward and Exit
// messages, and Return keys are separate and are only known to the client and
// relay that issues a Session, ensuring that the Exit cannot see the inner
// layers of the Return messages.
type Session struct {
ForwardKey pub.Bytes
ReturnKey pub.Bytes
Return
}
func (se *Session) Encode(o ifc.Bytes, c *slice.Cursor) {
o.Copy(c, c.Inc(MagicLen), SessionMagic)
o.Copy(c, c.Inc(pub.KeyLen), se.ForwardKey[:])
o.Copy(c, c.Inc(pub.KeyLen), se.ReturnKey[:])
se.Return.Encode(o, c)
}
// Acknowledgement messages just contain a nonce ID, these are used to terminate
// ping and Cipher onion messages which confirms relaying was successful.
type Acknowledgement struct {
nonce.ID
}
func (ak *Acknowledgement) Len() int { return MagicLen + nonce.IDLen }
func (ak *Acknowledgement) Encode(o ifc.Bytes, c *slice.Cursor) {
o.Copy(c, c.Inc(MagicLen), AcknowledgementMagic)
o.Copy(c, c.Inc(pub.KeyLen), ak.ID[:])
}
type Response ifc.Bytes
func (rs Response) Len() int { return MagicLen + len(rs) + 4 }
func (rs Response) Encode(o ifc.Bytes, c *slice.Cursor) {
o.Copy(c, c.Inc(MagicLen), ResponseMagic)
bytesLen := slice.NewUint32()
slice.EncodeUint32(bytesLen, len(rs))
o.Copy(c, c.Inc(slice.Uint32Len), bytesLen)
o.Copy(c, c.Inc(len(rs)), ifc.Bytes(rs))
}
type Token sha256.Hash
func (tk Token) Len() int { return MagicLen + sha256.Len }
func (tk Token) Encode(o ifc.Bytes, c *slice.Cursor) {
o.Copy(c, c.Inc(MagicLen), TokenMagic)
o.Copy(c, c.Inc(sha256.Len), tk[:])
}

View File

@@ -1,183 +0,0 @@
package wire
import (
"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"
)
// MagicLen is 3 to make it nearly impossible that the wrong cipher will yield a
// valid Magic string as listed below.
const MagicLen = 3
type MessageMagic string
type Message interface {
Encode() (o ifc.Message)
}
var (
ForwardMagic = MessageMagic("fwd")
ExitMagic = MessageMagic("exi")
ReturnMagic = MessageMagic("rtn")
CipherMagic = MessageMagic("cif")
PurchaseMagic = MessageMagic("prc")
SessionMagic = MessageMagic("ses")
)
// Forward is just an IP address and a wrapper for another message.
type Forward struct {
*message.Addresses
net.IP
Message
}
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:], fw.IP)
o = append(append(ifc.Message(ForwardMagic), fwd...), msg...)
return
}
func DecodeForward(msg ifc.Message) (rm *Forward, e error) {
return
}
// Exit messages are the layer of a message after two Forward packets that
// provides an exit address and
type Exit struct {
*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
// also running on the same machine. This service could be a proxy, of
// course, if configured this way.
Port uint16
// Cipher is a set of 3 symmetric ciphers that are to be used in their
// given order over the reply message from the service.
Cipher [3][32]byte
// Return is the encoded message with the three hops using the Return
// keys for the relevant relays, encrypted progressively. Note that this
// message uses a different Cipher than the one above
Return ifc.Message
Message
}
func (ex *Exit) Encode() (o ifc.Message) {
msg := ex.Message.Encode()
msg, _ = message.Encode(ex.To, ex.From, msg)
return
}
func DecodeExit(msg ifc.Message) (rm *Exit, e error) {
return
}
// Return messages are distinct from Forward messages in that the header
// encryption uses a different secret than the payload. Relays identify this by
// encrypting the first 16 bytes of the header and if one of the magic bytes is
// not found
type Return struct {
*message.Addresses
nonce.ID
// IP is the address of the next relay in the return leg of a circuit.
net.IP
Message
}
func (rt *Return) Encode() (o ifc.Message) {
msg := rt.Message.Encode()
msg, _ = message.Encode(rt.To, rt.From, msg)
return
}
func DecodeReturn(msg ifc.Message) (rm *Return, e error) {
return
}
// Cipher delivers a public key to be used in association with a Return with the
// matching ID. This is wrapped in two Forward messages and contains two layers
// 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 {
*message.Addresses
nonce.ID
Key pub.Bytes
Forward
}
func (ci *Cipher) Encode() (o ifc.Message) {
msg := ci.Forward.Encode()
msg, _ = message.Encode(ci.To, ci.From, msg)
return
}
func DecodeCipher(msg ifc.Message) (rm *Cipher, e error) {
return
}
// Purchase is a message that is sent after first forwarding a Lighting payment
// of an amount corresponding to the number of bytes requested based on the
// price advertised for Exit traffic by a relay. The Receipt is the confirmation
// after requesting an Invoice for the amount and then paying it.
//
// This message contains a Return message, which enables payments to proxy
// 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 {
*message.Addresses
Bytes int
Receipt ifc.Message
Return
}
func (pr *Purchase) Encode() (o ifc.Message) {
msg := pr.Return.Encode()
msg, _ = message.Encode(pr.To, pr.From, msg)
return
}
func DecodePurchase(msg ifc.Message) (rm *Purchase, e error) {
return
}
// Session is a message containing two public keys which identify to a relay the
// session to account bytes on, this is wrapped in two Return message layers by
// the seller. Forward keys are used for encryption in Forward and Exit
// messages, and Return keys are separate and are only known to the client and
// relay that issues a Session, ensuring that the Exit cannot see the inner
// layers of the Return messages.
type Session struct {
*message.Addresses
ForwardKey pub.Bytes
ReturnKey pub.Bytes
Return
}
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
}

View File

@@ -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 = "a40766089d9ead6c8b7ed52a500aa5f91c72b882"
ParentGitCommit = "af876fa30c7b1c97ffe9c3e13e213bbdc7275460"
// BuildTime stores the time when the current binary was built.
BuildTime = "2022-12-11T22:55:17+01:00"
BuildTime = "2022-12-13T09:23:51+01:00"
// SemVer lists the (latest) git tag on the build.
SemVer = "v0.0.182"
SemVer = "v0.0.183"
// 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 = 182
Patch = 183
)
// Version returns a pretty printed version information string.