aboutsummaryrefslogtreecommitdiff
path: root/delivery/signed.go
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--delivery/signed.go64
1 files changed, 64 insertions, 0 deletions
diff --git a/delivery/signed.go b/delivery/signed.go
new file mode 100644
index 0000000..acf4df5
--- /dev/null
+++ b/delivery/signed.go
@@ -0,0 +1,64 @@
+package delivery
+
+import (
+ "bytes"
+ "encoding/gob"
+ "net/http"
+ "net/url"
+ "sync"
+ "time"
+
+ "git.capotej.com/capotej/communique/config"
+ "git.capotej.com/capotej/communique/models"
+ "github.com/go-fed/httpsig"
+)
+
+type Signed struct {
+ signer httpsig.Signer
+ mu sync.Mutex
+ persister *models.Persister
+}
+
+func NewSigned(persister *models.Persister) (*Signed, error) {
+ signed := &Signed{persister: persister}
+ var err error
+ prefs := []httpsig.Algorithm{}
+ digestAlgorithm := httpsig.DigestSha256
+ headersToSign := []string{httpsig.RequestTarget, "host", "date", "digest"}
+ signed.signer, _, err = httpsig.NewSigner(prefs, digestAlgorithm, headersToSign, httpsig.Signature, 0)
+ if err != nil {
+ return nil, err
+ }
+ return signed, nil
+}
+
+func (s *Signed) SignedRequest(handler config.Handler, payload []byte, inboxUrl, actorKeyUrl *url.URL) (*http.Request, error) {
+ aso := models.NewKeypair(handler)
+ result, err := s.persister.Find(aso)
+ if err != nil {
+ return nil, err
+ }
+ buf := bytes.NewBuffer(result)
+ dec := gob.NewDecoder(buf)
+ var keypair models.Keypair
+ err = dec.Decode(&keypair)
+ if err != nil {
+ return nil, err
+ }
+ privKey := &keypair.PrivateKey
+
+ request, err := http.NewRequest("POST", inboxUrl.String(), bytes.NewBuffer(payload))
+ date := time.Now().UTC().Format(http.TimeFormat)
+ request.Header.Set("Date", date)
+ request.Header.Set("Content-Type", "application/activity+json")
+ request.Header.Set("Host", inboxUrl.Host)
+
+ s.mu.Lock()
+ err = s.signer.SignRequest(privKey, actorKeyUrl.String(), request, payload)
+ s.mu.Unlock()
+
+ if err != nil {
+ return nil, err
+ }
+ return request, nil
+}