Skip to content

Commit

Permalink
feat: Sign all request
Browse files Browse the repository at this point in the history
  • Loading branch information
yukimochi committed Feb 24, 2024
1 parent 528e801 commit e7fd53b
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 38 deletions.
6 changes: 3 additions & 3 deletions api/decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func decodeActivity(request *http.Request) (*models.Activity, *models.Actor, []b
return nil, nil, nil, err
}
KeyID := verifier.KeyId()
keyOwnerActor, err := models.NewActivityPubActorFromRemoteActor(KeyID, fmt.Sprintf("%s (golang net/http; Activity-Relay %s; %s)", GlobalConfig.ServerServiceName(), version, GlobalConfig.ServerHostname().Host), ActorCache)
keyOwnerActor, err := models.NewActivityPubActorFromRemoteActor(KeyID, RelayActor.ID, fmt.Sprintf("%s (golang net/http; Activity-Relay %s; %s)", GlobalConfig.ServerServiceName(), version, GlobalConfig.ServerHostname().Host), GlobalConfig.ActorKey(), ActorCache)
if err != nil {
return nil, nil, nil, err
}
Expand Down Expand Up @@ -56,7 +56,7 @@ func decodeActivity(request *http.Request) (*models.Activity, *models.Actor, []b
if err != nil {
return nil, nil, nil, err
}
remoteActor, err := models.NewActivityPubActorFromRemoteActor(activity.Actor, fmt.Sprintf("%s (golang net/http; Activity-Relay %s; %s)", GlobalConfig.ServerServiceName(), version, GlobalConfig.ServerHostname().Host), ActorCache)
remoteActor, err := models.NewActivityPubActorFromRemoteActor(activity.Actor, RelayActor.ID, fmt.Sprintf("%s (golang net/http; Activity-Relay %s; %s)", GlobalConfig.ServerServiceName(), version, GlobalConfig.ServerHostname().Host), GlobalConfig.ActorKey(), ActorCache)
if err != nil {
return nil, nil, nil, err
}
Expand All @@ -69,7 +69,7 @@ func fetchOriginalActivityFromURL(url string) (*models.Activity, *models.Actor,
if err != nil {
return nil, nil, err
}
remoteActor, err := models.NewActivityPubActorFromRemoteActor(remoteActivity.Actor, fmt.Sprintf("%s (golang net/http; Activity-Relay %s; %s)", GlobalConfig.ServerServiceName(), version, GlobalConfig.ServerHostname().Host), ActorCache)
remoteActor, err := models.NewActivityPubActorFromRemoteActor(remoteActivity.Actor, RelayActor.ID, fmt.Sprintf("%s (golang net/http; Activity-Relay %s; %s)", GlobalConfig.ServerServiceName(), version, GlobalConfig.ServerHostname().Host), GlobalConfig.ActorKey(), ActorCache)
if err != nil {
return &remoteActivity, nil, err
}
Expand Down
27 changes: 2 additions & 25 deletions deliver/sender.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,42 +7,19 @@ import (
"fmt"
"net/http"
"net/url"
"regexp"
"time"

"github.com/Songmu/go-httpdate"
"github.com/go-fed/httpsig"
"github.com/sirupsen/logrus"
"github.com/yukimochi/Activity-Relay/models"
)

func compatibilityForHTTPSignature11(request *http.Request, algorithm httpsig.Algorithm) {
signature := request.Header.Get("Signature")
targetString := regexp.MustCompile("algorithm=\"hs2019\"")
signature = targetString.ReplaceAllString(signature, string("algorithm=\""+algorithm+"\""))
request.Header.Set("Signature", signature)
}

func appendSignature(request *http.Request, body *[]byte, KeyID string, privateKey *rsa.PrivateKey) error {
request.Header.Set("Host", request.Host)

signer, _, err := httpsig.NewSigner([]httpsig.Algorithm{httpsig.RSA_SHA256}, httpsig.DigestSha256, []string{httpsig.RequestTarget, "Host", "Date", "Digest", "Content-Type"}, httpsig.Signature, 60*60)
if err != nil {
return err
}
err = signer.SignRequest(privateKey, KeyID, request, *body)
if err != nil {
return err
}
compatibilityForHTTPSignature11(request, httpsig.RSA_SHA256) // Compatibility for Misskey <12.111.0
return nil
}

func sendActivity(inboxURL string, KeyID string, body []byte, privateKey *rsa.PrivateKey) error {
req, _ := http.NewRequest("POST", inboxURL, bytes.NewBuffer(body))
req.Header.Set("Content-Type", "application/activity+json")
req.Header.Set("User-Agent", fmt.Sprintf("%s (golang net/http; Activity-Relay %s; %s)", GlobalConfig.ServerServiceName(), version, GlobalConfig.ServerHostname().Host))
req.Header.Set("Date", httpdate.Time2Str(time.Now()))
appendSignature(req, &body, KeyID, privateKey)
models.AppendSignature(req, &body, KeyID, privateKey)
resp, err := HttpClient.Do(req)
if err != nil {
urlErr := err.(*url.Error)
Expand Down
30 changes: 30 additions & 0 deletions models/http_sign.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package models

import (
"crypto/rsa"
"github.com/go-fed/httpsig"
"net/http"
"regexp"
)

func compatibilityForHTTPSignature11(request *http.Request, algorithm httpsig.Algorithm) {
signature := request.Header.Get("Signature")
targetString := regexp.MustCompile("algorithm=\"hs2019\"")
signature = targetString.ReplaceAllString(signature, string("algorithm=\""+algorithm+"\""))
request.Header.Set("Signature", signature)
}

func AppendSignature(request *http.Request, body *[]byte, KeyID string, privateKey *rsa.PrivateKey) error {
request.Header.Set("Host", request.Host)

signer, _, err := httpsig.NewSigner([]httpsig.Algorithm{httpsig.RSA_SHA256}, httpsig.DigestSha256, []string{httpsig.RequestTarget, "Host", "Date", "Digest", "Content-Type"}, httpsig.Signature, 60*60)
if err != nil {
return err
}
err = signer.SignRequest(privateKey, KeyID, request, *body)
if err != nil {
return err
}
compatibilityForHTTPSignature11(request, httpsig.RSA_SHA256) // Compatibility for Misskey <12.111.0
return nil
}
9 changes: 4 additions & 5 deletions deliver/sender_test.go → models/http_sign_test.go
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
package deliver
package models

import (
"bytes"
"crypto/sha256"
"encoding/base64"
"github.com/Songmu/go-httpdate"
"github.com/go-fed/httpsig"
"io"
"net/http"
"os"
"regexp"
"testing"
"time"

"github.com/Songmu/go-httpdate"
"github.com/go-fed/httpsig"
)

func TestAppendSignature(t *testing.T) {
Expand All @@ -21,7 +20,7 @@ func TestAppendSignature(t *testing.T) {
req, _ := http.NewRequest("POST", "https://localhost", bytes.NewBuffer(body))
req.Header.Set("Content-Type", "application/activity+json")
req.Header.Set("Date", httpdate.Time2Str(time.Now()))
appendSignature(req, &body, "https://innocent.yukimochi.io/users/YUKIMOCHI#main-key", GlobalConfig.ActorKey())
AppendSignature(req, &body, "https://innocent.yukimochi.io/users/YUKIMOCHI#main-key", GlobalConfig.ActorKey())

// Activated compatibilityForHTTPSignature11
sign := req.Header.Get("Signature")
Expand Down
8 changes: 6 additions & 2 deletions models/models.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package models

import (
"bytes"
"crypto/rsa"
"encoding/json"
"errors"
"io"
Expand Down Expand Up @@ -85,7 +87,7 @@ func NewActivityPubActorFromRelayConfig(globalConfig *RelayConfig) Actor {
}

// NewActivityPubActorFromRemoteActor : Retrieve Actor from remote instance.
func NewActivityPubActorFromRemoteActor(url string, uaString string, cache *cache.Cache) (Actor, error) {
func NewActivityPubActorFromRemoteActor(url string, KeyID string, uaString string, privateKey *rsa.PrivateKey, cache *cache.Cache) (Actor, error) {
var actor = new(Actor)
var err error
cacheData, found := cache.Get(url)
Expand All @@ -97,9 +99,11 @@ func NewActivityPubActorFromRemoteActor(url string, uaString string, cache *cach
return *actor, nil
}
}
req, _ := http.NewRequest("GET", url, nil)
body := []byte(nil)
req, _ := http.NewRequest("GET", url, bytes.NewBuffer(body))
req.Header.Set("Accept", "application/activity+json")
req.Header.Set("User-Agent", uaString)
AppendSignature(req, &body, KeyID, privateKey)
client := new(http.Client)
resp, err := client.Do(req)
if err != nil {
Expand Down
6 changes: 3 additions & 3 deletions models/models_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"github.com/spf13/viper"
)

var globalConfig *RelayConfig
var GlobalConfig *RelayConfig
var relayState RelayState
var ch chan bool

Expand All @@ -25,13 +25,13 @@ func TestMain(m *testing.M) {
viper.Set("ACTOR_PEM", "../misc/test/testKey.pem")
viper.BindEnv("REDIS_URL")

globalConfig, err = NewRelayConfig()
GlobalConfig, err = NewRelayConfig()
if err != nil {
fmt.Println(err.Error())
os.Exit(1)
}

relayState = NewState(globalConfig.RedisClient(), true)
relayState = NewState(GlobalConfig.RedisClient(), true)
ch = make(chan bool)
relayState.ListenNotify(ch)
relayState.RedisClient.FlushAll(context.TODO()).Result()
Expand Down

0 comments on commit e7fd53b

Please sign in to comment.