All Decode functions implemented
This commit is contained in:
@@ -60,7 +60,7 @@ package client
|
||||
// t.FailNow()
|
||||
// }
|
||||
// // Create the onion
|
||||
// var lastMsg ifc.Header
|
||||
// var lastMsg ifc.Message
|
||||
// lastMsg, _, e = testutils.GenerateTestMessage(32)
|
||||
// original := make([]byte, 32)
|
||||
// copy(original, lastMsg)
|
||||
@@ -70,7 +70,7 @@ package client
|
||||
// // progress through the hops in reverse
|
||||
// rm := &wire.HeaderKey{
|
||||
// IP: ci.Hops[len(ci.Hops)-i-1].IP,
|
||||
// Header: lastMsg,
|
||||
// Message: lastMsg,
|
||||
// }
|
||||
// rmm := rm.Encode()
|
||||
// ep := message.EP{
|
||||
@@ -127,7 +127,7 @@ package client
|
||||
// log.I.Ln("did not find matching address.Receiver")
|
||||
// t.FailNow()
|
||||
// }
|
||||
// var f *message.Header
|
||||
// var f *message.Message
|
||||
// if f, e = message.Decode(lastMsg, from,
|
||||
// match.Key); check(e) {
|
||||
//
|
||||
@@ -135,7 +135,7 @@ package client
|
||||
// t.FailNow()
|
||||
// }
|
||||
// var rm *wire.HeaderKey
|
||||
// var msg wire.Header
|
||||
// var msg wire.Message
|
||||
// if msg, e = wire.Deserialize(f.Data); check(e) {
|
||||
// t.Error(e)
|
||||
// t.FailNow()
|
||||
@@ -145,9 +145,9 @@ package client
|
||||
// t.FailNow()
|
||||
// }
|
||||
// // log.I.Ln(rm.IP)
|
||||
// // log.I.S(rm.Header)
|
||||
// // log.I.S(rm.Message)
|
||||
// // log.I.Ln(lastMsg[0], net.IP(lastMsg[1:5]))
|
||||
// lastMsg = rm.Header
|
||||
// lastMsg = rm.Message
|
||||
// }
|
||||
// if string(original) != string(lastMsg) {
|
||||
// t.Error("failed to recover original message")
|
||||
|
||||
@@ -31,14 +31,14 @@ func GenerateKey() (prv *Key, e error) {
|
||||
}
|
||||
|
||||
// PrivkeyFromBytes converts a byte slice into a private key.
|
||||
func PrivkeyFromBytes(b Bytes) *Key {
|
||||
return (*Key)(secp256k1.PrivKeyFromBytes(b[:]))
|
||||
func PrivkeyFromBytes(b []byte) *Key {
|
||||
return (*Key)(secp256k1.PrivKeyFromBytes(b))
|
||||
}
|
||||
|
||||
// Zero out a private key to prevent key scraping from memory.
|
||||
func (prv *Key) Zero() { (*secp256k1.PrivateKey)(prv).Zero() }
|
||||
|
||||
// ToBytes returns the Bytes serialized form.
|
||||
// ToBytes returns the Bytes serialized form. It zeroes the original bytes.
|
||||
func (prv *Key) ToBytes() (b Bytes) {
|
||||
br := (*secp256k1.PrivateKey)(prv).Serialize()
|
||||
copy(b[:], br[:KeyLen])
|
||||
|
||||
@@ -134,7 +134,7 @@ func Encode(ep EP) (pkt []byte, e error) {
|
||||
// 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
|
||||
// entire packet should then be decrypted, and the Decode function will then
|
||||
// decode a Header.
|
||||
// decode a Message.
|
||||
func GetKeys(d []byte) (from *pub.Key, e error) {
|
||||
pktLen := len(d)
|
||||
if pktLen < Overhead {
|
||||
|
||||
@@ -143,6 +143,11 @@ type Bytes []byte
|
||||
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) Zero() {
|
||||
for i := range m {
|
||||
m[i] = 0
|
||||
}
|
||||
}
|
||||
|
||||
type U64Slice []uint64
|
||||
|
||||
@@ -200,6 +205,12 @@ func (u U64Slice) XOR(v U64Slice) {
|
||||
}
|
||||
}
|
||||
|
||||
func (u U64Slice) Zero() {
|
||||
for i := range u[:len(u)-1] {
|
||||
u[i] = 8
|
||||
}
|
||||
}
|
||||
|
||||
func (u U64Slice) ToMessage() (m Bytes) {
|
||||
// length is encoded into the last element
|
||||
mLen := int(u[len(u)-1])
|
||||
|
||||
@@ -15,18 +15,23 @@ var (
|
||||
check = log.E.Chk
|
||||
)
|
||||
|
||||
// Type cipher delivers a pair of public keys to be used in association with a
|
||||
// Return specifically in the situation of a node bootstrapping sessions, which
|
||||
// doesn't have sessions yet.
|
||||
// Type cipher delivers a pair of private keys to be used in association with a
|
||||
// reply.Type specifically in the situation of a node bootstrapping sessions.
|
||||
//
|
||||
// After ~10 seconds these can be purged from the cache as they are otherwise a
|
||||
// DoS vector buffer flooding.
|
||||
//
|
||||
// The Decode function wipes the original message data for security as the
|
||||
// private keys inside it are no longer needed and any secret should only have
|
||||
// one storage so it doesn't appear in any GC later.
|
||||
type Type struct {
|
||||
Header, Payload pub.Bytes
|
||||
PrivHeader, PrivPayload *prv.Key
|
||||
Header, Payload *prv.Key
|
||||
types.Onion
|
||||
}
|
||||
|
||||
var (
|
||||
Magic = slice.Bytes("cif")
|
||||
MinLen = magicbytes.Len + pub.KeyLen*2
|
||||
MinLen = magicbytes.Len + prv.KeyLen*2
|
||||
_ types.Onion = &Type{}
|
||||
)
|
||||
|
||||
@@ -38,32 +43,25 @@ func (x *Type) Len() int {
|
||||
|
||||
func (x *Type) Encode(o slice.Bytes, c *slice.Cursor) {
|
||||
copy(o[*c:c.Inc(magicbytes.Len)], Magic)
|
||||
hdr := pub.Derive(x.PrivHeader).ToBytes()
|
||||
pld := pub.Derive(x.PrivPayload).ToBytes()
|
||||
hdr := x.Header.ToBytes()
|
||||
pld := x.Payload.ToBytes()
|
||||
copy(o[c.Inc(1):c.Inc(pub.KeyLen)], hdr[:])
|
||||
copy(o[c.Inc(1):c.Inc(pub.KeyLen)], pld[:])
|
||||
x.Onion.Encode(o, c)
|
||||
}
|
||||
|
||||
// Decode unwraps a cipher.Type message.
|
||||
func (x *Type) Decode(b slice.Bytes, c *slice.Cursor) (e error) {
|
||||
|
||||
if !magicbytes.CheckMagic(b, Magic) {
|
||||
return magicbytes.WrongMagic(x, b, Magic)
|
||||
}
|
||||
if len(b) < MinLen {
|
||||
return magicbytes.TooShort(len(b), MinLen, string(Magic))
|
||||
}
|
||||
var header, payload *pub.Key
|
||||
if header, e = pub.FromBytes(
|
||||
b[c.Inc(magicbytes.Len):c.Inc(pub.KeyLen)]); check(e) {
|
||||
|
||||
// this ensures the key is on the curve.
|
||||
return
|
||||
}
|
||||
if payload, e = pub.FromBytes(b[*c:c.Inc(pub.KeyLen)]); check(e) {
|
||||
// this ensures the key is on the curve.
|
||||
return
|
||||
}
|
||||
x.Header, x.Payload = header.ToBytes(), payload.ToBytes()
|
||||
start := c.Inc(magicbytes.Len)
|
||||
x.Header = prv.PrivkeyFromBytes(b[start:c.Inc(pub.KeyLen)])
|
||||
x.Payload = prv.PrivkeyFromBytes(b[*c:c.Inc(pub.KeyLen)])
|
||||
// zero out the version in the message as we have copied it to an array.
|
||||
b[start:*c].Zero()
|
||||
return
|
||||
}
|
||||
|
||||
@@ -15,14 +15,14 @@ var (
|
||||
)
|
||||
|
||||
// Type confirmation is an encryption layer for messages returned to the client
|
||||
// on the inside of an onion, for Ping and Cipher messages, providing a
|
||||
// on the inside of an onion, for Ping and Ciphers messages, providing a
|
||||
// confirmation of the transit of the onion through its encoded route.
|
||||
//
|
||||
// It is encrypted because otherwise internal identifiers could be leaked and
|
||||
// potentially reveal something about the entropy of a client/relay.
|
||||
//
|
||||
// In order to speed up recognition, the key of the table of pending Ping and
|
||||
// Cipher messages will include the last hop that will deliver this layer of the
|
||||
// Ciphers messages will include the last hop that will deliver this layer of the
|
||||
// onion - there can be more than one up in the air at a time, but they are
|
||||
// randomly selected, so they will generally be a much smaller subset versus the
|
||||
// current full set of Session s currently open.
|
||||
|
||||
@@ -25,9 +25,9 @@ type Type struct {
|
||||
// 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
|
||||
// Ciphers 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
|
||||
Ciphers [3]sha256.Hash
|
||||
// Bytes are the message to be passed to the exit service.
|
||||
slice.Bytes
|
||||
types.Onion
|
||||
@@ -51,9 +51,9 @@ func (x *Type) Encode(o slice.Bytes, c *slice.Cursor) {
|
||||
port := slice.NewUint16()
|
||||
slice.EncodeUint16(port, int(x.Port))
|
||||
copy(o[*c:c.Inc(slice.Uint16Len)], port)
|
||||
copy(o[*c:c.Inc(sha256.Len)], x.Cipher[0][:])
|
||||
copy(o[*c:c.Inc(sha256.Len)], x.Cipher[1][:])
|
||||
copy(o[*c:c.Inc(sha256.Len)], x.Cipher[1][:])
|
||||
copy(o[*c:c.Inc(sha256.Len)], x.Ciphers[0][:])
|
||||
copy(o[*c:c.Inc(sha256.Len)], x.Ciphers[1][:])
|
||||
copy(o[*c:c.Inc(sha256.Len)], x.Ciphers[1][:])
|
||||
bytesLen := slice.NewUint32()
|
||||
slice.EncodeUint32(bytesLen, len(x.Bytes))
|
||||
copy(o[*c:c.Inc(slice.Uint32Len)], bytesLen)
|
||||
@@ -63,13 +63,19 @@ func (x *Type) Encode(o slice.Bytes, c *slice.Cursor) {
|
||||
}
|
||||
|
||||
func (x *Type) Decode(b slice.Bytes, c *slice.Cursor) (e error) {
|
||||
|
||||
if !magicbytes.CheckMagic(b, Magic) {
|
||||
return magicbytes.WrongMagic(x, b, Magic)
|
||||
}
|
||||
if len(b) < MinLen {
|
||||
return magicbytes.TooShort(len(b), MinLen, string(Magic))
|
||||
}
|
||||
|
||||
x.Port = uint16(slice.DecodeUint16(b[*c:slice.Uint16Len]))
|
||||
for i := range x.Ciphers {
|
||||
bytes := b[*c:c.Inc(sha256.Len)]
|
||||
copy(x.Ciphers[i][:], bytes)
|
||||
bytes.Zero()
|
||||
}
|
||||
bytesLen := slice.DecodeUint32(b[*c:c.Inc(slice.Uint32Len)])
|
||||
x.Bytes = b[*c:c.Inc(bytesLen)]
|
||||
return
|
||||
}
|
||||
|
||||
@@ -41,14 +41,13 @@ func (x *Type) Encode(o slice.Bytes, c *slice.Cursor) {
|
||||
}
|
||||
|
||||
func (x *Type) Decode(b slice.Bytes, c *slice.Cursor) (e error) {
|
||||
|
||||
if !magicbytes.CheckMagic(b, Magic) {
|
||||
return magicbytes.WrongMagic(x, b, Magic)
|
||||
}
|
||||
if len(b) < MinLen {
|
||||
return magicbytes.TooShort(len(b), MinLen, string(Magic))
|
||||
}
|
||||
ipLen := b[0]
|
||||
x.IP = net.IP(b[1 : 1+ipLen])
|
||||
ipLen := b[*c]
|
||||
x.IP = net.IP(b[c.Inc(1):c.Inc(int(ipLen))])
|
||||
return
|
||||
}
|
||||
|
||||
@@ -16,15 +16,15 @@ import (
|
||||
"github.com/Indra-Labs/indra/pkg/wire/forward"
|
||||
"github.com/Indra-Labs/indra/pkg/wire/message"
|
||||
"github.com/Indra-Labs/indra/pkg/wire/purchase"
|
||||
"github.com/Indra-Labs/indra/pkg/wire/reply"
|
||||
"github.com/Indra-Labs/indra/pkg/wire/response"
|
||||
"github.com/Indra-Labs/indra/pkg/wire/retrn"
|
||||
"github.com/Indra-Labs/indra/pkg/wire/session"
|
||||
"github.com/Indra-Labs/indra/pkg/wire/token"
|
||||
)
|
||||
|
||||
type OnionSkins []types.Onion
|
||||
|
||||
func (o OnionSkins) Header(to *address.Sender, from *prv.Key) OnionSkins {
|
||||
func (o OnionSkins) Message(to *address.Sender, from *prv.Key) OnionSkins {
|
||||
return append(o, &message.Type{To: to, From: from})
|
||||
}
|
||||
func (o OnionSkins) Confirmation(id nonce.ID) OnionSkins {
|
||||
@@ -36,13 +36,13 @@ func (o OnionSkins) Forward(ip net.IP) OnionSkins {
|
||||
func (o OnionSkins) Exit(port uint16, ciphers [3]sha256.Hash,
|
||||
payload slice.Bytes) OnionSkins {
|
||||
|
||||
return append(o, &exit.Type{Port: port, Cipher: ciphers, Bytes: payload})
|
||||
return append(o, &exit.Type{Port: port, Ciphers: ciphers, Bytes: payload})
|
||||
}
|
||||
func (o OnionSkins) Return(ip net.IP) OnionSkins {
|
||||
return append(o, &retrn.Type{IP: ip})
|
||||
return append(o, &reply.Type{IP: ip})
|
||||
}
|
||||
func (o OnionSkins) Cipher(hdr, pld *prv.Key) OnionSkins {
|
||||
return append(o, &cipher.Type{PrivHeader: hdr, PrivPayload: pld})
|
||||
return append(o, &cipher.Type{Header: hdr, Payload: pld})
|
||||
}
|
||||
func (o OnionSkins) Purchase(nBytes uint64, ciphers [3]sha256.Hash) OnionSkins {
|
||||
return append(o, &purchase.Type{NBytes: nBytes, Ciphers: ciphers})
|
||||
|
||||
@@ -2,6 +2,7 @@ package message
|
||||
|
||||
import (
|
||||
"crypto/cipher"
|
||||
"fmt"
|
||||
|
||||
"github.com/Indra-Labs/indra"
|
||||
"github.com/Indra-Labs/indra/pkg/ciph"
|
||||
@@ -27,7 +28,15 @@ var (
|
||||
type Type struct {
|
||||
To *address.Sender
|
||||
From *prv.Key
|
||||
// The following field is only populated in the outermost layer.
|
||||
// The remainder here are for Decode.
|
||||
Nonce nonce.IV
|
||||
Cloak address.Cloaked
|
||||
ToPriv *prv.Key
|
||||
FromPub *pub.Key
|
||||
// The following field is only populated in the outermost layer, and
|
||||
// passed in the `b slice.Bytes` parameter in both encode and decode,
|
||||
// this is created after first getting the Len of everything and
|
||||
// pre-allocating.
|
||||
slice.Bytes
|
||||
types.Onion
|
||||
}
|
||||
@@ -44,50 +53,54 @@ func (x *Type) Len() int {
|
||||
return MinLen + x.Onion.Len()
|
||||
}
|
||||
|
||||
func (x *Type) Encode(o slice.Bytes, c *slice.Cursor) {
|
||||
func (x *Type) Encode(b slice.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 = x.Bytes
|
||||
if b == nil {
|
||||
b = x.Bytes
|
||||
}
|
||||
// We write the checksum last so save the cursor position here.
|
||||
checkStart, checkEnd := *c, c.Inc(4)
|
||||
// Magic after the check so it is part of the checksum.
|
||||
copy(o[*c:c.Inc(magicbytes.Len)], Magic)
|
||||
// Magic after the check, so it is part of the checksum.
|
||||
copy(b[*c:c.Inc(magicbytes.Len)], Magic)
|
||||
// Generate a new nonce and copy it in.
|
||||
n := nonce.New()
|
||||
copy(o[c.Inc(4):c.Inc(nonce.IVLen)], n[:])
|
||||
copy(b[c.Inc(4):c.Inc(nonce.IVLen)], n[:])
|
||||
// Derive the cloaked key and copy it in.
|
||||
to := x.To.GetCloak()
|
||||
copy(o[*c:c.Inc(address.Len)], to[:])
|
||||
copy(b[*c:c.Inc(address.Len)], to[:])
|
||||
// Derive the public key from the From key and copy in.
|
||||
pubKey := pub.Derive(x.From).ToBytes()
|
||||
copy(o[*c:c.Inc(pub.KeyLen)], pubKey[:])
|
||||
copy(b[*c:c.Inc(pub.KeyLen)], pubKey[:])
|
||||
// Encode the remaining data size of the message below. This will also
|
||||
// be the entire remaining part of the message buffer.
|
||||
mLen := len(o[*c:]) - slice.Uint32Len
|
||||
mLen := len(b[*c:]) - slice.Uint32Len
|
||||
length := slice.NewUint32()
|
||||
slice.EncodeUint32(length, mLen)
|
||||
copy(o[*c:c.Inc(mLen)], o[*c:])
|
||||
copy(b[*c:c.Inc(mLen)], b[*c:])
|
||||
// Call the tree of onions to perform their encoding.
|
||||
x.Onion.Encode(o, c)
|
||||
x.Onion.Encode(b, c)
|
||||
// Then we can encrypt the message segment
|
||||
var e error
|
||||
var blk cipher.Block
|
||||
if blk = ciph.GetBlock(x.From, x.To.Key); check(e) {
|
||||
panic(e)
|
||||
}
|
||||
ciph.Encipher(blk, n, o[MinLen:])
|
||||
ciph.Encipher(blk, n, b[MinLen:])
|
||||
// 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 Header and an
|
||||
// onion inside it, the Header takes care of the encryption. This saves
|
||||
// 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
|
||||
// x 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])
|
||||
hash := sha256.Single(b[checkEnd:])
|
||||
copy(b[checkStart:checkEnd], hash[:4])
|
||||
}
|
||||
|
||||
// Decode decodes a received message. Note that it only gets the relevant data
|
||||
// from the header, a subsequent process must be performed to find the prv.Key
|
||||
// corresponding to the Cloak and the pub.Key together forming the cipher secret
|
||||
// needed to decrypt the remainder of the bytes.
|
||||
func (x *Type) Decode(b slice.Bytes, c *slice.Cursor) (e error) {
|
||||
minLen := MinLen
|
||||
if len(b) < minLen {
|
||||
@@ -96,8 +109,28 @@ func (x *Type) Decode(b slice.Bytes, c *slice.Cursor) (e error) {
|
||||
if !magicbytes.CheckMagic(b, Magic) {
|
||||
return magicbytes.WrongMagic(x, b, Magic)
|
||||
}
|
||||
cloak := b[*c:c.Inc(address.Len)]
|
||||
_ = cloak
|
||||
|
||||
var n nonce.IV
|
||||
copy(n[:], b[c.Inc(magicbytes.Len):c.Inc(nonce.IVLen)])
|
||||
copy(x.Nonce[:], n[:])
|
||||
copy(x.Cloak[:], b[*c:c.Inc(address.Len)])
|
||||
if x.FromPub, e = pub.FromBytes(b[*c:c.Inc(pub.KeyLen)]); check(e) {
|
||||
return
|
||||
}
|
||||
length := slice.DecodeUint32(b[*c:c.Inc(slice.Uint32Len)])
|
||||
if length < len(b[*c:]) {
|
||||
e = fmt.Errorf("not enough remaining bytes as specified in"+
|
||||
" length field, got: %d expected %d",
|
||||
length, len(b[*c:]))
|
||||
}
|
||||
// A further step is required which decrypts the remainder of the bytes
|
||||
// after finding the private key corresponding to the Cloak and
|
||||
// FromPubKey.
|
||||
return
|
||||
}
|
||||
|
||||
// Decrypt requires the ToPriv key to be located from the Cloak, using the
|
||||
// FromPub key to derive the shared secret, and then decrypts the rest of the
|
||||
// message.
|
||||
func (x *Type) Decrypt(b slice.Bytes, c *slice.Cursor) {
|
||||
ciph.Encipher(ciph.GetBlock(x.ToPriv, x.FromPub), x.Nonce, b[*c:])
|
||||
}
|
||||
|
||||
@@ -26,13 +26,13 @@ func Ping(id nonce.ID, client node.Node, hop [3]node.Node,
|
||||
set signer.KeySet) types.Onion {
|
||||
|
||||
return OnionSkins{}.
|
||||
Header(address.FromPubKey(hop[0].HeaderKey), set.Next()).
|
||||
Message(address.FromPubKey(hop[0].HeaderKey), set.Next()).
|
||||
Forward(hop[1].IP).
|
||||
Header(address.FromPubKey(hop[1].HeaderKey), set.Next()).
|
||||
Message(address.FromPubKey(hop[1].HeaderKey), set.Next()).
|
||||
Forward(hop[2].IP).
|
||||
Header(address.FromPubKey(hop[2].HeaderKey), set.Next()).
|
||||
Message(address.FromPubKey(hop[2].HeaderKey), set.Next()).
|
||||
Forward(client.IP).
|
||||
Header(address.FromPubKey(client.HeaderKey), set.Next()).
|
||||
Message(address.FromPubKey(client.HeaderKey), set.Next()).
|
||||
Confirmation(id).
|
||||
Assemble()
|
||||
}
|
||||
@@ -41,7 +41,7 @@ func Ping(id nonce.ID, client node.Node, hop [3]node.Node,
|
||||
// Purchase header bytes and to generate the ciphers provided in the Purchase
|
||||
// message to encrypt the Session that is returned.
|
||||
//
|
||||
// The Header key, its cloaked public key counterpart used in the To field of
|
||||
// The Message key, its cloaked public key counterpart used in the To field of
|
||||
// the Purchase message preformed header bytes, but the Ciphers provided in the
|
||||
// Purchase message, for encrypting the Session to be returned, uses the Payload
|
||||
// key, along with the public key found in the encrypted layer of the header for
|
||||
@@ -54,18 +54,18 @@ func SendKeys(id nonce.ID, hdr, pld *prv.Key,
|
||||
client node.Node, hop [5]node.Node, set signer.KeySet) types.Onion {
|
||||
|
||||
return OnionSkins{}.
|
||||
Header(address.FromPubKey(hop[0].HeaderKey), set.Next()).
|
||||
Message(address.FromPubKey(hop[0].HeaderKey), set.Next()).
|
||||
Forward(hop[1].IP).
|
||||
Header(address.FromPubKey(hop[1].HeaderKey), set.Next()).
|
||||
Message(address.FromPubKey(hop[1].HeaderKey), set.Next()).
|
||||
Forward(hop[2].IP).
|
||||
Header(address.FromPubKey(hop[2].HeaderKey), set.Next()).
|
||||
Message(address.FromPubKey(hop[2].HeaderKey), set.Next()).
|
||||
Cipher(hdr, pld).
|
||||
Forward(hop[3].IP).
|
||||
Header(address.FromPubKey(hop[3].HeaderKey), set.Next()).
|
||||
Message(address.FromPubKey(hop[3].HeaderKey), set.Next()).
|
||||
Forward(hop[4].IP).
|
||||
Header(address.FromPubKey(hop[4].HeaderKey), set.Next()).
|
||||
Message(address.FromPubKey(hop[4].HeaderKey), set.Next()).
|
||||
Forward(client.IP).
|
||||
Header(address.FromPubKey(client.HeaderKey), set.Next()).
|
||||
Message(address.FromPubKey(client.HeaderKey), set.Next()).
|
||||
Confirmation(id).
|
||||
Assemble()
|
||||
}
|
||||
@@ -103,18 +103,18 @@ func SendPurchase(nBytes uint64, client node.Node,
|
||||
}
|
||||
|
||||
return OnionSkins{}.
|
||||
Header(address.FromPubKey(hop[0].HeaderKey), set.Next()).
|
||||
Message(address.FromPubKey(hop[0].HeaderKey), set.Next()).
|
||||
Forward(hop[1].IP).
|
||||
Header(address.FromPubKey(hop[1].HeaderKey), set.Next()).
|
||||
Message(address.FromPubKey(hop[1].HeaderKey), set.Next()).
|
||||
Forward(hop[2].IP).
|
||||
Header(address.FromPubKey(hop[2].HeaderKey), set.Next()).
|
||||
Message(address.FromPubKey(hop[2].HeaderKey), set.Next()).
|
||||
Purchase(nBytes, ciphers).
|
||||
Return(hop[3].IP).
|
||||
Header(address.FromPubKey(hop[3].HeaderKey), rtns[0]).
|
||||
Message(address.FromPubKey(hop[3].HeaderKey), rtns[0]).
|
||||
Return(hop[4].IP).
|
||||
Header(address.FromPubKey(hop[4].HeaderKey), rtns[1]).
|
||||
Message(address.FromPubKey(hop[4].HeaderKey), rtns[1]).
|
||||
Return(client.IP).
|
||||
Header(address.FromPubKey(client.HeaderKey), rtns[2]).
|
||||
Message(address.FromPubKey(client.HeaderKey), rtns[2]).
|
||||
Assemble()
|
||||
}
|
||||
|
||||
@@ -155,17 +155,17 @@ func SendExit(payload slice.Bytes, port uint16, client node.Node,
|
||||
}
|
||||
|
||||
return OnionSkins{}.
|
||||
Header(address.FromPubKey(hop[0].HeaderKey), set.Next()).
|
||||
Message(address.FromPubKey(hop[0].HeaderKey), set.Next()).
|
||||
Forward(hop[1].IP).
|
||||
Header(address.FromPubKey(hop[1].HeaderKey), set.Next()).
|
||||
Message(address.FromPubKey(hop[1].HeaderKey), set.Next()).
|
||||
Forward(hop[2].IP).
|
||||
Header(address.FromPubKey(hop[2].HeaderKey), set.Next()).
|
||||
Message(address.FromPubKey(hop[2].HeaderKey), set.Next()).
|
||||
Exit(port, ciphers, payload).
|
||||
Return(hop[3].IP).
|
||||
Header(address.FromPubKey(hop[3].HeaderKey), rtns[0]).
|
||||
Message(address.FromPubKey(hop[3].HeaderKey), rtns[0]).
|
||||
Return(hop[4].IP).
|
||||
Header(address.FromPubKey(hop[4].HeaderKey), rtns[1]).
|
||||
Message(address.FromPubKey(hop[4].HeaderKey), rtns[1]).
|
||||
Return(client.IP).
|
||||
Header(address.FromPubKey(client.HeaderKey), rtns[2]).
|
||||
Message(address.FromPubKey(client.HeaderKey), rtns[2]).
|
||||
Assemble()
|
||||
}
|
||||
|
||||
@@ -41,17 +41,25 @@ func (x *Type) Encode(o slice.Bytes, c *slice.Cursor) {
|
||||
copy(o[*c:c.Inc(magicbytes.Len)], Magic)
|
||||
value := slice.NewUint64()
|
||||
slice.EncodeUint64(value, x.NBytes)
|
||||
copy(o[*c:c.Inc(sha256.Len)], x.Ciphers[0][:])
|
||||
copy(o[*c:c.Inc(sha256.Len)], x.Ciphers[1][:])
|
||||
copy(o[*c:c.Inc(sha256.Len)], x.Ciphers[1][:])
|
||||
x.Onion.Encode(o, c)
|
||||
}
|
||||
|
||||
func (x *Type) Decode(b slice.Bytes, c *slice.Cursor) (e error) {
|
||||
|
||||
if !magicbytes.CheckMagic(b, Magic) {
|
||||
return magicbytes.WrongMagic(x, b, Magic)
|
||||
}
|
||||
if len(b) < MinLen {
|
||||
return magicbytes.TooShort(len(b), MinLen, string(Magic))
|
||||
}
|
||||
|
||||
x.NBytes = slice.DecodeUint64(
|
||||
b[c.Inc(magicbytes.Len):c.Inc(slice.Uint64Len)])
|
||||
for i := range x.Ciphers {
|
||||
bytes := b[*c:c.Inc(sha256.Len)]
|
||||
copy(x.Ciphers[i][:], bytes)
|
||||
bytes.Zero()
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package retrn
|
||||
package reply
|
||||
|
||||
import (
|
||||
"net"
|
||||
@@ -15,10 +15,12 @@ var (
|
||||
check = log.E.Chk
|
||||
)
|
||||
|
||||
// Type is return messages, 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 PayloadHey
|
||||
// matching the To address in the message header.
|
||||
// Type is reply messages, distinct from forward.Type 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
|
||||
// PayloadHey matching the To address in the message header. And lastly, each
|
||||
// step the relay budges up it's message to the front of the packet and puts
|
||||
// csprng random bytes into the remainder to the same length.
|
||||
type Type struct {
|
||||
// IP is the address of the next relay in the return leg of a circuit.
|
||||
net.IP
|
||||
@@ -26,7 +28,7 @@ type Type struct {
|
||||
}
|
||||
|
||||
var (
|
||||
Magic = slice.Bytes("rtn")
|
||||
Magic = slice.Bytes("rpl")
|
||||
MinLen = magicbytes.Len + 1 + net.IPv4len
|
||||
_ types.Onion = &Type{}
|
||||
)
|
||||
@@ -45,13 +47,13 @@ func (x *Type) Encode(o slice.Bytes, c *slice.Cursor) {
|
||||
}
|
||||
|
||||
func (x *Type) Decode(b slice.Bytes, c *slice.Cursor) (e error) {
|
||||
|
||||
if !magicbytes.CheckMagic(b, Magic) {
|
||||
return magicbytes.WrongMagic(x, b, Magic)
|
||||
}
|
||||
if len(b) < MinLen {
|
||||
return magicbytes.TooShort(len(b), MinLen, string(Magic))
|
||||
}
|
||||
|
||||
ipLen := b[0]
|
||||
x.IP = net.IP(b[1 : 1+ipLen])
|
||||
return
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
package response
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"unsafe"
|
||||
|
||||
"github.com/Indra-Labs/indra"
|
||||
"github.com/Indra-Labs/indra/pkg/slice"
|
||||
"github.com/Indra-Labs/indra/pkg/types"
|
||||
@@ -29,19 +32,22 @@ func (x Response) Len() int { return MinLen + len(x) }
|
||||
func (x Response) Encode(o slice.Bytes, c *slice.Cursor) {
|
||||
copy(o[*c:c.Inc(magicbytes.Len)], Magic)
|
||||
bytesLen := slice.NewUint32()
|
||||
slice.EncodeUint32(bytesLen, len(x))
|
||||
slice.EncodeUint32(bytesLen, len(x)-slice.Uint32Len)
|
||||
copy(o[*c:c.Inc(slice.Uint32Len)], bytesLen)
|
||||
copy(o[*c:c.Inc(len(x))], x)
|
||||
}
|
||||
|
||||
func (x Response) Decode(b slice.Bytes, c *slice.Cursor) (e error) {
|
||||
|
||||
if !magicbytes.CheckMagic(b, Magic) {
|
||||
return magicbytes.WrongMagic(x, b, Magic)
|
||||
}
|
||||
if len(b) < MinLen {
|
||||
return magicbytes.TooShort(len(b), MinLen, string(Magic))
|
||||
}
|
||||
|
||||
responseLen := slice.DecodeUint32(b[*c:c.Inc(slice.Uint32Len)])
|
||||
xd := Response(b[*c:c.Inc(responseLen)])
|
||||
// replace current slice header using unsafe.
|
||||
hdr := (*reflect.SliceHeader)(unsafe.Pointer(&x))
|
||||
hdr.Data = (*reflect.SliceHeader)(unsafe.Pointer(&xd)).Data
|
||||
return
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package session
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
"github.com/Indra-Labs/indra"
|
||||
"github.com/Indra-Labs/indra/pkg/key/pub"
|
||||
"github.com/Indra-Labs/indra/pkg/slice"
|
||||
@@ -29,14 +27,13 @@ var (
|
||||
// their generated private key which produces the public key that is placed in
|
||||
// the header.
|
||||
type Type struct {
|
||||
HeaderKey *pub.Key
|
||||
PayloadKey *pub.Key
|
||||
HeaderKey, PayloadKey *pub.Key
|
||||
types.Onion
|
||||
}
|
||||
|
||||
var (
|
||||
Magic = slice.Bytes("ses")
|
||||
MinLen = magicbytes.Len + 1 + net.IPv4len
|
||||
MinLen = magicbytes.Len + pub.KeyLen*2
|
||||
_ types.Onion = &Type{}
|
||||
)
|
||||
|
||||
@@ -55,13 +52,19 @@ func (x *Type) Encode(o slice.Bytes, c *slice.Cursor) {
|
||||
}
|
||||
|
||||
func (x *Type) Decode(b slice.Bytes, c *slice.Cursor) (e error) {
|
||||
|
||||
if !magicbytes.CheckMagic(b, Magic) {
|
||||
return magicbytes.WrongMagic(x, b, Magic)
|
||||
}
|
||||
if len(b) < MinLen {
|
||||
return magicbytes.TooShort(len(b), MinLen, string(Magic))
|
||||
}
|
||||
if x.HeaderKey, e = pub.FromBytes(b[c.Inc(magicbytes.Len):c.Inc(
|
||||
pub.KeyLen)]); check(e) {
|
||||
|
||||
return
|
||||
}
|
||||
if x.PayloadKey, e = pub.FromBytes(b[*c:c.Inc(pub.KeyLen)]); check(e) {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -40,6 +40,6 @@ func (x Type) Decode(b slice.Bytes, c *slice.Cursor) (e error) {
|
||||
if len(b) < MinLen {
|
||||
return magicbytes.TooShort(len(b), MinLen, string(Magic))
|
||||
}
|
||||
|
||||
copy(x[:], b[c.Inc(magicbytes.Len):c.Inc(sha256.Len)])
|
||||
return
|
||||
}
|
||||
|
||||
@@ -11,11 +11,11 @@ var (
|
||||
// URL is the git URL for the repository.
|
||||
URL = "github.com/Indra-Labs/indra"
|
||||
// GitRef is the gitref, as in refs/heads/branchname.
|
||||
GitRef = "refs/heads/main"
|
||||
GitRef = "refs/heads/ind-bootstrap"
|
||||
// ParentGitCommit is the commit hash of the parent HEAD.
|
||||
ParentGitCommit = "2a4c65e4671e1ff9463c494f298bcf2d7650ea97"
|
||||
ParentGitCommit = "ec634cba58726396fa6aac6634f82d499e714f81"
|
||||
// BuildTime stores the time when the current binary was built.
|
||||
BuildTime = "2022-12-23T09:53:26Z"
|
||||
BuildTime = "2022-12-23T12:28:36Z"
|
||||
// SemVer lists the (latest) git tag on the build.
|
||||
SemVer = "v0.0.216"
|
||||
// PathBase is the path base returned from runtime caller.
|
||||
|
||||
Reference in New Issue
Block a user