Starting on onion generation, restructuring relations between some types
This commit is contained in:
@@ -4,6 +4,7 @@ package ciph
|
||||
import (
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"fmt"
|
||||
|
||||
"github.com/Indra-Labs/indra"
|
||||
"github.com/Indra-Labs/indra/pkg/key/ecdh"
|
||||
@@ -34,3 +35,23 @@ func Encipher(blk cipher.Block, n nonce.IV, b []byte) {
|
||||
cipher.NewCTR(blk, n).XORKeyStream(b, b)
|
||||
}
|
||||
}
|
||||
|
||||
const SecretLength = 32
|
||||
|
||||
func CombineCiphers(secrets [][]byte) (combined []byte, e error) {
|
||||
// All ciphers must be the same length, 32 bytes for AES-CTR 256
|
||||
for i := range secrets {
|
||||
if len(secrets[i]) != SecretLength {
|
||||
e = fmt.Errorf("unable to combine ciphers, cipher %d is"+
|
||||
" length %d, expected %d",
|
||||
i, len(secrets[i]), SecretLength)
|
||||
}
|
||||
}
|
||||
combined = make([]byte, SecretLength)
|
||||
for i := range combined {
|
||||
for j := range secrets {
|
||||
combined[i] ^= secrets[j][i]
|
||||
}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
|
||||
"github.com/Indra-Labs/indra"
|
||||
"github.com/Indra-Labs/indra/pkg/ifc"
|
||||
"github.com/Indra-Labs/indra/pkg/key/address"
|
||||
"github.com/Indra-Labs/indra/pkg/node"
|
||||
"github.com/Indra-Labs/indra/pkg/nonce"
|
||||
"github.com/Indra-Labs/indra/pkg/onion"
|
||||
@@ -25,17 +26,22 @@ type Client struct {
|
||||
net.IP
|
||||
*node.Node
|
||||
node.Nodes
|
||||
*address.SendCache
|
||||
*address.ReceiveCache
|
||||
onion.Circuits
|
||||
Sessions
|
||||
ifc.Transport
|
||||
qu.C
|
||||
}
|
||||
|
||||
func New(tpt ifc.Transport) (c *Client) {
|
||||
func New(tpt ifc.Transport, nodes node.Nodes) (c *Client) {
|
||||
n, _ := node.New(nil, tpt)
|
||||
c = &Client{Node: n,
|
||||
Nodes: node.NewNodes(),
|
||||
c = &Client{
|
||||
Node: n,
|
||||
Nodes: nodes,
|
||||
Transport: tpt,
|
||||
C: qu.T()}
|
||||
C: qu.T(),
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -66,8 +72,8 @@ const CircuitExit = 2
|
||||
const ReturnLen = 3
|
||||
|
||||
func (c *Client) GeneratePath(length, exit int) (ci *onion.Circuit, e error) {
|
||||
if len(c.Nodes) < 5 {
|
||||
e = fmt.Errorf("insufficient nodes to form a circuit, "+
|
||||
if len(c.Sessions) < 5 {
|
||||
e = fmt.Errorf("insufficient Sessions to form a circuit, "+
|
||||
"5 required, %d available", len(c.Nodes))
|
||||
return
|
||||
}
|
||||
@@ -89,6 +95,7 @@ func (c *Client) GeneratePath(length, exit int) (ci *onion.Circuit, e error) {
|
||||
Hops: s[:length],
|
||||
Exit: exit,
|
||||
}
|
||||
c.Circuits = c.Circuits.Add(ci)
|
||||
return
|
||||
}
|
||||
|
||||
|
||||
@@ -1,23 +1,65 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
"github.com/Indra-Labs/indra/pkg/ifc"
|
||||
"github.com/Indra-Labs/indra/pkg/key/address"
|
||||
"github.com/Indra-Labs/indra/pkg/node"
|
||||
"github.com/Indra-Labs/indra/pkg/nonce"
|
||||
"github.com/Indra-Labs/indra/pkg/onion"
|
||||
"github.com/Indra-Labs/indra/pkg/packet"
|
||||
"github.com/Indra-Labs/indra/pkg/testutils"
|
||||
"github.com/Indra-Labs/indra/pkg/transport"
|
||||
"github.com/Indra-Labs/indra/pkg/wire"
|
||||
)
|
||||
|
||||
func TestClient(t *testing.T) {
|
||||
func TestClient_GenerateCircuit(t *testing.T) {
|
||||
var nodes node.Nodes
|
||||
var ids []nonce.ID
|
||||
var e error
|
||||
var n int
|
||||
nNodes := 10
|
||||
for i := 0; i < nNodes; i++ {
|
||||
n, id := node.New(nil, transport.NewSim(0))
|
||||
nodes = append(nodes, n)
|
||||
ip := make(net.IP, net.IPv4len)
|
||||
if n, e = rand.Read(ip); check(e) || n != net.IPv4len {
|
||||
t.Error(e)
|
||||
t.FailNow()
|
||||
}
|
||||
var id nonce.ID
|
||||
var nod *node.Node
|
||||
nod, id = node.New(ip, transport.NewSim(0))
|
||||
nodes = append(nodes, nod)
|
||||
ids = append(ids, id)
|
||||
}
|
||||
cl := New(transport.NewSim(0))
|
||||
cl := New(transport.NewSim(0), nodes)
|
||||
cl.Nodes = nodes
|
||||
|
||||
var ci *onion.Circuit
|
||||
if ci, e = cl.GenerateCircuit(); check(e) {
|
||||
t.Error(e)
|
||||
}
|
||||
// Create the onion
|
||||
var lastMsg ifc.Message
|
||||
lastMsg, _, e = testutils.GenerateTestMessage(32)
|
||||
for i := range ci.Hops {
|
||||
// progress through the hops in reverse
|
||||
rm := &wire.ReturnMessage{
|
||||
IP: ci.Hops[len(ci.Hops)-i].IP,
|
||||
Message: lastMsg,
|
||||
}
|
||||
rmm := rm.Serialize()
|
||||
ep := packet.EP{
|
||||
To: address.FromPubKey(ci.Hops[i].Key),
|
||||
// From: _,
|
||||
Parity: 0,
|
||||
Seq: 0,
|
||||
Length: len(rmm),
|
||||
Data: rmm,
|
||||
}
|
||||
lastMsg, e = packet.Encode(ep)
|
||||
}
|
||||
// now unwrap the message
|
||||
|
||||
}
|
||||
|
||||
@@ -1,21 +1,9 @@
|
||||
// Package session provides a mechanism for keeping track of existing sessions
|
||||
// with Indra relays.
|
||||
//
|
||||
// These sessions consist of the current state of the message encryption scheme
|
||||
// and the account of remaining data allocation on the session.
|
||||
package session
|
||||
package client
|
||||
|
||||
import (
|
||||
"github.com/Indra-Labs/indra"
|
||||
"github.com/Indra-Labs/indra/pkg/key/address"
|
||||
"github.com/Indra-Labs/indra/pkg/key/signer"
|
||||
"github.com/Indra-Labs/indra/pkg/nonce"
|
||||
log2 "github.com/cybriq/proc/pkg/log"
|
||||
)
|
||||
|
||||
var (
|
||||
log = log2.GetLogger(indra.PathBase)
|
||||
check = log.E.Chk
|
||||
)
|
||||
|
||||
// A Session keeps track of a connection session. It specifically maintains the
|
||||
@@ -57,12 +45,13 @@ func (s Sessions) Find(t nonce.ID) (se *Session) {
|
||||
return
|
||||
}
|
||||
|
||||
// New creates a new Session.
|
||||
// NewSession creates a new Session.
|
||||
//
|
||||
// Purchasing a session the seller returns a token, based on a requested data
|
||||
// allocation,
|
||||
func New(id nonce.ID, rem uint64, se *address.SendEntry, re *address.ReceiveEntry,
|
||||
kr *signer.KeySet) (s *Session) {
|
||||
func NewSession(id nonce.ID, rem uint64, se *address.SendEntry,
|
||||
re *address.ReceiveEntry, kr *signer.KeySet) (s *Session) {
|
||||
|
||||
s = &Session{
|
||||
ID: id,
|
||||
Remaining: rem,
|
||||
1
pkg/client/session_test.go
Normal file
1
pkg/client/session_test.go
Normal file
@@ -0,0 +1 @@
|
||||
package client
|
||||
@@ -6,3 +6,6 @@ type Transport interface {
|
||||
}
|
||||
|
||||
type Message []byte
|
||||
|
||||
func ToMessage(b []byte) (msg Message) { return b }
|
||||
func (msg Message) ToBytes() []byte { return msg }
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
"github.com/Indra-Labs/indra/pkg/ifc"
|
||||
"github.com/Indra-Labs/indra/pkg/key/pub"
|
||||
"github.com/Indra-Labs/indra/pkg/nonce"
|
||||
"github.com/Indra-Labs/indra/pkg/session"
|
||||
log2 "github.com/cybriq/proc/pkg/log"
|
||||
)
|
||||
|
||||
@@ -26,8 +25,7 @@ var (
|
||||
type Node struct {
|
||||
nonce.ID
|
||||
net.IP
|
||||
pub.Key
|
||||
session.Sessions
|
||||
*pub.Key
|
||||
ifc.Transport
|
||||
}
|
||||
|
||||
@@ -38,7 +36,6 @@ func New(ip net.IP, tpt ifc.Transport) (n *Node, id nonce.ID) {
|
||||
n = &Node{
|
||||
ID: id,
|
||||
IP: ip,
|
||||
Sessions: session.Sessions{},
|
||||
Transport: tpt,
|
||||
}
|
||||
return
|
||||
|
||||
@@ -26,6 +26,18 @@ type Circuit struct {
|
||||
Exit int
|
||||
}
|
||||
|
||||
func (c *Circuit) GenerateOnion(exit []byte, messages [][]byte) (msg []byte,
|
||||
e error) {
|
||||
|
||||
if len(messages) != len(c.Hops) {
|
||||
e = fmt.Errorf("mismatch of message count, %d messages, %d hops",
|
||||
len(messages), len(c.Hops))
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
type Circuits []*Circuit
|
||||
|
||||
func New(id nonce.ID, hops node.Nodes, exit int) (c *Circuit) {
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
package session
|
||||
@@ -1 +1,55 @@
|
||||
package wire
|
||||
|
||||
import (
|
||||
"net"
|
||||
|
||||
"github.com/Indra-Labs/indra/pkg/ifc"
|
||||
)
|
||||
|
||||
type RelayMsg struct {
|
||||
}
|
||||
|
||||
type ExitMsg struct {
|
||||
}
|
||||
|
||||
// ReturnMessage is just an IP address and a wrapper for another return message.
|
||||
// These are wrapped in three onion layers, the final one being a secret
|
||||
// provided by the client to identify the private key of the message, and the
|
||||
// hop in the path that has successfully been relayed that was sent out that it
|
||||
// relates to.
|
||||
//
|
||||
// These messages are used to trace the progress of messages through a circuit.
|
||||
// If they do not return, either the hop itself, or one of the three relays used
|
||||
// in the ReturnMessage onion are not working. These relays will also be used in
|
||||
// parallel in other circuits and so by this in a process of elimination the
|
||||
// dead relays can be eliminated by the ones that are known and responding.
|
||||
//
|
||||
// In a standard path diagnostic onion, one of these contains another, which
|
||||
// contains another message, the last one informing the node of the node that
|
||||
// succeeded in the path trace.
|
||||
//
|
||||
// The last layer of the onion contains the public key of the hop this
|
||||
// return was sent from.
|
||||
type ReturnMessage struct {
|
||||
net.IP
|
||||
ifc.Message
|
||||
}
|
||||
|
||||
func (rm *ReturnMessage) Serialize() (o ifc.Message) {
|
||||
ipLen := len(rm.IP)
|
||||
totalLen := 1 + ipLen + len(rm.Message)
|
||||
o = make(ifc.Message, totalLen)
|
||||
o[0] = byte(ipLen)
|
||||
copy(o[1:ipLen+1], rm.IP)
|
||||
copy(o[ipLen+1:], rm.Message)
|
||||
return
|
||||
}
|
||||
|
||||
func Deserialize(msg ifc.Message) (rm *ReturnMessage) {
|
||||
ipLen := int(msg[0])
|
||||
rm = &ReturnMessage{
|
||||
IP: net.IP(msg[1 : 1+ipLen]),
|
||||
Message: msg[1+ipLen:],
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
@@ -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 = "40865d86002154fc105be210be2acff747db92e4"
|
||||
ParentGitCommit = "3f711d2f40e78d4c4f20a292e17648b18e6f8015"
|
||||
// BuildTime stores the time when the current binary was built.
|
||||
BuildTime = "2022-11-28T20:15:44+01:00"
|
||||
BuildTime = "2022-11-30T22:41:22+01:00"
|
||||
// SemVer lists the (latest) git tag on the build.
|
||||
SemVer = "v0.0.139"
|
||||
SemVer = "v0.0.140"
|
||||
// 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 = 139
|
||||
Patch = 140
|
||||
)
|
||||
|
||||
// Version returns a pretty printed version information string.
|
||||
|
||||
Reference in New Issue
Block a user