code.pfad.fr/gohmekit@v0.2.1/pairing/pair_verify_test.go (about)

     1  package pairing_test
     2  
     3  import (
     4  	"crypto/ed25519"
     5  	"net"
     6  	"net/http"
     7  	"testing"
     8  
     9  	"code.pfad.fr/gohmekit/pairing"
    10  	"code.pfad.fr/gohmekit/storage"
    11  	"github.com/brutella/hc/db"
    12  	"github.com/brutella/hc/hap"
    13  	"github.com/brutella/hc/hap/pair"
    14  	"github.com/brutella/hc/util"
    15  	"gotest.tools/v3/assert"
    16  )
    17  
    18  // Tests the pairing key verification.
    19  func TestPairVerifyIntegration(t *testing.T) {
    20  	database := storage.NewMemDatabase()
    21  	_, privateKey, err := ed25519.GenerateKey(nil)
    22  	assert.NilError(t, err)
    23  	bridge, err := pairing.NewDeviceWithPin(pairing.NewRandomPairingID(), "001-02-003", privateKey)
    24  	assert.NilError(t, err)
    25  
    26  	s := pairing.NewServer(&http.Server{}, bridge, database)
    27  
    28  	addr := startServer(t, s)
    29  
    30  	clientStorage, err := util.NewFileStorage(t.TempDir())
    31  	assert.NilError(t, err)
    32  
    33  	clientDatabase := db.NewDatabaseWithStorage(clientStorage)
    34  	bridgeEntity := db.NewEntity(string(bridge.PairingID()), bridge.OwnLongTermPublicKey(), nil)
    35  	err = clientDatabase.SaveEntity(bridgeEntity)
    36  	assert.NilError(t, err)
    37  
    38  	client, err := hap.NewDevice("HomeKit Client", clientDatabase)
    39  	assert.NilError(t, err)
    40  	err = database.AddLongTermPublicKey(pairing.Controller{PairingID: []byte(client.Name()), LongTermPublicKey: client.PublicKey()})
    41  	assert.NilError(t, err)
    42  
    43  	clientController := pair.NewVerifyClientController(client, clientDatabase)
    44  
    45  	tlvVerifyStepStartRequest := clientController.InitialKeyVerifyRequest()
    46  
    47  	httpClient, encryptClientConn := newHTTPClient()
    48  	_ = encryptClientConn
    49  
    50  	// 1) C -> S
    51  	resp, err := httpClient.Post(addr+"pair-verify", pairing.ContentType, tlvVerifyStepStartRequest)
    52  	assert.NilError(t, err)
    53  	assert.Equal(t, 200, resp.StatusCode)
    54  
    55  	// 2) S -> C
    56  	tlvFinishRequest, err := pair.HandleReaderForHandler(resp.Body, clientController)
    57  	assert.NilError(t, err)
    58  	assert.NilError(t, resp.Body.Close())
    59  
    60  	// 3) C -> S
    61  	resp, err = httpClient.Post(addr+"pair-verify", pairing.ContentType, tlvFinishRequest)
    62  	assert.NilError(t, err)
    63  	assert.Equal(t, 200, resp.StatusCode)
    64  
    65  	// // 4) S -> C
    66  	response, err := pair.HandleReaderForHandler(resp.Body, clientController)
    67  	assert.NilError(t, err)
    68  	assert.NilError(t, resp.Body.Close())
    69  	assert.Equal(t, response, nil)
    70  }
    71  
    72  func BenchmarkPairVerify(b *testing.B) {
    73  	database := storage.NewMemDatabase()
    74  	_, privateKey, err := ed25519.GenerateKey(nil)
    75  
    76  	assert.NilError(b, err)
    77  	bridge, err := pairing.NewDeviceWithPin(pairing.NewRandomPairingID(), "001-02-003", privateKey)
    78  	assert.NilError(b, err)
    79  
    80  	s := pairing.NewServer(&http.Server{}, bridge, database)
    81  
    82  	ln, err := net.Listen("tcp", ":0")
    83  	assert.NilError(b, err)
    84  	defer func() {
    85  		assert.NilError(b, ln.Close())
    86  	}()
    87  	go s.Serve(ln) //nolint:errcheck
    88  	addr := "http://" + ln.Addr().String() + "/"
    89  
    90  	clientStorage, err := util.NewFileStorage(b.TempDir())
    91  	assert.NilError(b, err)
    92  
    93  	clientDatabase := db.NewDatabaseWithStorage(clientStorage)
    94  	bridgeEntity := db.NewEntity(string(bridge.PairingID()), bridge.OwnLongTermPublicKey(), nil)
    95  	err = clientDatabase.SaveEntity(bridgeEntity)
    96  	assert.NilError(b, err)
    97  
    98  	client, err := hap.NewDevice("HomeKit Client", clientDatabase)
    99  	assert.NilError(b, err)
   100  	err = database.AddLongTermPublicKey(pairing.Controller{PairingID: []byte(client.Name()), LongTermPublicKey: client.PublicKey()})
   101  	assert.NilError(b, err)
   102  
   103  	for i := 0; i < b.N; i++ {
   104  		clientController := pair.NewVerifyClientController(client, clientDatabase)
   105  
   106  		tlvVerifyStepStartRequest := clientController.InitialKeyVerifyRequest()
   107  
   108  		httpClient, encryptClientConn := newHTTPClient()
   109  		_ = encryptClientConn
   110  
   111  		// 1) C -> S
   112  		resp, err := httpClient.Post(addr+"pair-verify", pairing.ContentType, tlvVerifyStepStartRequest)
   113  		assert.NilError(b, err)
   114  		assert.Equal(b, 200, resp.StatusCode)
   115  
   116  		// 2) S -> C
   117  		tlvFinishRequest, err := pair.HandleReaderForHandler(resp.Body, clientController)
   118  		assert.NilError(b, err)
   119  		assert.NilError(b, resp.Body.Close())
   120  
   121  		// 3) C -> S
   122  		resp, err = httpClient.Post(addr+"pair-verify", pairing.ContentType, tlvFinishRequest)
   123  		assert.NilError(b, err)
   124  		assert.Equal(b, 200, resp.StatusCode)
   125  
   126  		// // 4) S -> C
   127  		response, err := pair.HandleReaderForHandler(resp.Body, clientController)
   128  		assert.NilError(b, err)
   129  		assert.NilError(b, resp.Body.Close())
   130  		assert.Equal(b, response, nil)
   131  	}
   132  }