added signature to introduction for spoofing protection
This commit is contained in:
@@ -2,9 +2,9 @@ package hiddenservice
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"git-indra.lan/indra-labs/indra"
|
"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/nonce"
|
||||||
"git-indra.lan/indra-labs/indra/pkg/crypto/sha256"
|
"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"
|
"git-indra.lan/indra-labs/indra/pkg/messages/magicbytes"
|
||||||
log2 "git-indra.lan/indra-labs/indra/pkg/proc/log"
|
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/splice"
|
||||||
@@ -14,7 +14,7 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
MagicString = "hs"
|
MagicString = "hs"
|
||||||
Len = magicbytes.Len + nonce.IDLen + pub.KeyLen +
|
Len = magicbytes.Len + nonce.IDLen + intro.Len +
|
||||||
3*sha256.Len + nonce.IVLen*3
|
3*sha256.Len + nonce.IVLen*3
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -30,11 +30,7 @@ var (
|
|||||||
// header for any client that requests it.
|
// header for any client that requests it.
|
||||||
type Layer struct {
|
type Layer struct {
|
||||||
nonce.ID
|
nonce.ID
|
||||||
// Identity is a public key identifying the hidden service. It is encoded
|
intro.Layer
|
||||||
// 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
|
|
||||||
// Ciphers 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.
|
// given order over the reply message from the service.
|
||||||
Ciphers [3]sha256.Hash
|
Ciphers [3]sha256.Hash
|
||||||
@@ -56,7 +52,9 @@ func (x *Layer) Encode(b slice.Bytes, c *slice.Cursor) {
|
|||||||
splice.Splice(b, c).
|
splice.Splice(b, c).
|
||||||
Magic(Magic).
|
Magic(Magic).
|
||||||
ID(x.ID).
|
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]).
|
Hash(x.Ciphers[0]).Hash(x.Ciphers[1]).Hash(x.Ciphers[2]).
|
||||||
IV(x.Nonces[0]).IV(x.Nonces[1]).IV(x.Nonces[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).
|
splice.Splice(b, c).
|
||||||
ReadID(&x.ID).
|
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]).
|
ReadHash(&x.Ciphers[0]).ReadHash(&x.Ciphers[1]).ReadHash(&x.Ciphers[2]).
|
||||||
ReadIV(&x.Nonces[0]).ReadIV(&x.Nonces[1]).ReadIV(&x.Nonces[2])
|
ReadIV(&x.Nonces[0]).ReadIV(&x.Nonces[1]).ReadIV(&x.Nonces[2])
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -4,17 +4,27 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"net/netip"
|
"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/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"
|
"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/splice"
|
||||||
"git-indra.lan/indra-labs/indra/pkg/types"
|
"git-indra.lan/indra-labs/indra/pkg/types"
|
||||||
"git-indra.lan/indra-labs/indra/pkg/util/slice"
|
"git-indra.lan/indra-labs/indra/pkg/util/slice"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
log = log2.GetLogger(indra.PathBase)
|
||||||
|
check = log.E.Chk
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
MagicString = "in"
|
MagicString = "in"
|
||||||
AddrLen = net.IPv6len + 3
|
AddrLen = net.IPv6len + 3
|
||||||
Len = magicbytes.Len + pub.KeyLen + AddrLen
|
Len = magicbytes.Len + pub.KeyLen + AddrLen + sig.Len
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -24,17 +34,57 @@ var (
|
|||||||
type Layer struct {
|
type Layer struct {
|
||||||
*pub.Key
|
*pub.Key
|
||||||
*netip.AddrPort
|
*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) Insert(o types.Onion) {}
|
||||||
func (im *Layer) Len() int { return Len }
|
func (im *Layer) Len() int { return Len }
|
||||||
|
|
||||||
func (im *Layer) Encode(b slice.Bytes, c *slice.Cursor) {
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (im *Layer) Decode(b slice.Bytes, c *slice.Cursor) (e error) {
|
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
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ var (
|
|||||||
// is concealed to the hops except for the encryption crypt they decrypt using
|
// is concealed to the hops except for the encryption crypt they decrypt using
|
||||||
// their Payload key, delivered in this message.
|
// their Payload key, delivered in this message.
|
||||||
type Layer struct {
|
type Layer struct {
|
||||||
nonce.ID
|
nonce.ID // only used by a node
|
||||||
Hop byte // only used by a node
|
Hop byte // only used by a node
|
||||||
Header, Payload *prv.Key
|
Header, Payload *prv.Key
|
||||||
types.Onion
|
types.Onion
|
||||||
|
|||||||
@@ -10,9 +10,9 @@ import (
|
|||||||
"go.uber.org/atomic"
|
"go.uber.org/atomic"
|
||||||
|
|
||||||
"git-indra.lan/indra-labs/indra/pkg/crypto/key/prv"
|
"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/nonce"
|
||||||
"git-indra.lan/indra-labs/indra/pkg/crypto/sha256"
|
"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"
|
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/service"
|
||||||
"git-indra.lan/indra-labs/indra/pkg/transport"
|
"git-indra.lan/indra-labs/indra/pkg/transport"
|
||||||
@@ -290,10 +290,10 @@ func TestClient_HiddenService(t *testing.T) {
|
|||||||
t.Error(e)
|
t.Error(e)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
identPub := pub.Derive(identPrv)
|
|
||||||
id := nonce.NewID()
|
id := nonce.NewID()
|
||||||
|
il := intro.New(identPrv, clients[0].GetLocalNodeAddress())
|
||||||
clients[0].SendIntro(id, clients[0].Sessions[i+returns],
|
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")
|
log.I.Ln("success")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -303,7 +303,7 @@ func TestClient_HiddenService(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
func TestClient_HiddenServiceBroadcast(t *testing.T) {
|
func TestClient_HiddenServiceBroadcast(t *testing.T) {
|
||||||
log2.SetLogLevel(log2.Trace)
|
log2.SetLogLevel(log2.Info)
|
||||||
var clients []*Engine
|
var clients []*Engine
|
||||||
var e error
|
var e error
|
||||||
const returns = 2
|
const returns = 2
|
||||||
@@ -340,10 +340,12 @@ func TestClient_HiddenServiceBroadcast(t *testing.T) {
|
|||||||
t.Error(e)
|
t.Error(e)
|
||||||
t.FailNow()
|
t.FailNow()
|
||||||
}
|
}
|
||||||
identPub := pub.Derive(identPrv)
|
log2.SetLogLevel(log2.Trace)
|
||||||
|
// identPub := pub.Derive(identPrv)
|
||||||
id := nonce.NewID()
|
id := nonce.NewID()
|
||||||
|
il := intro.New(identPrv, clients[0].GetLocalNodeAddress())
|
||||||
clients[0].SendIntro(id, clients[0].Sessions[returns],
|
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")
|
log.I.Ln("success")
|
||||||
})
|
})
|
||||||
time.Sleep(time.Second * 5)
|
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) {
|
c *slice.Cursor, prev types.Onion) {
|
||||||
|
|
||||||
log.D.F("%s adding introduction for key %s", eng.GetLocalNodeAddress(),
|
log.D.F("%s adding introduction for key %s", eng.GetLocalNodeAddress(),
|
||||||
hs.Identity.ToBase32())
|
hs.Layer.Key.ToBase32())
|
||||||
eng.Introductions.AddIntro(hs.Identity, b[*c:])
|
eng.Introductions.AddIntro(hs.Layer.Key, b[*c:])
|
||||||
log.I.Ln("stored new introduction, starting broadcast")
|
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) {
|
c *slice.Cursor, prev types.Onion) {
|
||||||
|
|
||||||
log.D.Ln(prev == nil)
|
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())
|
pi := eng.FindPendingPreimage(on.PreimageHash())
|
||||||
if pi != nil {
|
if pi != nil {
|
||||||
// We need to delete this first in case somehow two such messages arrive
|
// We need to delete this first in case somehow two such messages arrive
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
package relay
|
package relay
|
||||||
|
|
||||||
import (
|
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/crypto/nonce"
|
||||||
|
"git-indra.lan/indra-labs/indra/pkg/messages/intro"
|
||||||
"git-indra.lan/indra-labs/indra/pkg/util/slice"
|
"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)) {
|
hook func(id nonce.ID, b slice.Bytes)) {
|
||||||
|
|
||||||
log.I.Ln(target.Hop)
|
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)
|
se := eng.SelectHops(hops, s)
|
||||||
var c Circuit
|
var c Circuit
|
||||||
copy(c[:], se)
|
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")
|
log.D.Ln("sending out intro onion")
|
||||||
res := eng.PostAcctOnion(o)
|
res := eng.PostAcctOnion(o)
|
||||||
eng.SendWithOneHook(c[0].AddrPort, res, hook)
|
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/pub"
|
||||||
"git-indra.lan/indra-labs/indra/pkg/crypto/key/signer"
|
"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/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 {
|
ks *signer.KeySet) Skins {
|
||||||
|
|
||||||
var prvs [3]*prv.Key
|
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[0], ks.Next(), n[0], 3).
|
||||||
ReverseCrypt(s[1], ks.Next(), n[1], 2).
|
ReverseCrypt(s[1], ks.Next(), n[1], 2).
|
||||||
ReverseCrypt(s[2], ks.Next(), n[2], 1).
|
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[3], prvs[0], n[3], 3).
|
||||||
ReverseCrypt(s[4], prvs[1], n[4], 2).
|
ReverseCrypt(s[4], prvs[1], n[4], 2).
|
||||||
ReverseCrypt(client, prvs[2], n[5], 1)
|
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/forward"
|
||||||
"git-indra.lan/indra-labs/indra/pkg/messages/getbalance"
|
"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/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/noop"
|
||||||
"git-indra.lan/indra-labs/indra/pkg/messages/response"
|
"git-indra.lan/indra-labs/indra/pkg/messages/response"
|
||||||
"git-indra.lan/indra-labs/indra/pkg/messages/reverse"
|
"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 {
|
pubs [3]*pub.Key, nonces [3]nonce.IV) Skins {
|
||||||
return append(o, &hiddenservice.Layer{
|
return append(o, &hiddenservice.Layer{
|
||||||
ID: id,
|
ID: id,
|
||||||
Identity: addr,
|
Layer: *intr,
|
||||||
Ciphers: GenCiphers(prvs, pubs),
|
Ciphers: GenCiphers(prvs, pubs),
|
||||||
Nonces: nonces,
|
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/cloak"
|
||||||
"git-indra.lan/indra-labs/indra/pkg/crypto/key/prv"
|
"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/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/nonce"
|
||||||
"git-indra.lan/indra-labs/indra/pkg/crypto/sha256"
|
"git-indra.lan/indra-labs/indra/pkg/crypto/sha256"
|
||||||
"git-indra.lan/indra-labs/indra/pkg/messages/magicbytes"
|
"git-indra.lan/indra-labs/indra/pkg/messages/magicbytes"
|
||||||
@@ -177,4 +178,14 @@ func (s *Splicer) Bytes(b []byte) *Splicer {
|
|||||||
return s
|
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() {}
|
func (s *Splicer) Done() {}
|
||||||
|
|||||||
Reference in New Issue
Block a user