forked from cwtch.im/tapir
Adding Integration Test
- Converted cmd/main to integ test - Factored in Identity from libricochet-go - Breaking up Auth run into smaller contained functions
This commit is contained in:
parent
f664afb021
commit
42d3cb196a
|
@ -21,6 +21,12 @@ pipeline:
|
||||||
commands:
|
commands:
|
||||||
- export PATH=$PATH:/go/src/cwtch.im/tapir
|
- export PATH=$PATH:/go/src/cwtch.im/tapir
|
||||||
- sh testing/tests.sh
|
- sh testing/tests.sh
|
||||||
|
integ-test:
|
||||||
|
image: golang
|
||||||
|
commands:
|
||||||
|
- ./tor -f ./torrc
|
||||||
|
- sleep 15
|
||||||
|
- go test -v cwtch.im/tapir/testing
|
||||||
notify-email:
|
notify-email:
|
||||||
image: drillster/drone-email
|
image: drillster/drone-email
|
||||||
host: build.openprivacy.ca
|
host: build.openprivacy.ca
|
||||||
|
|
|
@ -2,3 +2,4 @@ vendor/
|
||||||
.idea
|
.idea
|
||||||
/tor/
|
/tor/
|
||||||
coverage.out
|
coverage.out
|
||||||
|
/testing/tor/
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
package applications
|
package applications
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/rand"
|
|
||||||
"crypto/subtle"
|
"crypto/subtle"
|
||||||
"cwtch.im/tapir"
|
"cwtch.im/tapir"
|
||||||
|
"cwtch.im/tapir/primitives"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"git.openprivacy.ca/openprivacy/libricochet-go/identity"
|
|
||||||
"git.openprivacy.ca/openprivacy/libricochet-go/log"
|
"git.openprivacy.ca/openprivacy/libricochet-go/log"
|
||||||
"git.openprivacy.ca/openprivacy/libricochet-go/utils"
|
"git.openprivacy.ca/openprivacy/libricochet-go/utils"
|
||||||
"golang.org/x/crypto/ed25519"
|
"golang.org/x/crypto/ed25519"
|
||||||
|
@ -35,11 +34,8 @@ func (ea AuthApp) NewInstance() tapir.Application {
|
||||||
// or the connection is closed.
|
// or the connection is closed.
|
||||||
func (ea AuthApp) Init(connection tapir.Connection) {
|
func (ea AuthApp) Init(connection tapir.Connection) {
|
||||||
longTermPubKey := ed25519.PublicKey(connection.ID().PublicKeyBytes())
|
longTermPubKey := ed25519.PublicKey(connection.ID().PublicKeyBytes())
|
||||||
epk, esk, _ := ed25519.GenerateKey(rand.Reader)
|
ephemeralIdentity, _ := primitives.InitializeEphemeral()
|
||||||
ephemeralPublicKey := ed25519.PublicKey(epk)
|
authMessage := AuthMessage{LongTermPublicKey: longTermPubKey, EphemeralPublicKey: ephemeralIdentity.PublicKey()}
|
||||||
ephemeralPrivateKey := ed25519.PrivateKey(esk)
|
|
||||||
ephemeralIdentity := identity.InitializeV3("", &ephemeralPrivateKey, &ephemeralPublicKey)
|
|
||||||
authMessage := AuthMessage{LongTermPublicKey: longTermPubKey, EphemeralPublicKey: ephemeralPublicKey}
|
|
||||||
serialized, _ := json.Marshal(authMessage)
|
serialized, _ := json.Marshal(authMessage)
|
||||||
connection.Send(serialized)
|
connection.Send(serialized)
|
||||||
message := connection.Expect()
|
message := connection.Expect()
|
||||||
|
@ -51,23 +47,8 @@ func (ea AuthApp) Init(connection tapir.Connection) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3DH Handshake
|
key := primitives.Perform3DH(connection.ID(), &ephemeralIdentity, remoteAuthMessage.LongTermPublicKey, remoteAuthMessage.EphemeralPublicKey, connection.IsOutbound())
|
||||||
l2e := connection.ID().EDH(remoteAuthMessage.EphemeralPublicKey)
|
connection.SetEncryptionKey(key)
|
||||||
e2l := ephemeralIdentity.EDH(remoteAuthMessage.LongTermPublicKey)
|
|
||||||
e2e := ephemeralIdentity.EDH(remoteAuthMessage.EphemeralPublicKey)
|
|
||||||
|
|
||||||
// We need to define an order for the result concatenation so that both sides derive the same key.
|
|
||||||
var result [96]byte
|
|
||||||
if connection.IsOutbound() {
|
|
||||||
copy(result[0:32], l2e)
|
|
||||||
copy(result[32:64], e2l)
|
|
||||||
copy(result[64:96], e2e)
|
|
||||||
} else {
|
|
||||||
copy(result[0:32], e2l)
|
|
||||||
copy(result[32:64], l2e)
|
|
||||||
copy(result[64:96], e2e)
|
|
||||||
}
|
|
||||||
connection.SetEncryptionKey(sha3.Sum256(result[:]))
|
|
||||||
|
|
||||||
// Wait to Sync (we need to ensure that both the Local and Remote server have turned encryption on
|
// Wait to Sync (we need to ensure that both the Local and Remote server have turned encryption on
|
||||||
// otherwise our next Send will fail.
|
// otherwise our next Send will fail.
|
||||||
|
|
|
@ -2,22 +2,19 @@ package applications
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
|
"cwtch.im/tapir/primitives"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"git.openprivacy.ca/openprivacy/libricochet-go/identity"
|
|
||||||
"golang.org/x/crypto/ed25519"
|
"golang.org/x/crypto/ed25519"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
type MockConnection struct {
|
type MockConnection struct {
|
||||||
id identity.Identity
|
id primitives.Identity
|
||||||
outbound bool
|
outbound bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mc *MockConnection) Init(outbound bool) {
|
func (mc *MockConnection) Init(outbound bool) {
|
||||||
pubkey, privateKey, _ := ed25519.GenerateKey(rand.Reader)
|
mc.id, _ = primitives.InitializeEphemeral()
|
||||||
sk := ed25519.PrivateKey(privateKey)
|
|
||||||
pk := ed25519.PublicKey(pubkey)
|
|
||||||
mc.id = identity.InitializeV3("", &sk, &pk)
|
|
||||||
mc.outbound = outbound
|
mc.outbound = outbound
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -30,7 +27,7 @@ func (mc MockConnection) IsOutbound() bool {
|
||||||
return mc.outbound
|
return mc.outbound
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mc MockConnection) ID() *identity.Identity {
|
func (mc MockConnection) ID() *primitives.Identity {
|
||||||
return &mc.id
|
return &mc.id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,10 +3,10 @@ package tor
|
||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"cwtch.im/tapir"
|
"cwtch.im/tapir"
|
||||||
|
"cwtch.im/tapir/primitives"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"errors"
|
"errors"
|
||||||
"git.openprivacy.ca/openprivacy/libricochet-go/connectivity"
|
"git.openprivacy.ca/openprivacy/libricochet-go/connectivity"
|
||||||
"git.openprivacy.ca/openprivacy/libricochet-go/identity"
|
|
||||||
"git.openprivacy.ca/openprivacy/libricochet-go/log"
|
"git.openprivacy.ca/openprivacy/libricochet-go/log"
|
||||||
"golang.org/x/crypto/ed25519"
|
"golang.org/x/crypto/ed25519"
|
||||||
"sync"
|
"sync"
|
||||||
|
@ -17,14 +17,14 @@ import (
|
||||||
type BaseOnionService struct {
|
type BaseOnionService struct {
|
||||||
connections sync.Map
|
connections sync.Map
|
||||||
acn connectivity.ACN
|
acn connectivity.ACN
|
||||||
id identity.Identity
|
id *primitives.Identity
|
||||||
privateKey ed25519.PrivateKey
|
privateKey ed25519.PrivateKey
|
||||||
ls connectivity.ListenService
|
ls connectivity.ListenService
|
||||||
}
|
}
|
||||||
|
|
||||||
// Init initializes a BaseOnionService with a given private key and identity
|
// Init initializes a BaseOnionService with a given private key and identity
|
||||||
// The private key is needed to initialize the Onion listen socket, ideally we could just pass an Identity in here.
|
// The private key is needed to initialize the Onion listen socket, ideally we could just pass an Identity in here.
|
||||||
func (s *BaseOnionService) Init(acn connectivity.ACN, sk ed25519.PrivateKey, id identity.Identity) {
|
func (s *BaseOnionService) Init(acn connectivity.ACN, sk ed25519.PrivateKey, id *primitives.Identity) {
|
||||||
// run add onion
|
// run add onion
|
||||||
// get listen context
|
// get listen context
|
||||||
s.acn = acn
|
s.acn = acn
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
package primitives
|
||||||
|
|
||||||
|
import (
|
||||||
|
"golang.org/x/crypto/ed25519"
|
||||||
|
"golang.org/x/crypto/sha3"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Perform3DH encapsulates a triple-diffie-hellman key exchange.
|
||||||
|
// In this exchange Alice and Bob both hold longterm identity keypairs
|
||||||
|
// Both Alice and Bob generate an additional ephemeral key pair:
|
||||||
|
// 3 Diffie Hellman exchanges are then performed:
|
||||||
|
// Alice Long Term <-> Bob Ephemeral
|
||||||
|
// Alice Ephemeral <-> Bob Long Term
|
||||||
|
// Alice Ephemeral <-> Bob Ephemeral
|
||||||
|
//
|
||||||
|
// Through this, a unique session key is derived. The exchange is offline-deniable (in the context of Tapir and Onion Service)
|
||||||
|
func Perform3DH(longtermIdentity *Identity, ephemeralIdentity *Identity, remoteLongTermPublicKey ed25519.PublicKey, remoteEphemeralPublicKey ed25519.PublicKey, outbound bool) [32]byte {
|
||||||
|
// 3DH Handshake
|
||||||
|
l2e := longtermIdentity.EDH(remoteEphemeralPublicKey)
|
||||||
|
e2l := ephemeralIdentity.EDH(remoteLongTermPublicKey)
|
||||||
|
e2e := ephemeralIdentity.EDH(remoteEphemeralPublicKey)
|
||||||
|
|
||||||
|
// We need to define an order for the result concatenation so that both sides derive the same key.
|
||||||
|
var result [96]byte
|
||||||
|
if outbound {
|
||||||
|
copy(result[0:32], l2e)
|
||||||
|
copy(result[32:64], e2l)
|
||||||
|
copy(result[64:96], e2e)
|
||||||
|
} else {
|
||||||
|
copy(result[0:32], e2l)
|
||||||
|
copy(result[32:64], l2e)
|
||||||
|
copy(result[64:96], e2e)
|
||||||
|
}
|
||||||
|
return sha3.Sum256(result[:])
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
package primitives
|
||||||
|
|
||||||
|
import (
|
||||||
|
"crypto/rand"
|
||||||
|
"git.openprivacy.ca/openprivacy/libricochet-go/utils"
|
||||||
|
"golang.org/x/crypto/ed25519"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Identity is an encapsulation of Name, PrivateKey and other features
|
||||||
|
// that make up a Tapir client.
|
||||||
|
// The purpose of Identity is to prevent other classes directly accessing private key
|
||||||
|
// and to ensure the integrity of security-critical functions.
|
||||||
|
type Identity struct {
|
||||||
|
Name string
|
||||||
|
edpk *ed25519.PrivateKey
|
||||||
|
edpubk *ed25519.PublicKey
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize is a courtesy function for initializing a V3 Identity in-code.
|
||||||
|
func Initialize(name string, pk *ed25519.PrivateKey, pubk *ed25519.PublicKey) Identity {
|
||||||
|
return Identity{name, pk, pubk}
|
||||||
|
}
|
||||||
|
|
||||||
|
// InitializeEphemeral generates a new ephemeral identity, the private key of this identity is provided in the response.
|
||||||
|
func InitializeEphemeral() (Identity, ed25519.PrivateKey) {
|
||||||
|
epk, esk, _ := ed25519.GenerateKey(rand.Reader)
|
||||||
|
ephemeralPublicKey := ed25519.PublicKey(epk)
|
||||||
|
ephemeralPrivateKey := ed25519.PrivateKey(esk)
|
||||||
|
ephemeralIdentity := Initialize("", &ephemeralPrivateKey, &ephemeralPublicKey)
|
||||||
|
return ephemeralIdentity, ephemeralPrivateKey
|
||||||
|
}
|
||||||
|
|
||||||
|
// PublicKeyBytes returns the public key associated with this Identity in serializable-friendly
|
||||||
|
// format.
|
||||||
|
func (i *Identity) PublicKeyBytes() []byte {
|
||||||
|
return *i.edpubk
|
||||||
|
}
|
||||||
|
|
||||||
|
// PublicKey returns the public key associated with this Identity
|
||||||
|
func (i *Identity) PublicKey() ed25519.PublicKey {
|
||||||
|
return *i.edpubk
|
||||||
|
}
|
||||||
|
|
||||||
|
// EDH performs a diffie helman operation on this identities private key with the given public key.
|
||||||
|
func (i *Identity) EDH(key ed25519.PublicKey) []byte {
|
||||||
|
secret := utils.EDH(*i.edpk, key)
|
||||||
|
return secret[:]
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hostname provides the onion address associated with this Identity.
|
||||||
|
func (i *Identity) Hostname() string {
|
||||||
|
return utils.GetTorV3Hostname(*i.edpubk)
|
||||||
|
}
|
14
service.go
14
service.go
|
@ -2,9 +2,9 @@ package tapir
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
|
"cwtch.im/tapir/primitives"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"git.openprivacy.ca/openprivacy/libricochet-go/connectivity"
|
"git.openprivacy.ca/openprivacy/libricochet-go/connectivity"
|
||||||
"git.openprivacy.ca/openprivacy/libricochet-go/identity"
|
|
||||||
"git.openprivacy.ca/openprivacy/libricochet-go/log"
|
"git.openprivacy.ca/openprivacy/libricochet-go/log"
|
||||||
"golang.org/x/crypto/ed25519"
|
"golang.org/x/crypto/ed25519"
|
||||||
"golang.org/x/crypto/nacl/secretbox"
|
"golang.org/x/crypto/nacl/secretbox"
|
||||||
|
@ -15,7 +15,7 @@ import (
|
||||||
|
|
||||||
// Service defines the interface for a Tapir Service
|
// Service defines the interface for a Tapir Service
|
||||||
type Service interface {
|
type Service interface {
|
||||||
Init(acn connectivity.ACN, privateKey ed25519.PrivateKey, identity identity.Identity)
|
Init(acn connectivity.ACN, privateKey ed25519.PrivateKey, identity *primitives.Identity)
|
||||||
Connect(hostname string, application Application) (bool, error)
|
Connect(hostname string, application Application) (bool, error)
|
||||||
Listen(application Application) error
|
Listen(application Application) error
|
||||||
GetConnection(connectionID string) (Connection, error)
|
GetConnection(connectionID string) (Connection, error)
|
||||||
|
@ -27,7 +27,7 @@ type Service interface {
|
||||||
type Connection interface {
|
type Connection interface {
|
||||||
Hostname() string
|
Hostname() string
|
||||||
IsOutbound() bool
|
IsOutbound() bool
|
||||||
ID() *identity.Identity
|
ID() *primitives.Identity
|
||||||
Expect() []byte
|
Expect() []byte
|
||||||
SetHostname(hostname string)
|
SetHostname(hostname string)
|
||||||
HasCapability(name string) bool
|
HasCapability(name string) bool
|
||||||
|
@ -46,19 +46,19 @@ type connection struct {
|
||||||
encrypted bool
|
encrypted bool
|
||||||
key [32]byte
|
key [32]byte
|
||||||
App Application
|
App Application
|
||||||
identity *identity.Identity
|
identity *primitives.Identity
|
||||||
outbound bool
|
outbound bool
|
||||||
closed bool
|
closed bool
|
||||||
MaxLength int
|
MaxLength int
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewConnection creates a new Connection
|
// NewConnection creates a new Connection
|
||||||
func NewConnection(id identity.Identity, hostname string, outbound bool, conn net.Conn, app Application) Connection {
|
func NewConnection(id *primitives.Identity, hostname string, outbound bool, conn net.Conn, app Application) Connection {
|
||||||
connection := new(connection)
|
connection := new(connection)
|
||||||
connection.hostname = hostname
|
connection.hostname = hostname
|
||||||
connection.conn = conn
|
connection.conn = conn
|
||||||
connection.App = app
|
connection.App = app
|
||||||
connection.identity = &id
|
connection.identity = id
|
||||||
connection.outbound = outbound
|
connection.outbound = outbound
|
||||||
connection.MaxLength = 1024
|
connection.MaxLength = 1024
|
||||||
go connection.App.Init(connection)
|
go connection.App.Init(connection)
|
||||||
|
@ -66,7 +66,7 @@ func NewConnection(id identity.Identity, hostname string, outbound bool, conn ne
|
||||||
}
|
}
|
||||||
|
|
||||||
// ID returns an identity.Identity encapsulation (for the purposes of cryptographic protocols)
|
// ID returns an identity.Identity encapsulation (for the purposes of cryptographic protocols)
|
||||||
func (c *connection) ID() *identity.Identity {
|
func (c *connection) ID() *primitives.Identity {
|
||||||
return c.identity
|
return c.identity
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,16 +1,17 @@
|
||||||
package main
|
package testing
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/rand"
|
|
||||||
"cwtch.im/tapir"
|
"cwtch.im/tapir"
|
||||||
"cwtch.im/tapir/applications"
|
"cwtch.im/tapir/applications"
|
||||||
"cwtch.im/tapir/networks/tor"
|
"cwtch.im/tapir/networks/tor"
|
||||||
|
"cwtch.im/tapir/primitives"
|
||||||
"git.openprivacy.ca/openprivacy/libricochet-go/connectivity"
|
"git.openprivacy.ca/openprivacy/libricochet-go/connectivity"
|
||||||
"git.openprivacy.ca/openprivacy/libricochet-go/identity"
|
|
||||||
"git.openprivacy.ca/openprivacy/libricochet-go/log"
|
"git.openprivacy.ca/openprivacy/libricochet-go/log"
|
||||||
"git.openprivacy.ca/openprivacy/libricochet-go/utils"
|
"git.openprivacy.ca/openprivacy/libricochet-go/utils"
|
||||||
"golang.org/x/crypto/ed25519"
|
"golang.org/x/crypto/ed25519"
|
||||||
"os"
|
"runtime"
|
||||||
|
"sync"
|
||||||
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -37,60 +38,82 @@ func (ea SimpleApp) Init(connection tapir.Connection) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var AuthSuccess = false
|
||||||
|
|
||||||
// CheckConnection is a simple test that GetConnection is working.
|
// CheckConnection is a simple test that GetConnection is working.
|
||||||
func CheckConnection(service tapir.Service, hostname string) {
|
func CheckConnection(service tapir.Service, hostname string, group *sync.WaitGroup) {
|
||||||
for {
|
for {
|
||||||
_, err := service.GetConnection(hostname)
|
_, err := service.GetConnection(hostname)
|
||||||
if err == nil {
|
if err == nil {
|
||||||
log.Infof("Authed!")
|
log.Infof("Authed!")
|
||||||
|
group.Done()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
log.Errorf("Error %v", err)
|
log.Infof("Waiting for Authentication...%v", err)
|
||||||
time.Sleep(time.Second)
|
time.Sleep(time.Second * 5)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func TestTapir(t *testing.T) {
|
||||||
|
|
||||||
|
numRoutinesStart := runtime.NumGoroutine()
|
||||||
log.SetLevel(log.LevelDebug)
|
log.SetLevel(log.LevelDebug)
|
||||||
|
log.Infof("Number of goroutines open at start: %d", runtime.NumGoroutine())
|
||||||
// Connect to Tor
|
// Connect to Tor
|
||||||
var acn connectivity.ACN
|
var acn connectivity.ACN
|
||||||
acn, _ = connectivity.StartTor("./", "")
|
acn, _ = connectivity.StartTor("./", "")
|
||||||
acn.WaitTillBootstrapped()
|
acn.WaitTillBootstrapped()
|
||||||
|
|
||||||
// Generate Server Keys
|
// Generate Server Keys
|
||||||
pubkey, privateKey, _ := ed25519.GenerateKey(rand.Reader)
|
id, sk := primitives.InitializeEphemeral()
|
||||||
sk := ed25519.PrivateKey(privateKey)
|
|
||||||
pk := ed25519.PublicKey(pubkey)
|
|
||||||
id := identity.InitializeV3("server", &sk, &pk)
|
|
||||||
|
|
||||||
// Init a Client to Connect to the Server
|
|
||||||
client, clienthostname := genclient(acn)
|
|
||||||
go connectclient(client, pubkey)
|
|
||||||
|
|
||||||
// Init the Server running the Simple App.
|
// Init the Server running the Simple App.
|
||||||
var service tapir.Service
|
var service tapir.Service
|
||||||
service = new(tor.BaseOnionService)
|
service = new(tor.BaseOnionService)
|
||||||
service.Init(acn, sk, id)
|
service.Init(acn, sk, &id)
|
||||||
go CheckConnection(service, clienthostname)
|
|
||||||
|
// Goroutine Management
|
||||||
|
sg := new(sync.WaitGroup)
|
||||||
|
sg.Add(1)
|
||||||
|
go func() {
|
||||||
service.Listen(SimpleApp{})
|
service.Listen(SimpleApp{})
|
||||||
|
sg.Done()
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Wait for server to come online
|
||||||
|
time.Sleep(time.Second * 30)
|
||||||
|
wg := new(sync.WaitGroup)
|
||||||
|
wg.Add(2)
|
||||||
|
// Init a Client to Connect to the Server
|
||||||
|
client, clienthostname := genclient(acn)
|
||||||
|
go connectclient(client, id.PublicKey(), wg)
|
||||||
|
CheckConnection(service, clienthostname, wg)
|
||||||
|
wg.Wait()
|
||||||
|
// Wait for Server to Sync
|
||||||
|
time.Sleep(time.Second * 2)
|
||||||
|
log.Infof("Closing ACN...")
|
||||||
|
acn.Close()
|
||||||
|
sg.Wait()
|
||||||
|
time.Sleep(time.Second * 2)
|
||||||
|
log.Infof("Number of goroutines open at close: %d", runtime.NumGoroutine())
|
||||||
|
if numRoutinesStart != runtime.NumGoroutine() {
|
||||||
|
t.Errorf("Potential goroutine leak: Num Start:%v NumEnd: %v", numRoutinesStart, runtime.NumGoroutine())
|
||||||
|
}
|
||||||
|
if !AuthSuccess {
|
||||||
|
t.Fatalf("Integration Test FAILED, client did not auth with server")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func genclient(acn connectivity.ACN) (tapir.Service, string) {
|
func genclient(acn connectivity.ACN) (tapir.Service, string) {
|
||||||
pubkey, privateKey, _ := ed25519.GenerateKey(rand.Reader)
|
id, sk := primitives.InitializeEphemeral()
|
||||||
sk := ed25519.PrivateKey(privateKey)
|
|
||||||
pk := ed25519.PublicKey(pubkey)
|
|
||||||
id := identity.InitializeV3("client", &sk, &pk)
|
|
||||||
var client tapir.Service
|
var client tapir.Service
|
||||||
client = new(tor.BaseOnionService)
|
client = new(tor.BaseOnionService)
|
||||||
client.Init(acn, sk, id)
|
client.Init(acn, sk, &id)
|
||||||
return client, utils.GetTorV3Hostname(pk)
|
return client, id.Hostname()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Client will Connect and launch it's own Echo App goroutine.
|
// Client will Connect and launch it's own Echo App goroutine.
|
||||||
func connectclient(client tapir.Service, key ed25519.PublicKey) {
|
func connectclient(client tapir.Service, key ed25519.PublicKey, group *sync.WaitGroup) {
|
||||||
|
|
||||||
client.Connect(utils.GetTorV3Hostname(key), SimpleApp{})
|
client.Connect(utils.GetTorV3Hostname(key), SimpleApp{})
|
||||||
|
|
||||||
// Once connected, it shouldn't take long to authenticate and run the application. So for the purposes of this demo
|
// Once connected, it shouldn't take long to authenticate and run the application. So for the purposes of this demo
|
||||||
|
@ -99,6 +122,6 @@ func connectclient(client tapir.Service, key ed25519.PublicKey) {
|
||||||
|
|
||||||
conn, _ := client.GetConnection(utils.GetTorV3Hostname(key))
|
conn, _ := client.GetConnection(utils.GetTorV3Hostname(key))
|
||||||
log.Debugf("Client has Auth: %v", conn.HasCapability(applications.AuthCapability))
|
log.Debugf("Client has Auth: %v", conn.HasCapability(applications.AuthCapability))
|
||||||
|
AuthSuccess = true
|
||||||
os.Exit(0)
|
group.Done()
|
||||||
}
|
}
|
Loading…
Reference in New Issue