service and intro ads fully testing
This commit is contained in:
@@ -50,7 +50,7 @@ func (ng *Engine) SendGetBalance(alice, bob *sessions.Data, hook responses.Callb
|
||||
func (ng *Engine) SendHiddenService(id nonce.ID, key *crypto.Prv,
|
||||
relayRate uint32, port uint16, expiry time.Time,
|
||||
alice, bob *sessions.Data, svc *services.Service,
|
||||
hook responses.Callback) (in *onions.Intro) {
|
||||
hook responses.Callback) (in *onions.IntroAd) {
|
||||
|
||||
hops := sess.StandardCircuit()
|
||||
s := make(sessions.Sessions, len(hops))
|
||||
@@ -58,7 +58,7 @@ func (ng *Engine) SendHiddenService(id nonce.ID, key *crypto.Prv,
|
||||
se := ng.Manager.SelectHops(hops, s, "sendhiddenservice")
|
||||
var c sessions.Circuit
|
||||
copy(c[:], se[:len(c)])
|
||||
in = onions.NewIntro(id, key, alice.Node.AddrPort, relayRate, port, expiry)
|
||||
in = onions.NewIntroAd(id, key, alice.Node.AddrPort, relayRate, port, expiry)
|
||||
o := onions.MakeHiddenService(in, alice, bob, c, ng.KeySet)
|
||||
log.D.F("%s sending out hidden service onion %s",
|
||||
ng.Manager.GetLocalNodeAddressString(),
|
||||
@@ -71,7 +71,7 @@ func (ng *Engine) SendHiddenService(id nonce.ID, key *crypto.Prv,
|
||||
}
|
||||
|
||||
func (ng *Engine) SendIntroQuery(id nonce.ID, hsk *crypto.Pub,
|
||||
alice, bob *sessions.Data, hook func(in *onions.Intro)) {
|
||||
alice, bob *sessions.Data, hook func(in *onions.IntroAd)) {
|
||||
|
||||
fn := func(id nonce.ID, ifc interface{}, b slice.Bytes) (e error) {
|
||||
s := splice.Load(b, slice.NewCursor())
|
||||
@@ -79,9 +79,9 @@ func (ng *Engine) SendIntroQuery(id nonce.ID, hsk *crypto.Pub,
|
||||
if e = on.Decode(s); fails(e) {
|
||||
return
|
||||
}
|
||||
var oni *onions.Intro
|
||||
var oni *onions.IntroAd
|
||||
var ok bool
|
||||
if oni, ok = on.(*onions.Intro); !ok {
|
||||
if oni, ok = on.(*onions.IntroAd); !ok {
|
||||
return
|
||||
}
|
||||
hook(oni)
|
||||
|
||||
@@ -18,10 +18,10 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
IntroMagic = "intr"
|
||||
IntroMagic = "inad"
|
||||
IntroLen = magic.Len +
|
||||
nonce.IDLen +
|
||||
crypto.PubKeyLen + 1 + 1 +
|
||||
crypto.PubKeyLen + 1 + 4 +
|
||||
splice.AddrLen +
|
||||
slice.Uint16Len +
|
||||
slice.Uint32Len +
|
||||
@@ -29,7 +29,7 @@ const (
|
||||
crypto.SigLen
|
||||
)
|
||||
|
||||
type Intro struct {
|
||||
type IntroAd struct {
|
||||
ID nonce.ID // Ensures never a repeated signature.
|
||||
Key *crypto.Pub // Hidden service address.
|
||||
AddrPort *netip.AddrPort // Introducer address.
|
||||
@@ -39,7 +39,7 @@ type Intro struct {
|
||||
Sig crypto.SigBytes
|
||||
}
|
||||
|
||||
func (x *Intro) Account(
|
||||
func (x *IntroAd) Account(
|
||||
res *sess.Data,
|
||||
sm *sess.Manager,
|
||||
s *sessions.Data,
|
||||
@@ -50,13 +50,14 @@ func (x *Intro) Account(
|
||||
return
|
||||
}
|
||||
|
||||
func (x *Intro) Decode(s *splice.Splice) (e error) {
|
||||
func (x *IntroAd) Decode(s *splice.Splice) (e error) {
|
||||
if e = magic.TooShort(s.Remaining(), IntroLen-magic.Len,
|
||||
IntroMagic); fails(e) {
|
||||
|
||||
return
|
||||
}
|
||||
s.ReadID(&x.ID).
|
||||
s.
|
||||
ReadID(&x.ID).
|
||||
ReadPubkey(&x.Key).
|
||||
ReadAddrPort(&x.AddrPort).
|
||||
ReadUint32(&x.RelayRate).
|
||||
@@ -66,24 +67,24 @@ func (x *Intro) Decode(s *splice.Splice) (e error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (x *Intro) Encode(s *splice.Splice) (e error) {
|
||||
func (x *IntroAd) Encode(s *splice.Splice) (e error) {
|
||||
log.T.S("encoding", reflect.TypeOf(x),
|
||||
x.ID, x.AddrPort.String(), x.Expiry, x.Sig,
|
||||
)
|
||||
x.Splice(s.Magic(IntroMagic))
|
||||
x.Splice(s)
|
||||
return
|
||||
}
|
||||
|
||||
func (x *Intro) GetOnion() interface{} { return x }
|
||||
func (x *IntroAd) GetOnion() interface{} { return x }
|
||||
|
||||
// Gossip means adding to the node's peer message list which will be gossiped by
|
||||
// the libp2p network of Indra peers.
|
||||
func (x *Intro) Gossip(sm *sess.Manager, c qu.C) {
|
||||
func (x *IntroAd) Gossip(sm *sess.Manager, c qu.C) {
|
||||
log.D.F("propagating hidden service intro for %s",
|
||||
x.Key.ToBased32Abbreviated())
|
||||
}
|
||||
|
||||
func (x *Intro) Handle(s *splice.Splice, p Onion, ng Ngin) (e error) {
|
||||
func (x *IntroAd) Handle(s *splice.Splice, p Onion, ng Ngin) (e error) {
|
||||
log.D.Ln("handling intro")
|
||||
ng.GetHidden().Lock()
|
||||
valid := x.Validate()
|
||||
@@ -117,37 +118,19 @@ func (x *Intro) Handle(s *splice.Splice, p Onion, ng Ngin) (e error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (x *Intro) Len() int { return IntroLen }
|
||||
func (x *Intro) Magic() string { return IntroMagic }
|
||||
func (x *IntroAd) Len() int { return IntroLen }
|
||||
func (x *IntroAd) Magic() string { return IntroMagic }
|
||||
|
||||
func (x *Intro) Splice(s *splice.Splice) {
|
||||
func (x *IntroAd) Splice(s *splice.Splice) {
|
||||
x.SpliceNoSig(s)
|
||||
s.Signature(x.Sig)
|
||||
}
|
||||
|
||||
func IntroSplice(
|
||||
s *splice.Splice,
|
||||
id nonce.ID,
|
||||
key *crypto.Pub,
|
||||
ap *netip.AddrPort,
|
||||
relayRate uint32,
|
||||
port uint16,
|
||||
expires time.Time,
|
||||
) {
|
||||
|
||||
s.ID(id).
|
||||
Pubkey(key).
|
||||
AddrPort(ap).
|
||||
Uint32(relayRate).
|
||||
Uint16(port).
|
||||
Time(expires)
|
||||
}
|
||||
|
||||
func (x *Intro) SpliceNoSig(s *splice.Splice) {
|
||||
func (x *IntroAd) SpliceNoSig(s *splice.Splice) {
|
||||
IntroSplice(s, x.ID, x.Key, x.AddrPort, x.RelayRate, x.Port, x.Expiry)
|
||||
}
|
||||
|
||||
func (x *Intro) Validate() bool {
|
||||
func (x *IntroAd) Validate() bool {
|
||||
s := splice.New(IntroLen - magic.Len)
|
||||
x.SpliceNoSig(s)
|
||||
hash := sha256.Single(s.GetUntil(s.GetCursor()))
|
||||
@@ -161,19 +144,38 @@ func (x *Intro) Validate() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (x *Intro) Wrap(inner Onion) {}
|
||||
func (x *IntroAd) Wrap(inner Onion) {}
|
||||
|
||||
func NewIntro(
|
||||
func IntroSplice(
|
||||
s *splice.Splice,
|
||||
id nonce.ID,
|
||||
key *crypto.Pub,
|
||||
ap *netip.AddrPort,
|
||||
relayRate uint32,
|
||||
port uint16,
|
||||
expires time.Time,
|
||||
) {
|
||||
|
||||
s.Magic(IntroMagic).
|
||||
ID(id).
|
||||
Pubkey(key).
|
||||
AddrPort(ap).
|
||||
Uint32(relayRate).
|
||||
Uint16(port).
|
||||
Time(expires)
|
||||
}
|
||||
|
||||
func NewIntroAd(
|
||||
id nonce.ID,
|
||||
key *crypto.Prv,
|
||||
ap *netip.AddrPort,
|
||||
relayRate uint32,
|
||||
port uint16,
|
||||
expires time.Time,
|
||||
) (in *Intro) {
|
||||
) (in *IntroAd) {
|
||||
|
||||
pk := crypto.DerivePub(key)
|
||||
s := splice.New(IntroLen - magic.Len)
|
||||
s := splice.New(IntroLen)
|
||||
IntroSplice(s, id, pk, ap, relayRate, port, expires)
|
||||
hash := sha256.Single(s.GetUntil(s.GetCursor()))
|
||||
var e error
|
||||
@@ -181,7 +183,7 @@ func NewIntro(
|
||||
if sign, e = crypto.Sign(key, hash); fails(e) {
|
||||
return nil
|
||||
}
|
||||
in = &Intro{
|
||||
in = &IntroAd{
|
||||
ID: id,
|
||||
Key: pk,
|
||||
AddrPort: ap,
|
||||
@@ -194,4 +196,4 @@ func NewIntro(
|
||||
}
|
||||
|
||||
func init() { Register(IntroMagic, introGen) }
|
||||
func introGen() coding.Codec { return &Intro{} }
|
||||
func introGen() coding.Codec { return &IntroAd{} }
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package onions
|
||||
|
||||
import (
|
||||
"github.com/indra-labs/indra/pkg/util/splice"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -12,26 +13,17 @@ import (
|
||||
)
|
||||
|
||||
func TestOnionSkins_IntroAd(t *testing.T) {
|
||||
log2.SetLogLevel(log2.Debug)
|
||||
log2.SetLogLevel(log2.Trace)
|
||||
var e error
|
||||
pr, ks, _ := crypto.NewSigner()
|
||||
pr, _, _ := crypto.NewSigner()
|
||||
id := nonce.NewID()
|
||||
in := NewIntro(id, pr, slice.GenerateRandomAddrPortIPv6(),
|
||||
0, 0, time.Now().Add(time.Hour))
|
||||
var prvs crypto.Privs
|
||||
for i := range prvs {
|
||||
prvs[i] = ks.Next()
|
||||
in := NewIntroAd(id, pr, slice.GenerateRandomAddrPortIPv6(),
|
||||
20000, 80, time.Now().Add(time.Hour))
|
||||
log.D.S("intro", in)
|
||||
s := splice.New(in.Len())
|
||||
if e = in.Encode(s); fails(e) {
|
||||
t.FailNow()
|
||||
}
|
||||
var pubs crypto.Pubs
|
||||
for i := range pubs {
|
||||
pubs[i] = crypto.DerivePub(prvs[i])
|
||||
}
|
||||
on1 := Skins{}.
|
||||
Intro(id, pr, in.AddrPort, time.Now().Add(time.Hour))
|
||||
on1 = append(on1, &End{})
|
||||
on := on1.Assemble()
|
||||
s := Encode(on)
|
||||
log.D.S(s.GetAll().ToBytes())
|
||||
s.SetCursor(0)
|
||||
var onc coding.Codec
|
||||
if onc = Recognise(s); onc == nil {
|
||||
@@ -43,16 +35,32 @@ func TestOnionSkins_IntroAd(t *testing.T) {
|
||||
t.FailNow()
|
||||
}
|
||||
log.D.S(onc)
|
||||
var intro *Intro
|
||||
var intro *IntroAd
|
||||
var ok bool
|
||||
if intro, ok = onc.(*Intro); !ok {
|
||||
if intro, ok = onc.(*IntroAd); !ok {
|
||||
t.Error("did not unwrap expected type")
|
||||
t.FailNow()
|
||||
}
|
||||
if intro.ID != in.ID {
|
||||
t.Errorf("ID did not decode correctly")
|
||||
t.FailNow()
|
||||
}
|
||||
if intro.Port != in.Port {
|
||||
t.Errorf("port did not decode correctly")
|
||||
t.FailNow()
|
||||
}
|
||||
if intro.RelayRate != in.RelayRate {
|
||||
t.Errorf("relay rate did not decode correctly")
|
||||
t.FailNow()
|
||||
}
|
||||
if intro.AddrPort.String() != in.AddrPort.String() {
|
||||
t.Errorf("addrport did not decode correctly")
|
||||
t.FailNow()
|
||||
}
|
||||
if !intro.Key.Equals(crypto.DerivePub(pr)) {
|
||||
t.Errorf("public key did not decode correctly")
|
||||
t.FailNow()
|
||||
}
|
||||
if !intro.Validate() {
|
||||
t.Errorf("received intro did not validate")
|
||||
t.FailNow()
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"github.com/indra-labs/indra/pkg/crypto"
|
||||
"github.com/indra-labs/indra/pkg/crypto/nonce"
|
||||
"github.com/indra-labs/indra/pkg/crypto/sha256"
|
||||
"github.com/indra-labs/indra/pkg/engine/coding"
|
||||
"github.com/indra-labs/indra/pkg/engine/magic"
|
||||
"github.com/indra-labs/indra/pkg/engine/sess"
|
||||
"github.com/indra-labs/indra/pkg/engine/sessions"
|
||||
@@ -17,10 +18,13 @@ const (
|
||||
PeerAdMagic = "prad"
|
||||
PeerAdLen = magic.Len +
|
||||
nonce.IDLen +
|
||||
slice.Uint64Len +
|
||||
crypto.PubKeyLen +
|
||||
slice.Uint32Len +
|
||||
crypto.SigLen
|
||||
)
|
||||
|
||||
var _ Ad = &PeerAd{}
|
||||
|
||||
// PeerAd is the root identity document for an Indra peer. It is indexed by the
|
||||
// Identity field, its public key. The slices found below it are derived via
|
||||
// concatenation of strings with the keys and hashing to generate a derived
|
||||
@@ -31,14 +35,28 @@ const (
|
||||
// service from their introduction solicitation, and the index from the current
|
||||
// set is given by the hidden service.
|
||||
type PeerAd struct {
|
||||
nonce.ID // To ensure no repeating message
|
||||
Identity crypto.PubBytes
|
||||
RelayRate int
|
||||
nonce.ID // To ensure no repeating message
|
||||
Identity *crypto.Pub // Must match signature.
|
||||
RelayRate uint32 // Zero means not relaying.
|
||||
Sig crypto.SigBytes
|
||||
// Addresses - first is address, nil for hidden services,
|
||||
// hidden services have more than one, 6 or more are kept active.
|
||||
Addresses []*AddressAd
|
||||
ServiceInfos []ServiceAd
|
||||
}
|
||||
|
||||
func NewPeerAd(
|
||||
id nonce.ID,
|
||||
key *crypto.Prv,
|
||||
relayRate uint32,
|
||||
) (pa *PeerAd) {
|
||||
|
||||
pa = &PeerAd{
|
||||
ID: id,
|
||||
Identity: crypto.DerivePub(key),
|
||||
RelayRate: relayRate,
|
||||
}
|
||||
var e error
|
||||
if e = pa.Sign(key); fails(e) {
|
||||
return
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (x *PeerAd) Account(res *sess.Data, sm *sess.Manager, s *sessions.Data, last bool) (skip bool, sd *sessions.Data) {
|
||||
@@ -47,19 +65,20 @@ func (x *PeerAd) Account(res *sess.Data, sm *sess.Manager, s *sessions.Data, las
|
||||
}
|
||||
|
||||
func (x *PeerAd) Decode(s *splice.Splice) (e error) {
|
||||
var v uint64
|
||||
s.ReadID(&x.ID).ReadUint64(&v)
|
||||
s.ReadSignature(&x.Sig)
|
||||
x.RelayRate = int(v)
|
||||
s.ReadID(&x.ID).
|
||||
ReadPubkey(&x.Identity).
|
||||
ReadUint32(&x.RelayRate).
|
||||
ReadSignature(&x.Sig)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *PeerAd) Encode(s *splice.Splice) (e error) {
|
||||
s.ID(x.ID).Uint64(uint64(x.RelayRate))
|
||||
s.Magic(PeerAdMagic)
|
||||
x.Splice(s)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (x *PeerAd) GetOnion() interface{} { return nil }
|
||||
func (x *PeerAd) GetOnion() interface{} { return nil }
|
||||
func (x *PeerAd) Gossip(sm *sess.Manager, c qu.C) {}
|
||||
func (x *PeerAd) Handle(s *splice.Splice, p Onion, ni Ngin) (e error) {
|
||||
return nil
|
||||
@@ -85,17 +104,30 @@ func (x *PeerAd) Sign(prv *crypto.Prv) (e error) {
|
||||
}
|
||||
|
||||
func (x *PeerAd) Splice(s *splice.Splice) {
|
||||
s.
|
||||
ID(x.ID).
|
||||
Uint64(uint64(x.RelayRate))
|
||||
s.ID(x.ID).
|
||||
Pubkey(x.Identity).
|
||||
Uint32(x.RelayRate).
|
||||
Signature(x.Sig)
|
||||
}
|
||||
|
||||
func (x *PeerAd) Validate(s *splice.Splice) (pk *crypto.Pub) {
|
||||
h := sha256.Single(s.GetRange(0, nonce.IDLen+slice.Uint64Len))
|
||||
func (x *PeerAd) SpliceNoSig(s *splice.Splice) {
|
||||
s.ID(x.ID).
|
||||
Pubkey(x.Identity).
|
||||
Uint32(x.RelayRate).
|
||||
Signature(x.Sig)
|
||||
}
|
||||
|
||||
func (x *PeerAd) Validate() (valid bool) {
|
||||
s := splice.New(x.Len())
|
||||
x.SpliceNoSig(s)
|
||||
h := sha256.Single(s.GetUntil(s.GetCursor()))
|
||||
var e error
|
||||
var pk *crypto.Pub
|
||||
if pk, e = x.Sig.Recover(h); fails(e) {
|
||||
}
|
||||
return
|
||||
return pk != nil
|
||||
}
|
||||
|
||||
func (x *PeerAd) Wrap(inner Onion) {}
|
||||
func init() { Register(PeerAdMagic, peerAdGen) }
|
||||
func peerAdGen() coding.Codec { return &PeerAd{} }
|
||||
|
||||
@@ -1,50 +1,47 @@
|
||||
package onions
|
||||
|
||||
//
|
||||
//func TestOnionSkins_PeerAd(t *testing.T) {
|
||||
// log2.SetLogLevel(log2.Debug)
|
||||
// var e error
|
||||
// pr, ks, _ := crypto.NewSigner()
|
||||
// id := nonce.NewID()
|
||||
// in := NewPeerAd(id, pr, slice.GenerateRandomAddrPortIPv6(),
|
||||
// 0, 0, time.Now().Add(time.Hour))
|
||||
// var prvs crypto.Privs
|
||||
// for i := range prvs {
|
||||
// prvs[i] = ks.Next()
|
||||
// }
|
||||
// var pubs crypto.Pubs
|
||||
// for i := range pubs {
|
||||
// pubs[i] = crypto.DerivePub(prvs[i])
|
||||
// }
|
||||
// on1 := Skins{}.
|
||||
// PeerAd(id, pr, in.AddrPort, time.Now().Add(time.Hour))
|
||||
// on1 = append(on1, &End{})
|
||||
// on := on1.Assemble()
|
||||
// s := Encode(on)
|
||||
// log.D.S(s.GetAll().ToBytes())
|
||||
// s.SetCursor(0)
|
||||
// var onc coding.Codec
|
||||
// if onc = Recognise(s); onc == nil {
|
||||
// t.Error("did not unwrap")
|
||||
// t.FailNow()
|
||||
// }
|
||||
// if e = onc.Decode(s); fails(e) {
|
||||
// t.Error("did not decode")
|
||||
// t.FailNow()
|
||||
// }
|
||||
// log.D.S(onc)
|
||||
// var intro *PeerAd
|
||||
// var ok bool
|
||||
// if intro, ok = onc.(*PeerAd); !ok {
|
||||
// t.Error("did not unwrap expected type")
|
||||
// t.FailNow()
|
||||
// }
|
||||
// if intro.AddrPort.String() != in.AddrPort.String() {
|
||||
// t.Errorf("addrport did not decode correctly")
|
||||
// t.FailNow()
|
||||
// }
|
||||
// if !intro.Validate() {
|
||||
// t.Errorf("received intro did not validate")
|
||||
// t.FailNow()
|
||||
// }
|
||||
//}
|
||||
import (
|
||||
"github.com/indra-labs/indra/pkg/crypto"
|
||||
"github.com/indra-labs/indra/pkg/crypto/nonce"
|
||||
"github.com/indra-labs/indra/pkg/engine/coding"
|
||||
log2 "github.com/indra-labs/indra/pkg/proc/log"
|
||||
"github.com/indra-labs/indra/pkg/util/splice"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestOnionSkins_PeerAd(t *testing.T) {
|
||||
log2.SetLogLevel(log2.Trace)
|
||||
var e error
|
||||
pr, _, _ := crypto.NewSigner()
|
||||
id := nonce.NewID()
|
||||
peerAd := NewPeerAd(id, pr, 20000)
|
||||
s := splice.New(peerAd.Len())
|
||||
if e = peerAd.Encode(s); fails(e) {
|
||||
t.FailNow()
|
||||
}
|
||||
s.SetCursor(0)
|
||||
var onc coding.Codec
|
||||
if onc = Recognise(s); onc == nil {
|
||||
t.Error("did not unwrap")
|
||||
t.FailNow()
|
||||
}
|
||||
if e = onc.Decode(s); fails(e) {
|
||||
t.Error("did not decode")
|
||||
t.FailNow()
|
||||
}
|
||||
log.D.S(onc)
|
||||
var pa *PeerAd
|
||||
var ok bool
|
||||
if pa, ok = onc.(*PeerAd); !ok {
|
||||
t.Error("did not unwrap expected type")
|
||||
t.FailNow()
|
||||
}
|
||||
if pa.RelayRate != peerAd.RelayRate {
|
||||
t.Errorf("relay rate did not decode correctly")
|
||||
t.FailNow()
|
||||
}
|
||||
if !pa.Validate() {
|
||||
t.Errorf("received intro did not validate")
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"github.com/indra-labs/indra/pkg/crypto/nonce"
|
||||
"github.com/indra-labs/indra/pkg/crypto/sha256"
|
||||
"github.com/indra-labs/indra/pkg/engine/coding"
|
||||
"github.com/indra-labs/indra/pkg/engine/magic"
|
||||
"github.com/indra-labs/indra/pkg/engine/sess"
|
||||
"github.com/indra-labs/indra/pkg/engine/sessions"
|
||||
"github.com/indra-labs/indra/pkg/util/qu"
|
||||
@@ -14,9 +15,11 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
ServiceAdMagic = "intr"
|
||||
ServiceAdLen = nonce.IDLen +
|
||||
2*slice.Uint16Len +
|
||||
ServiceAdMagic = "svad"
|
||||
ServiceAdLen = magic.Len +
|
||||
nonce.IDLen +
|
||||
crypto.PubKeyLen +
|
||||
slice.Uint16Len +
|
||||
slice.Uint32Len +
|
||||
crypto.SigLen
|
||||
)
|
||||
@@ -27,26 +30,29 @@ const (
|
||||
// "/service/N" where N is the index of the entry. A zero value at an index
|
||||
// signals to stop scanning for more subsequent values.
|
||||
type ServiceAd struct {
|
||||
ID nonce.ID // To ensure no repeating message
|
||||
Index uint16 // This is the index in the slice from Peer.
|
||||
ID nonce.ID // To ensure no repeating message.
|
||||
Key *crypto.Pub // Server offering service.
|
||||
Port uint16
|
||||
RelayRate uint32
|
||||
Sig crypto.SigBytes
|
||||
}
|
||||
|
||||
func (x *ServiceAd) Account(res *sess.Data, sm *sess.Manager, s *sessions.Data, last bool) (skip bool, sd *sessions.Data) {
|
||||
func (x *ServiceAd) Account(res *sess.Data, sm *sess.Manager,
|
||||
s *sessions.Data, last bool) (skip bool, sd *sessions.Data) {
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (x *ServiceAd) Decode(s *splice.Splice) (e error) {
|
||||
s.ReadID(&x.ID).
|
||||
ReadUint16(&x.Index).
|
||||
ReadPubkey(&x.Key).
|
||||
ReadUint16(&x.Port).
|
||||
ReadUint32(&x.RelayRate)
|
||||
ReadUint32(&x.RelayRate).
|
||||
ReadSignature(&x.Sig)
|
||||
return
|
||||
}
|
||||
func (x *ServiceAd) Encode(s *splice.Splice) (e error) {
|
||||
x.Splice(s.Magic(ServiceAdMagic))
|
||||
x.Splice(s)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -81,22 +87,70 @@ func (x *ServiceAd) Sign(prv *crypto.Prv) (e error) {
|
||||
}
|
||||
|
||||
func (x *ServiceAd) Splice(s *splice.Splice) {
|
||||
s.ID(x.ID).
|
||||
Uint16(x.Index).
|
||||
Uint16(x.Port).
|
||||
Uint32(x.RelayRate)
|
||||
x.SpliceNoSig(s)
|
||||
s.Signature(x.Sig)
|
||||
}
|
||||
|
||||
func (x *ServiceAd) Validate(s *splice.Splice) (pub *crypto.Pub) {
|
||||
h := sha256.Single(s.GetRange(0, nonce.IDLen+2*slice.Uint16Len+
|
||||
slice.Uint64Len))
|
||||
var e error
|
||||
if pub, e = x.Sig.Recover(h); fails(e) {
|
||||
func (x *ServiceAd) SpliceNoSig(s *splice.Splice) {
|
||||
ServiceSplice(s, x.ID, x.Key, x.RelayRate, x.Port)
|
||||
}
|
||||
|
||||
func (x *ServiceAd) Validate() (valid bool) {
|
||||
s := splice.New(IntroLen - magic.Len)
|
||||
x.SpliceNoSig(s)
|
||||
hash := sha256.Single(s.GetUntil(s.GetCursor()))
|
||||
key, e := x.Sig.Recover(hash)
|
||||
if fails(e) {
|
||||
return false
|
||||
}
|
||||
return
|
||||
if key.Equals(x.Key) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (x *ServiceAd) Wrap(inner Onion) {}
|
||||
|
||||
func ServiceSplice(
|
||||
s *splice.Splice,
|
||||
id nonce.ID,
|
||||
key *crypto.Pub,
|
||||
relayRate uint32,
|
||||
port uint16,
|
||||
) {
|
||||
|
||||
s.Magic(ServiceAdMagic).
|
||||
ID(id).
|
||||
Pubkey(key).
|
||||
Uint16(port).
|
||||
Uint32(relayRate)
|
||||
}
|
||||
|
||||
func NewServiceAd(
|
||||
id nonce.ID,
|
||||
key *crypto.Prv,
|
||||
relayRate uint32,
|
||||
port uint16,
|
||||
) (sv *ServiceAd) {
|
||||
|
||||
s := splice.New(IntroLen)
|
||||
k := crypto.DerivePub(key)
|
||||
ServiceSplice(s, id, k, relayRate, port)
|
||||
hash := sha256.Single(s.GetUntil(s.GetCursor()))
|
||||
var e error
|
||||
var sign crypto.SigBytes
|
||||
if sign, e = crypto.Sign(key, hash); fails(e) {
|
||||
return nil
|
||||
}
|
||||
sv = &ServiceAd{
|
||||
ID: id,
|
||||
Key: k,
|
||||
RelayRate: relayRate,
|
||||
Port: port,
|
||||
Sig: sign,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func init() { Register(ServiceAdMagic, serviceAdGen) }
|
||||
func serviceAdGen() coding.Codec { return &Intro{} }
|
||||
func serviceAdGen() coding.Codec { return &ServiceAd{} }
|
||||
|
||||
56
pkg/engine/onions/adservice_test.go
Normal file
56
pkg/engine/onions/adservice_test.go
Normal file
@@ -0,0 +1,56 @@
|
||||
package onions
|
||||
|
||||
import (
|
||||
"github.com/indra-labs/indra/pkg/crypto"
|
||||
"github.com/indra-labs/indra/pkg/crypto/nonce"
|
||||
"github.com/indra-labs/indra/pkg/engine/coding"
|
||||
log2 "github.com/indra-labs/indra/pkg/proc/log"
|
||||
"github.com/indra-labs/indra/pkg/util/splice"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestOnionSkins_ServiceAd(t *testing.T) {
|
||||
log2.SetLogLevel(log2.Trace)
|
||||
var e error
|
||||
pr, _, _ := crypto.NewSigner()
|
||||
id := nonce.NewID()
|
||||
sv := NewServiceAd(id, pr, 20000, 80)
|
||||
log.D.S("service", sv)
|
||||
s := splice.New(sv.Len())
|
||||
if e = sv.Encode(s); fails(e) {
|
||||
t.FailNow()
|
||||
}
|
||||
s.SetCursor(0)
|
||||
var onc coding.Codec
|
||||
if onc = Recognise(s); onc == nil {
|
||||
t.Error("did not unwrap")
|
||||
t.FailNow()
|
||||
}
|
||||
if e = onc.Decode(s); fails(e) {
|
||||
t.Error("did not decode")
|
||||
t.FailNow()
|
||||
}
|
||||
log.D.S(onc)
|
||||
var svcAd *ServiceAd
|
||||
var ok bool
|
||||
if svcAd, ok = onc.(*ServiceAd); !ok {
|
||||
t.Error("did not unwrap expected type")
|
||||
t.FailNow()
|
||||
}
|
||||
if svcAd.RelayRate != sv.RelayRate {
|
||||
t.Errorf("relay rate did not decode correctly")
|
||||
t.FailNow()
|
||||
}
|
||||
if svcAd.Port != sv.Port {
|
||||
t.Errorf("port did not decode correctly")
|
||||
t.FailNow()
|
||||
}
|
||||
if !svcAd.Key.Equals(crypto.DerivePub(pr)) {
|
||||
t.Errorf("public key did not decode correctly")
|
||||
t.FailNow()
|
||||
}
|
||||
if !svcAd.Validate() {
|
||||
t.Errorf("received service ad did not validate")
|
||||
t.FailNow()
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@ type Hidden struct {
|
||||
}
|
||||
|
||||
func (hr *Hidden) AddHiddenService(svc *services.Service, key *crypto.Prv,
|
||||
in *Intro, addr string) {
|
||||
in *IntroAd, addr string) {
|
||||
pk := crypto.DerivePub(key).ToBytes()
|
||||
hr.Lock()
|
||||
log.I.F("%s added hidden service with key %s", addr, pk)
|
||||
@@ -42,7 +42,7 @@ func (hr *Hidden) AddIntro(pk *crypto.Pub, intro *Introduction) {
|
||||
hr.Unlock()
|
||||
}
|
||||
|
||||
func (hr *Hidden) AddIntroToHiddenService(key crypto.PubBytes, in *Intro) {
|
||||
func (hr *Hidden) AddIntroToHiddenService(key crypto.PubBytes, in *IntroAd) {
|
||||
hr.Lock()
|
||||
hr.Services[key].CurrentIntros = append(hr.Services[key].
|
||||
CurrentIntros, in)
|
||||
@@ -140,7 +140,7 @@ func (hr *Hidden) FindIntroductionUnsafe(
|
||||
return
|
||||
}
|
||||
|
||||
func (hr *Hidden) FindKnownIntro(key crypto.PubBytes) (intro *Intro) {
|
||||
func (hr *Hidden) FindKnownIntro(key crypto.PubBytes) (intro *IntroAd) {
|
||||
hr.Lock()
|
||||
var ok bool
|
||||
if intro, ok = hr.KnownIntros[key]; ok {
|
||||
@@ -149,17 +149,17 @@ func (hr *Hidden) FindKnownIntro(key crypto.PubBytes) (intro *Intro) {
|
||||
return
|
||||
}
|
||||
|
||||
func (hr *Hidden) FindKnownIntroUnsafe(key crypto.PubBytes) (intro *Intro) {
|
||||
func (hr *Hidden) FindKnownIntroUnsafe(key crypto.PubBytes) (intro *IntroAd) {
|
||||
var ok bool
|
||||
if intro, ok = hr.KnownIntros[key]; ok {
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type KnownIntros map[crypto.PubBytes]*Intro
|
||||
type KnownIntros map[crypto.PubBytes]*IntroAd
|
||||
type LocalHiddenService struct {
|
||||
Prv *crypto.Prv
|
||||
CurrentIntros []*Intro
|
||||
CurrentIntros []*IntroAd
|
||||
*services.Service
|
||||
}
|
||||
type MyIntros map[crypto.PubBytes]*Introduction
|
||||
|
||||
@@ -20,7 +20,7 @@ const (
|
||||
)
|
||||
|
||||
type HiddenService struct {
|
||||
Intro Intro
|
||||
Intro IntroAd
|
||||
// Ciphers is a set of 3 symmetric ciphers that are to be used in their
|
||||
// given order over the reply message from the service.
|
||||
crypto.Ciphers
|
||||
|
||||
@@ -73,11 +73,11 @@ func (x *IntroQuery) Handle(s *splice.Splice, p Onion, ng Ngin) (e error) {
|
||||
log.D.Ln(ng.Mgr().GetLocalNodeAddressString(), "handling introquery", x.ID,
|
||||
x.Key.ToBased32Abbreviated())
|
||||
var ok bool
|
||||
var il *Intro
|
||||
var il *IntroAd
|
||||
if il, ok = ng.GetHidden().KnownIntros[x.Key.ToBytes()]; !ok {
|
||||
// if the reply is zeroes the querant knows it needs to retry at a
|
||||
// different relay
|
||||
il = &Intro{}
|
||||
il = &IntroAd{}
|
||||
ng.GetHidden().Unlock()
|
||||
log.E.Ln("intro not known")
|
||||
return
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package onions
|
||||
|
||||
type Introduction struct {
|
||||
Intro *Intro
|
||||
Intro *IntroAd
|
||||
ReplyHeader
|
||||
}
|
||||
|
||||
@@ -213,7 +213,7 @@ func (h *Headers) ExitPoint() *ExitPoint {
|
||||
}
|
||||
}
|
||||
|
||||
func (o Skins) HiddenService(in *Intro, point *ExitPoint) Skins {
|
||||
func (o Skins) HiddenService(in *IntroAd, point *ExitPoint) Skins {
|
||||
return append(o, &HiddenService{
|
||||
Intro: *in,
|
||||
Ciphers: crypto.GenCiphers(point.Keys, point.ReturnPubs),
|
||||
@@ -224,7 +224,13 @@ func (o Skins) HiddenService(in *Intro, point *ExitPoint) Skins {
|
||||
|
||||
func (o Skins) Intro(id nonce.ID, key *crypto.Prv, ap *netip.AddrPort,
|
||||
expires time.Time) (sk Skins) {
|
||||
return append(o, NewIntro(id, key, ap, 0, 0, expires))
|
||||
return append(o, NewIntroAd(id, key, ap, 0, 0, expires))
|
||||
}
|
||||
|
||||
func (o Skins) PeerAd(id nonce.ID, key *crypto.Prv, ap *netip.AddrPort,
|
||||
relayRate uint32, port uint16, expires time.Time) (sk Skins) {
|
||||
|
||||
return append(o, NewPeerAd(id, key, relayRate))
|
||||
}
|
||||
|
||||
func (o Skins) IntroQuery(id nonce.ID, hsk *crypto.Pub, exit *ExitPoint) Skins {
|
||||
@@ -267,7 +273,7 @@ func MakeGetBalance(p GetBalanceParams) Skins {
|
||||
RoutingHeader(headers.Return)
|
||||
}
|
||||
|
||||
func MakeHiddenService(in *Intro, alice, bob *sessions.Data,
|
||||
func MakeHiddenService(in *IntroAd, alice, bob *sessions.Data,
|
||||
c sessions.Circuit, ks *crypto.KeySet) Skins {
|
||||
|
||||
headers := GetHeaders(alice, bob, c, ks)
|
||||
|
||||
Reference in New Issue
Block a user