mirror of
https://git.mills.io/saltyim/saltyim.git
synced 2024-06-28 09:41:02 +00:00
![James Mills](/assets/img/avatar_default.png)
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>
133 lines
3.0 KiB
Go
133 lines
3.0 KiB
Go
package internal
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"go.mills.io/saltyim"
|
|
)
|
|
|
|
const (
|
|
wellknownPath = ".well-known/salty"
|
|
avatarsPath = "avatars"
|
|
avatarResolution = 80 // 80x80 px
|
|
blobsPath = "blobs"
|
|
)
|
|
|
|
var (
|
|
ErrAddressExists = errors.New("error: address already exists")
|
|
ErrBlobNotFound = errors.New("error: blob not found")
|
|
)
|
|
|
|
func CreateConfig(conf *Config, hash string, key string) error {
|
|
p := filepath.Join(conf.Data, wellknownPath)
|
|
p = saltyim.FixUnixHome(p)
|
|
|
|
fn := filepath.Join(p, fmt.Sprintf("%s.json", hash))
|
|
if FileExists(fn) {
|
|
return ErrAddressExists
|
|
}
|
|
|
|
if err := os.MkdirAll(p, 0755); err != nil {
|
|
return fmt.Errorf("error creating config paths %s: %w", p, err)
|
|
}
|
|
|
|
ulid, err := saltyim.GenerateULID()
|
|
if err != nil {
|
|
return fmt.Errorf("error generating ulid")
|
|
}
|
|
|
|
endpointURL := *conf.baseURL
|
|
endpointURL.Path = fmt.Sprintf("/inbox/%s", ulid)
|
|
|
|
config := saltyim.Config{
|
|
Endpoint: endpointURL.String(),
|
|
Key: key,
|
|
}
|
|
|
|
data, err := json.Marshal(config)
|
|
if err != nil {
|
|
return fmt.Errorf("error serializing config")
|
|
}
|
|
|
|
if err := os.WriteFile(fn, data, 0644); err != nil {
|
|
return fmt.Errorf("error writing config to %s: %w", fn, err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func CreateOrUpdateAvatar(conf *Config, addr *saltyim.Addr, contents []byte) error {
|
|
p := filepath.Join(conf.Data, avatarsPath)
|
|
p = saltyim.FixUnixHome(p)
|
|
|
|
if err := os.MkdirAll(p, 0755); err != nil {
|
|
return fmt.Errorf("error creating avatars paths %s: %w", p, err)
|
|
}
|
|
|
|
fn := filepath.Join(p, fmt.Sprintf("%s.png", addr.Hash()))
|
|
|
|
if err := SaveAvatar(fn, bytes.NewBuffer(contents), avatarResolution); err != nil {
|
|
return fmt.Errorf("error writing avatar %s: %w", fn, err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func CreateOrUpdateBlob(conf *Config, key string, data []byte, signer string) error {
|
|
p := filepath.Join(conf.Data, blobsPath, signer)
|
|
p = saltyim.FixUnixHome(p)
|
|
|
|
if err := os.MkdirAll(p, 0755); err != nil {
|
|
return fmt.Errorf("error creating blobs paths %s: %w", p, err)
|
|
}
|
|
|
|
fn := filepath.Join(p, key)
|
|
|
|
if err := os.WriteFile(fn, data, os.FileMode(0644)); err != nil {
|
|
return fmt.Errorf("error writing blob %s: %w", fn, err)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func GetBlob(conf *Config, key string, signer string) (*saltyim.Blob, error) {
|
|
p := filepath.Join(conf.Data, blobsPath, signer)
|
|
p = saltyim.FixUnixHome(p)
|
|
|
|
if err := os.MkdirAll(p, 0755); err != nil {
|
|
return nil, fmt.Errorf("error creating blobs paths %s: %w", p, err)
|
|
}
|
|
|
|
fn := filepath.Join(p, key)
|
|
|
|
if !FileExists(fn) {
|
|
return nil, ErrBlobNotFound
|
|
}
|
|
|
|
return saltyim.OpenBlob(fn)
|
|
}
|
|
|
|
func DeleteBlob(conf *Config, key string, signer string) error {
|
|
p := filepath.Join(conf.Data, blobsPath, signer)
|
|
p = saltyim.FixUnixHome(p)
|
|
|
|
if err := os.MkdirAll(p, 0755); err != nil {
|
|
return fmt.Errorf("error creating blobs paths %s: %w", p, err)
|
|
}
|
|
|
|
fn := filepath.Join(p, key)
|
|
|
|
if !FileExists(fn) {
|
|
return ErrBlobNotFound
|
|
}
|
|
|
|
// TODO: Delete the .json properties metadata files too
|
|
|
|
return os.Remove(fn)
|
|
}
|