added signature to introduction for spoofing protection
This commit is contained in:
@@ -2,9 +2,9 @@ package hiddenservice
|
||||
|
||||
import (
|
||||
"git-indra.lan/indra-labs/indra"
|
||||
"git-indra.lan/indra-labs/indra/pkg/crypto/key/pub"
|
||||
"git-indra.lan/indra-labs/indra/pkg/crypto/nonce"
|
||||
"git-indra.lan/indra-labs/indra/pkg/crypto/sha256"
|
||||
"git-indra.lan/indra-labs/indra/pkg/messages/intro"
|
||||
"git-indra.lan/indra-labs/indra/pkg/messages/magicbytes"
|
||||
log2 "git-indra.lan/indra-labs/indra/pkg/proc/log"
|
||||
"git-indra.lan/indra-labs/indra/pkg/splice"
|
||||
@@ -14,7 +14,7 @@ import (
|
||||
|
||||
const (
|
||||
MagicString = "hs"
|
||||
Len = magicbytes.Len + nonce.IDLen + pub.KeyLen +
|
||||
Len = magicbytes.Len + nonce.IDLen + intro.Len +
|
||||
3*sha256.Len + nonce.IVLen*3
|
||||
)
|
||||
|
||||
@@ -30,11 +30,7 @@ var (
|
||||
// header for any client that requests it.
|
||||
type Layer struct {
|
||||
nonce.ID
|
||||
// Identity is a public key identifying the hidden service. It is encoded
|
||||
// into Bech32 encoding to function like an IP address, with a 2 byte
|
||||
// truncated hash check suffix to eliminate possible human input errors and
|
||||
// ending in ".indra" to indicate it is an indra hidden service.
|
||||
Identity *pub.Key
|
||||
intro.Layer
|
||||
// Ciphers is a set of 3 symmetric ciphers that are to be used in their
|
||||
// given order over the reply message from the service.
|
||||
Ciphers [3]sha256.Hash
|
||||
@@ -56,7 +52,9 @@ func (x *Layer) Encode(b slice.Bytes, c *slice.Cursor) {
|
||||
splice.Splice(b, c).
|
||||
Magic(Magic).
|
||||
ID(x.ID).
|
||||
Pubkey(x.Identity).
|
||||
Pubkey(x.Key).
|
||||
AddrPort(x.AddrPort).
|
||||
Signature(x.Bytes).
|
||||
Hash(x.Ciphers[0]).Hash(x.Ciphers[1]).Hash(x.Ciphers[2]).
|
||||
IV(x.Nonces[0]).IV(x.Nonces[1]).IV(x.Nonces[2])
|
||||
}
|
||||
@@ -67,7 +65,9 @@ func (x *Layer) Decode(b slice.Bytes, c *slice.Cursor) (e error) {
|
||||
}
|
||||
splice.Splice(b, c).
|
||||
ReadID(&x.ID).
|
||||
ReadPubkey(&x.Identity).
|
||||
ReadPubkey(&x.Key).
|
||||
ReadAddrPort(&x.AddrPort).
|
||||
ReadSignature(x.Bytes).
|
||||
ReadHash(&x.Ciphers[0]).ReadHash(&x.Ciphers[1]).ReadHash(&x.Ciphers[2]).
|
||||
ReadIV(&x.Nonces[0]).ReadIV(&x.Nonces[1]).ReadIV(&x.Nonces[2])
|
||||
return
|
||||
|
||||
@@ -4,17 +4,27 @@ import (
|
||||
"net"
|
||||
"net/netip"
|
||||
|
||||
"git-indra.lan/indra-labs/indra"
|
||||
"git-indra.lan/indra-labs/indra/pkg/crypto/key/prv"
|
||||
"git-indra.lan/indra-labs/indra/pkg/crypto/key/pub"
|
||||
"git-indra.lan/indra-labs/indra/pkg/crypto/key/sig"
|
||||
"git-indra.lan/indra-labs/indra/pkg/crypto/sha256"
|
||||
"git-indra.lan/indra-labs/indra/pkg/messages/magicbytes"
|
||||
log2 "git-indra.lan/indra-labs/indra/pkg/proc/log"
|
||||
"git-indra.lan/indra-labs/indra/pkg/splice"
|
||||
"git-indra.lan/indra-labs/indra/pkg/types"
|
||||
"git-indra.lan/indra-labs/indra/pkg/util/slice"
|
||||
)
|
||||
|
||||
var (
|
||||
log = log2.GetLogger(indra.PathBase)
|
||||
check = log.E.Chk
|
||||
)
|
||||
|
||||
const (
|
||||
MagicString = "in"
|
||||
AddrLen = net.IPv6len + 3
|
||||
Len = magicbytes.Len + pub.KeyLen + AddrLen
|
||||
Len = magicbytes.Len + pub.KeyLen + AddrLen + sig.Len
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -24,17 +34,57 @@ var (
|
||||
type Layer struct {
|
||||
*pub.Key
|
||||
*netip.AddrPort
|
||||
sig.Bytes
|
||||
}
|
||||
|
||||
func New(key *prv.Key, ap *netip.AddrPort) (im *Layer) {
|
||||
pk := pub.Derive(key)
|
||||
bap, _ := ap.MarshalBinary()
|
||||
pkb := pk.ToBytes()
|
||||
hash := sha256.Single(append(pkb[:], bap...))
|
||||
var e error
|
||||
var sign sig.Bytes
|
||||
if sign, e = sig.Sign(key, hash); check(e) {
|
||||
return nil
|
||||
}
|
||||
im = &Layer{
|
||||
Key: pk,
|
||||
AddrPort: ap,
|
||||
Bytes: sign,
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func (im *Layer) Validate() bool {
|
||||
bap, _ := im.AddrPort.MarshalBinary()
|
||||
pkb := im.Key.ToBytes()
|
||||
hash := sha256.Single(append(pkb[:], bap...))
|
||||
key, e := im.Bytes.Recover(hash)
|
||||
if check(e) {
|
||||
return false
|
||||
}
|
||||
kb := key.ToBytes()
|
||||
if kb.Equals(pkb) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (im *Layer) Insert(o types.Onion) {}
|
||||
func (im *Layer) Len() int { return Len }
|
||||
|
||||
func (im *Layer) Encode(b slice.Bytes, c *slice.Cursor) {
|
||||
splice.Splice(b, c).Magic(Magic).Pubkey(im.Key).AddrPort(im.AddrPort)
|
||||
splice.Splice(b, c).
|
||||
Magic(Magic).
|
||||
Pubkey(im.Key).
|
||||
AddrPort(im.AddrPort).
|
||||
Signature(im.Bytes)
|
||||
return
|
||||
}
|
||||
|
||||
func (im *Layer) Decode(b slice.Bytes, c *slice.Cursor) (e error) {
|
||||
splice.Splice(b, c).ReadPubkey(&im.Key).ReadAddrPort(&im.AddrPort)
|
||||
splice.Splice(b, c).
|
||||
ReadPubkey(&im.Key).
|
||||
ReadAddrPort(&im.AddrPort).ReadSignature(im.Bytes)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ var (
|
||||
// is concealed to the hops except for the encryption crypt they decrypt using
|
||||
// their Payload key, delivered in this message.
|
||||
type Layer struct {
|
||||
nonce.ID
|
||||
nonce.ID // only used by a node
|
||||
Hop byte // only used by a node
|
||||
Header, Payload *prv.Key
|
||||
types.Onion
|
||||
|
||||
@@ -10,9 +10,9 @@ import (
|
||||
"go.uber.org/atomic"
|
||||
|
||||
"git-indra.lan/indra-labs/indra/pkg/crypto/key/prv"
|
||||
"git-indra.lan/indra-labs/indra/pkg/crypto/key/pub"
|
||||
"git-indra.lan/indra-labs/indra/pkg/crypto/nonce"
|
||||
"git-indra.lan/indra-labs/indra/pkg/crypto/sha256"
|
||||
"git-indra.lan/indra-labs/indra/pkg/messages/intro"
|
||||
log2 "git-indra.lan/indra-labs/indra/pkg/proc/log"
|
||||
"git-indra.lan/indra-labs/indra/pkg/service"
|
||||
"git-indra.lan/indra-labs/indra/pkg/transport"
|
||||
@@ -290,10 +290,10 @@ func TestClient_HiddenService(t *testing.T) {
|
||||
t.Error(e)
|
||||
t.FailNow()
|
||||
}
|
||||
identPub := pub.Derive(identPrv)
|
||||
id := nonce.NewID()
|
||||
il := intro.New(identPrv, clients[0].GetLocalNodeAddress())
|
||||
clients[0].SendIntro(id, clients[0].Sessions[i+returns],
|
||||
identPub, func(id nonce.ID, b slice.Bytes) {
|
||||
il, func(id nonce.ID, b slice.Bytes) {
|
||||
log.I.Ln("success")
|
||||
})
|
||||
}
|
||||
@@ -303,7 +303,7 @@ func TestClient_HiddenService(t *testing.T) {
|
||||
}
|
||||
}
|
||||
func TestClient_HiddenServiceBroadcast(t *testing.T) {
|
||||
log2.SetLogLevel(log2.Trace)
|
||||
log2.SetLogLevel(log2.Info)
|
||||
var clients []*Engine
|
||||
var e error
|
||||
const returns = 2
|
||||
@@ -340,10 +340,12 @@ func TestClient_HiddenServiceBroadcast(t *testing.T) {
|
||||
t.Error(e)
|
||||
t.FailNow()
|
||||
}
|
||||
identPub := pub.Derive(identPrv)
|
||||
log2.SetLogLevel(log2.Trace)
|
||||
// identPub := pub.Derive(identPrv)
|
||||
id := nonce.NewID()
|
||||
il := intro.New(identPrv, clients[0].GetLocalNodeAddress())
|
||||
clients[0].SendIntro(id, clients[0].Sessions[returns],
|
||||
identPub, func(id nonce.ID, b slice.Bytes) {
|
||||
il, func(id nonce.ID, b slice.Bytes) {
|
||||
log.I.Ln("success")
|
||||
})
|
||||
time.Sleep(time.Second * 5)
|
||||
|
||||
@@ -10,8 +10,8 @@ func (eng *Engine) hiddenservice(hs *hiddenservice.Layer, b slice.Bytes,
|
||||
c *slice.Cursor, prev types.Onion) {
|
||||
|
||||
log.D.F("%s adding introduction for key %s", eng.GetLocalNodeAddress(),
|
||||
hs.Identity.ToBase32())
|
||||
eng.Introductions.AddIntro(hs.Identity, b[*c:])
|
||||
hs.Layer.Key.ToBase32())
|
||||
eng.Introductions.AddIntro(hs.Layer.Key, b[*c:])
|
||||
log.I.Ln("stored new introduction, starting broadcast")
|
||||
go eng.hiddenserviceBroadcaster(hs.Identity)
|
||||
go eng.hiddenserviceBroadcaster(hs.Layer.Key)
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ func (eng *Engine) session(on *session.Layer, b slice.Bytes,
|
||||
c *slice.Cursor, prev types.Onion) {
|
||||
|
||||
log.D.Ln(prev == nil)
|
||||
log.T.F("incoming session %s", on.ID)
|
||||
log.T.F("incoming session %x", on.PreimageHash())
|
||||
pi := eng.FindPendingPreimage(on.PreimageHash())
|
||||
if pi != nil {
|
||||
// We need to delete this first in case somehow two such messages arrive
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
package relay
|
||||
|
||||
import (
|
||||
"git-indra.lan/indra-labs/indra/pkg/crypto/key/pub"
|
||||
"git-indra.lan/indra-labs/indra/pkg/crypto/nonce"
|
||||
"git-indra.lan/indra-labs/indra/pkg/messages/intro"
|
||||
"git-indra.lan/indra-labs/indra/pkg/util/slice"
|
||||
)
|
||||
|
||||
func (eng *Engine) SendIntro(id nonce.ID, target *Session, ident *pub.Key,
|
||||
func (eng *Engine) SendIntro(id nonce.ID, target *Session, intr *intro.Layer,
|
||||
hook func(id nonce.ID, b slice.Bytes)) {
|
||||
|
||||
log.I.Ln(target.Hop)
|
||||
@@ -16,7 +16,7 @@ func (eng *Engine) SendIntro(id nonce.ID, target *Session, ident *pub.Key,
|
||||
se := eng.SelectHops(hops, s)
|
||||
var c Circuit
|
||||
copy(c[:], se)
|
||||
o := HiddenService(id, ident, se[len(se)-1], c, eng.KeySet)
|
||||
o := HiddenService(id, intr, se[len(se)-1], c, eng.KeySet)
|
||||
log.D.Ln("sending out intro onion")
|
||||
res := eng.PostAcctOnion(o)
|
||||
eng.SendWithOneHook(c[0].AddrPort, res, hook)
|
||||
|
||||
@@ -5,9 +5,10 @@ import (
|
||||
"git-indra.lan/indra-labs/indra/pkg/crypto/key/pub"
|
||||
"git-indra.lan/indra-labs/indra/pkg/crypto/key/signer"
|
||||
"git-indra.lan/indra-labs/indra/pkg/crypto/nonce"
|
||||
"git-indra.lan/indra-labs/indra/pkg/messages/intro"
|
||||
)
|
||||
|
||||
func HiddenService(id nonce.ID, ident *pub.Key, client *Session, s Circuit,
|
||||
func HiddenService(id nonce.ID, il *intro.Layer, client *Session, s Circuit,
|
||||
ks *signer.KeySet) Skins {
|
||||
|
||||
var prvs [3]*prv.Key
|
||||
@@ -25,7 +26,7 @@ func HiddenService(id nonce.ID, ident *pub.Key, client *Session, s Circuit,
|
||||
ReverseCrypt(s[0], ks.Next(), n[0], 3).
|
||||
ReverseCrypt(s[1], ks.Next(), n[1], 2).
|
||||
ReverseCrypt(s[2], ks.Next(), n[2], 1).
|
||||
HiddenService(id, ident, prvs, pubs, returnNonces).
|
||||
HiddenService(id, il, prvs, pubs, returnNonces).
|
||||
ReverseCrypt(s[3], prvs[0], n[3], 3).
|
||||
ReverseCrypt(s[4], prvs[1], n[4], 2).
|
||||
ReverseCrypt(client, prvs[2], n[5], 1)
|
||||
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
"git-indra.lan/indra-labs/indra/pkg/messages/forward"
|
||||
"git-indra.lan/indra-labs/indra/pkg/messages/getbalance"
|
||||
"git-indra.lan/indra-labs/indra/pkg/messages/hiddenservice"
|
||||
"git-indra.lan/indra-labs/indra/pkg/messages/intro"
|
||||
"git-indra.lan/indra-labs/indra/pkg/messages/noop"
|
||||
"git-indra.lan/indra-labs/indra/pkg/messages/response"
|
||||
"git-indra.lan/indra-labs/indra/pkg/messages/reverse"
|
||||
@@ -113,13 +114,13 @@ func (o Skins) GetBalance(id, confID nonce.ID, prvs [3]*prv.Key,
|
||||
})
|
||||
}
|
||||
|
||||
func (o Skins) HiddenService(id nonce.ID, addr *pub.Key, prvs [3]*prv.Key,
|
||||
func (o Skins) HiddenService(id nonce.ID, intr *intro.Layer, prvs [3]*prv.Key,
|
||||
pubs [3]*pub.Key, nonces [3]nonce.IV) Skins {
|
||||
return append(o, &hiddenservice.Layer{
|
||||
ID: id,
|
||||
Identity: addr,
|
||||
Ciphers: GenCiphers(prvs, pubs),
|
||||
Nonces: nonces,
|
||||
ID: id,
|
||||
Layer: *intr,
|
||||
Ciphers: GenCiphers(prvs, pubs),
|
||||
Nonces: nonces,
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"git-indra.lan/indra-labs/indra/pkg/crypto/key/cloak"
|
||||
"git-indra.lan/indra-labs/indra/pkg/crypto/key/prv"
|
||||
"git-indra.lan/indra-labs/indra/pkg/crypto/key/pub"
|
||||
"git-indra.lan/indra-labs/indra/pkg/crypto/key/sig"
|
||||
"git-indra.lan/indra-labs/indra/pkg/crypto/nonce"
|
||||
"git-indra.lan/indra-labs/indra/pkg/crypto/sha256"
|
||||
"git-indra.lan/indra-labs/indra/pkg/messages/magicbytes"
|
||||
@@ -177,4 +178,14 @@ func (s *Splicer) Bytes(b []byte) *Splicer {
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *Splicer) Signature(sb sig.Bytes) *Splicer {
|
||||
copy(s.b[*s.c:s.c.Inc(sig.Len)], sb[:])
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *Splicer) ReadSignature(sb sig.Bytes) *Splicer {
|
||||
copy(sb[:], s.b[*s.c:s.c.Inc(sig.Len)])
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *Splicer) Done() {}
|
||||
|
||||
Reference in New Issue
Block a user