6
1
mirror of https://git.mills.io/saltyim/saltyim.git synced 2024-06-30 18:51:03 +00:00
prologic-saltyim/client_test.go
James Mills ddd16c202f Add blob service and support for signing and verifying HTTP requests (#178)
Alternative to #177

The way this works is:

Client:

- Client creates a normal `net/http.Request{}` object using the `Request()` function in `utils.go`. The `http.Request{}` object is then signed using the Client's Ed25519 private key.
- The HTTP Method and Path (_note this is important_) are hashed, as well as the request body (if any) using the FNV128a hashing algorithm.
- This hash is then signed by the Client's's Ed25519 private key.
- The resulting signature is then encoded to Base64 (_standard encoding_) and added to the HTTP headers as a `Signature:` header.
- In addition the Client's Ed25519 public key is added to the HTTP headers as `Signer:`

Server:

- The server calculates the same FNV128a hash of the HTTP Request Method and Path and the body (if any)
- The server decodes the HTTP header `Signature:`
- The server then uses the Client's Ed25519 public key in the HTTP header `Signer:` to verify the signature of the `Signature:` HTTP header which gives us back the original FNV128a hash the Client calculated for the request.
- The server then compares the Client's hash with the expected hash to see if they compare equally.

Co-authored-by: James Mills <1290234+prologic@users.noreply.github.com>
Co-authored-by: Jon Lundy <jon@xuu.cc>
Reviewed-on: https://git.mills.io/saltyim/saltyim/pulls/178
Reviewed-by: xuu <xuu@noreply@mills.io>
2023-01-25 23:05:29 +00:00

60 lines
1.6 KiB
Go

package saltyim
import (
"crypto/sha256"
"fmt"
"net/url"
"testing"
"github.com/keys-pub/keys"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestClient_InvalidEndpoint(t *testing.T) {
assert := assert.New(t)
require := require.New(t)
me, err := ParseAddr("foo@example.com")
require.NoError(err)
assert.NotNil(me)
_, err = NewClient(WithAddr(me))
require.Error(err)
}
func TestClient_Outbox(t *testing.T) {
assert := assert.New(t)
require := require.New(t)
endpoint := &url.URL{Host: "example.com", Path: "/path", Scheme: "https"}
key := keys.GenerateEdX25519Key()
client := &Client{me: &Addr{endpoint: endpoint}, id: &Identity{key: key}}
outbox := client.Outbox()
require.True(endpoint.Path == "/path",
"endpoint.Path should not be modified after call to client.Outbox()")
require.False(*endpoint == *outbox,
"endpoint and outbox should not point to the same *url.URL")
expected := fmt.Sprintf("/%x", sha256.Sum256(key.Private()))
assert.Equal(expected, outbox.Path, "expected %s but got %s", expected, outbox.Path)
}
func TestClient_Outbox_State(t *testing.T) {
req := require.New(t)
endpoint := &url.URL{Host: "example.com", Path: "/path", Scheme: "https"}
key := keys.GenerateEdX25519Key()
state := NewState()
var testIndex int64 = 100
state.SetIndex("testIndex", testIndex)
client := &Client{me: &Addr{endpoint: endpoint}, id: &Identity{key: key}, state: state}
outboxClient := client.OutboxClient(nil)
req.Equal(state, outboxClient.state)
req.Equal(testIndex, outboxClient.state.GetIndex("testIndex"))
}