(except for iceshrimp, but who cares) (well, I do. Would not be nice to not be compatible with a not-so-rarely used software)
This commit is contained in:
parent
59dd8d82cf
commit
5e13817563
7 changed files with 167 additions and 93 deletions
|
@ -4,6 +4,7 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
|
"net/http"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.mstar.dev/mstar/goutils/other"
|
"git.mstar.dev/mstar/goutils/other"
|
||||||
|
@ -12,6 +13,7 @@ import (
|
||||||
|
|
||||||
"git.mstar.dev/mstar/linstrom/config"
|
"git.mstar.dev/mstar/linstrom/config"
|
||||||
"git.mstar.dev/mstar/linstrom/storage-new/dbgen"
|
"git.mstar.dev/mstar/linstrom/storage-new/dbgen"
|
||||||
|
"git.mstar.dev/mstar/linstrom/storage-new/models"
|
||||||
webshared "git.mstar.dev/mstar/linstrom/web/shared"
|
webshared "git.mstar.dev/mstar/linstrom/web/shared"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -54,35 +56,35 @@ func ImportRemoteAccount(targetName string) (string, error) {
|
||||||
return t.Relation == "self"
|
return t.Relation == "self"
|
||||||
})
|
})
|
||||||
if len(selfLinks) == 0 {
|
if len(selfLinks) == 0 {
|
||||||
return "", errors.New("No self link")
|
return "", errors.New("no self link")
|
||||||
}
|
}
|
||||||
APLink := selfLinks[0]
|
APLink := selfLinks[0]
|
||||||
req, err := webshared.NewRequest("GET", *APLink.Href, nil)
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
req.Header.Add("Accept", "application/activity+json")
|
|
||||||
|
|
||||||
// Server actor key for signing
|
// Server actor key for signing
|
||||||
linstromActor, err := dbgen.User.Where(dbgen.User.Username.Eq("linstrom")).First()
|
linstromActor, err := dbgen.User.Where(dbgen.User.Username.Eq("linstrom")).First()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
var keyBytes []byte
|
var response *http.Response
|
||||||
if config.GlobalConfig.Experimental.UseEd25519Keys {
|
// if config.GlobalConfig.Experimental.UseEd25519Keys {
|
||||||
keyBytes = linstromActor.PrivateKeyEd
|
// response, err = webshared.RequestSignedCavage(
|
||||||
} else {
|
// "GET",
|
||||||
keyBytes = linstromActor.PrivateKeyRsa
|
// *APLink.Href,
|
||||||
}
|
// nil,
|
||||||
|
// config.GlobalConfig.General.GetFullPublicUrl()+"/api/activitypub/user/"+linstromActor.ID+"#main-key",
|
||||||
// Sign and send
|
// linstromActor.PrivateKeyEd,
|
||||||
err = webshared.SignRequest(req, linstromActor.ID+"#main-key", keyBytes, nil)
|
// true,
|
||||||
// err = webshared.SignRequestWithHttpsig(req, linstromActor.ID+"#main-key", keyBytes, nil)
|
// )
|
||||||
if err != nil {
|
// } else {
|
||||||
return "", err
|
// response, err = webshared.RequestSignedCavage(
|
||||||
}
|
// "GET",
|
||||||
log.Debug().Str("Signature", req.Header.Get("Signature")).Msg("Post sign signature")
|
// *APLink.Href,
|
||||||
response, err := webshared.RequestClient.Do(req)
|
// nil,
|
||||||
|
// config.GlobalConfig.General.GetFullPublicUrl()+"/api/activitypub/user/"+linstromActor.ID+"#main-key",
|
||||||
|
// linstromActor.PrivateKeyRsa,
|
||||||
|
// false,
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
response, err = customReq(*APLink.Href, linstromActor)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
@ -94,7 +96,7 @@ func ImportRemoteAccount(targetName string) (string, error) {
|
||||||
Any("headers", response.Header).
|
Any("headers", response.Header).
|
||||||
Msg("Response information")
|
Msg("Response information")
|
||||||
if response.StatusCode != 200 {
|
if response.StatusCode != 200 {
|
||||||
return "", errors.New("Bad status")
|
return "", errors.New("bad status")
|
||||||
}
|
}
|
||||||
var data InboundUser
|
var data InboundUser
|
||||||
err = json.Unmarshal(body, &data)
|
err = json.Unmarshal(body, &data)
|
||||||
|
@ -104,3 +106,26 @@ func ImportRemoteAccount(targetName string) (string, error) {
|
||||||
log.Info().Any("received-data", data).Msg("Response data")
|
log.Info().Any("received-data", data).Msg("Response data")
|
||||||
return "", nil
|
return "", nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func customReq(target string, linstromActor *models.User) (*http.Response, error) {
|
||||||
|
req, err := webshared.NewRequest("GET", target, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
req.Header.Add("Accept", "application/activity+json")
|
||||||
|
|
||||||
|
var keyBytes []byte
|
||||||
|
if config.GlobalConfig.Experimental.UseEd25519Keys {
|
||||||
|
keyBytes = linstromActor.PrivateKeyEd
|
||||||
|
} else {
|
||||||
|
keyBytes = linstromActor.PrivateKeyRsa
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sign and send
|
||||||
|
err = webshared.SignRequest(req, linstromActor.ID+"#main-key", keyBytes, nil)
|
||||||
|
// err = webshared.SignRequestWithHttpsig(req, linstromActor.ID+"#main-key", keyBytes, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return webshared.RequestClient.Do(req)
|
||||||
|
}
|
||||||
|
|
1
go.mod
1
go.mod
|
@ -47,6 +47,7 @@ require (
|
||||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||||
github.com/ebitengine/purego v0.7.1 // indirect
|
github.com/ebitengine/purego v0.7.1 // indirect
|
||||||
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
|
github.com/fxamacker/cbor/v2 v2.7.0 // indirect
|
||||||
|
github.com/go-fed/httpsig v1.1.0 // indirect
|
||||||
github.com/go-ini/ini v1.67.0 // indirect
|
github.com/go-ini/ini v1.67.0 // indirect
|
||||||
github.com/go-sql-driver/mysql v1.8.1 // indirect
|
github.com/go-sql-driver/mysql v1.8.1 // indirect
|
||||||
github.com/go-webauthn/x v0.1.14 // indirect
|
github.com/go-webauthn/x v0.1.14 // indirect
|
||||||
|
|
2
go.sum
2
go.sum
|
@ -103,6 +103,8 @@ github.com/gen2brain/avif v0.3.2 h1:XUR0CBl5n4ISFJE8/pc1RMEKt5KUVoW8InctN+M7+DQ=
|
||||||
github.com/gen2brain/avif v0.3.2/go.mod h1:tdL2sV6oOJXBZZvT5iP55VEM1X2c3/yJmYKMJTl8fXg=
|
github.com/gen2brain/avif v0.3.2/go.mod h1:tdL2sV6oOJXBZZvT5iP55VEM1X2c3/yJmYKMJTl8fXg=
|
||||||
github.com/go-ap/httpsig v0.0.0-20221203064646-3647b4d88fdf h1:Ab5yBsD/dXhFmgf2hX7T/YYr+VK0Df7SrIxyNztT9YE=
|
github.com/go-ap/httpsig v0.0.0-20221203064646-3647b4d88fdf h1:Ab5yBsD/dXhFmgf2hX7T/YYr+VK0Df7SrIxyNztT9YE=
|
||||||
github.com/go-ap/httpsig v0.0.0-20221203064646-3647b4d88fdf/go.mod h1:+4SUDMvPlRMUPW5PlMTbxj3U5a4fWasBIbakUw7Kp6c=
|
github.com/go-ap/httpsig v0.0.0-20221203064646-3647b4d88fdf/go.mod h1:+4SUDMvPlRMUPW5PlMTbxj3U5a4fWasBIbakUw7Kp6c=
|
||||||
|
github.com/go-fed/httpsig v1.1.0 h1:9M+hb0jkEICD8/cAiNqEB66R87tTINszBRTjwjQzWcI=
|
||||||
|
github.com/go-fed/httpsig v1.1.0/go.mod h1:RCMrTZvN1bJYtofsG4rd5NaO5obxQ5xBkdiS7xsT7bM=
|
||||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
[general]
|
[general]
|
||||||
protocol = "https"
|
protocol = "https"
|
||||||
domain = "serveo.net"
|
domain = "serveo.net"
|
||||||
subdomain = "29a62d7d1dd05bd000b8f9138244df2c"
|
subdomain = "cc45720a387f04ba6a748a2627327a77"
|
||||||
private_port = 8080
|
private_port = 8080
|
||||||
public_port = 443
|
public_port = 443
|
||||||
|
|
||||||
|
|
|
@ -1,18 +1,12 @@
|
||||||
package webshared
|
package webshared
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/ed25519"
|
|
||||||
"crypto/sha256"
|
|
||||||
"crypto/x509"
|
|
||||||
"encoding/base64"
|
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.mstar.dev/mstar/goutils/maputils"
|
"git.mstar.dev/mstar/goutils/maputils"
|
||||||
"github.com/go-ap/httpsig"
|
|
||||||
"github.com/rs/zerolog/log"
|
|
||||||
|
|
||||||
"git.mstar.dev/mstar/linstrom/config"
|
"git.mstar.dev/mstar/linstrom/config"
|
||||||
)
|
)
|
||||||
|
@ -21,8 +15,6 @@ import (
|
||||||
|
|
||||||
var RequestClient = http.Client{}
|
var RequestClient = http.Client{}
|
||||||
|
|
||||||
const xRandomHeader = "X-Auth-Random"
|
|
||||||
|
|
||||||
// Sign a given outbound request for authorized fetch.
|
// Sign a given outbound request for authorized fetch.
|
||||||
// At the end, the Signature header will have the signature needed,
|
// At the end, the Signature header will have the signature needed,
|
||||||
// nothing else is modified.
|
// nothing else is modified.
|
||||||
|
@ -31,19 +23,9 @@ const xRandomHeader = "X-Auth-Random"
|
||||||
func SignRequest(r *http.Request, keyId string, privateKeyBytes, postBody []byte) error {
|
func SignRequest(r *http.Request, keyId string, privateKeyBytes, postBody []byte) error {
|
||||||
method := r.Method
|
method := r.Method
|
||||||
headers := r.Header
|
headers := r.Header
|
||||||
var nowString string
|
|
||||||
if dateString := headers.Get("Date"); dateString != "" {
|
if dateString := headers.Get("Date"); dateString != "" {
|
||||||
nowString = dateString
|
|
||||||
} else {
|
} else {
|
||||||
nowString = time.Now().Format("Mon, 02 Jan 2006 15:04:05 MST")
|
headers.Set("Date", time.Now().UTC().Format(http.TimeFormat))
|
||||||
headers.Set("Date", nowString)
|
|
||||||
}
|
|
||||||
var host string
|
|
||||||
if hostString := headers.Get("Host"); hostString != "" {
|
|
||||||
host = hostString
|
|
||||||
} else {
|
|
||||||
host = config.GlobalConfig.General.GetFullDomain()
|
|
||||||
headers.Set("Host", host)
|
|
||||||
}
|
}
|
||||||
applyBodyHash(headers, postBody)
|
applyBodyHash(headers, postBody)
|
||||||
mappedHeaders := maputils.MapNewKeys(headers, func(k string, v []string) (string, string) {
|
mappedHeaders := maputils.MapNewKeys(headers, func(k string, v []string) (string, string) {
|
||||||
|
@ -61,14 +43,14 @@ func SignRequest(r *http.Request, keyId string, privateKeyBytes, postBody []byte
|
||||||
var signedString string
|
var signedString string
|
||||||
var usedHeaders []string
|
var usedHeaders []string
|
||||||
if config.GlobalConfig.Experimental.UseEd25519Keys {
|
if config.GlobalConfig.Experimental.UseEd25519Keys {
|
||||||
tmp, tmp2, err := CreateSignatureED(method, r.URL.Path, mappedHeaders, privateKeyBytes)
|
tmp, tmp2, err := CreateSignatureED(method, r.URL, mappedHeaders, privateKeyBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
signedString = tmp
|
signedString = tmp
|
||||||
usedHeaders = tmp2
|
usedHeaders = tmp2
|
||||||
} else {
|
} else {
|
||||||
tmp, tmp2, err := CreateSignatureRSA(method, r.URL.Path, mappedHeaders, privateKeyBytes)
|
tmp, tmp2, err := CreateSignatureRSA(method, r.URL, mappedHeaders, privateKeyBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -80,47 +62,10 @@ func SignRequest(r *http.Request, keyId string, privateKeyBytes, postBody []byte
|
||||||
signedString,
|
signedString,
|
||||||
usedHeaders...,
|
usedHeaders...,
|
||||||
)
|
)
|
||||||
log.Debug().Str("signature-header", signature).Send()
|
|
||||||
headers.Set("Signature", signature)
|
headers.Set("Signature", signature)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func SignRequestWithHttpsig(
|
|
||||||
r *http.Request,
|
|
||||||
keyId string,
|
|
||||||
privateKeyBytes, postBody []byte,
|
|
||||||
) error {
|
|
||||||
keyId = config.GlobalConfig.General.GetFullPublicUrl() + "/api/activitypub/user/" + keyId
|
|
||||||
if config.GlobalConfig.Experimental.UseEd25519Keys {
|
|
||||||
key := ed25519.PrivateKey(privateKeyBytes)
|
|
||||||
signer := httpsig.NewEd25519Signer(keyId, key, nil)
|
|
||||||
if err := signer.Sign(r); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
key, err := x509.ParsePKCS1PrivateKey(privateKeyBytes)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
signer := httpsig.NewRSASHA256Signer(keyId, key, nil)
|
|
||||||
if err = signer.Sign(r); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
// r.Header.Add("Signature", strings.TrimPrefix(r.Header.Get("Authorization"), "Signature "))
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func applyBodyHash(headers http.Header, body []byte) error {
|
|
||||||
if body == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
hash := sha256.Sum256(body)
|
|
||||||
based := base64.StdEncoding.EncodeToString(hash[:])
|
|
||||||
headers.Set("Digest", "SHA-256="+based)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewRequest(method string, url string, body io.Reader) (*http.Request, error) {
|
func NewRequest(method string, url string, body io.Reader) (*http.Request, error) {
|
||||||
req, err := http.NewRequest(method, url, body)
|
req, err := http.NewRequest(method, url, body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -130,7 +75,6 @@ func NewRequest(method string, url string, body io.Reader) (*http.Request, error
|
||||||
"User-Agent",
|
"User-Agent",
|
||||||
"Linstrom v0.0.0-pre-alpha ("+config.GlobalConfig.General.GetFullDomain()+")",
|
"Linstrom v0.0.0-pre-alpha ("+config.GlobalConfig.General.GetFullDomain()+")",
|
||||||
)
|
)
|
||||||
req.Header.Add("Date", time.Now().Format(time.RFC1123))
|
req.Header.Add("Date", time.Now().UTC().Format(http.TimeFormat))
|
||||||
req.Header.Add("Host", config.GlobalConfig.General.GetFullDomain())
|
|
||||||
return req, nil
|
return req, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,22 @@
|
||||||
package webshared
|
package webshared
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"crypto"
|
||||||
|
"crypto/ed25519"
|
||||||
|
"crypto/sha256"
|
||||||
"crypto/x509"
|
"crypto/x509"
|
||||||
"io"
|
"encoding/base64"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"slices"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/go-fed/httpsig"
|
||||||
|
"github.com/rs/zerolog/log"
|
||||||
"github.com/yaronf/httpsign"
|
"github.com/yaronf/httpsign"
|
||||||
|
|
||||||
"git.mstar.dev/mstar/linstrom/config"
|
"git.mstar.dev/mstar/linstrom/config"
|
||||||
|
"git.mstar.dev/mstar/linstrom/shared"
|
||||||
)
|
)
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -22,16 +31,19 @@ Links for home:
|
||||||
- https://datatracker.ietf.org/doc/html/rfc9421
|
- https://datatracker.ietf.org/doc/html/rfc9421
|
||||||
*/
|
*/
|
||||||
|
|
||||||
func RequestSigned(
|
// Perform a request, signing it as specified in RFC 9421
|
||||||
|
func RequestSignedRFC9421(
|
||||||
method, target string,
|
method, target string,
|
||||||
body io.Reader,
|
body []byte,
|
||||||
keyId string,
|
keyId string,
|
||||||
privateKeyBytes []byte,
|
privateKeyBytes []byte,
|
||||||
|
useEd bool,
|
||||||
) (*http.Response, error) {
|
) (*http.Response, error) {
|
||||||
req, err := http.NewRequest(method, target, body)
|
req, err := http.NewRequest(method, target, bytes.NewBuffer(slices.Clone(body)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
applyDefaultHeaders(req)
|
||||||
var signer *httpsign.Signer
|
var signer *httpsign.Signer
|
||||||
signerFields := httpsign.Headers("@request-target", "content-digest")
|
signerFields := httpsign.Headers("@request-target", "content-digest")
|
||||||
if config.GlobalConfig.Experimental.UseEd25519Keys {
|
if config.GlobalConfig.Experimental.UseEd25519Keys {
|
||||||
|
@ -40,12 +52,18 @@ func RequestSigned(
|
||||||
httpsign.NewSignConfig(),
|
httpsign.NewSignConfig(),
|
||||||
signerFields,
|
signerFields,
|
||||||
)
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
key, err := x509.ParsePKCS1PrivateKey(privateKeyBytes)
|
key, err := x509.ParsePKCS1PrivateKey(privateKeyBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
signer, err = httpsign.NewRSASigner(*key, httpsign.NewSignConfig(), signerFields)
|
signer, err = httpsign.NewRSASigner(*key, httpsign.NewSignConfig(), signerFields)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
client := httpsign.NewClient(
|
client := httpsign.NewClient(
|
||||||
RequestClient,
|
RequestClient,
|
||||||
|
@ -54,3 +72,80 @@ func RequestSigned(
|
||||||
res, err := client.Do(req)
|
res, err := client.Do(req)
|
||||||
return res, err
|
return res, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Perform a request, signing it as specified in the cavage proposal
|
||||||
|
// (https://swicg.github.io/activitypub-http-signature/#how-to-sign-a-request)
|
||||||
|
func RequestSignedCavage(
|
||||||
|
method, target string,
|
||||||
|
body []byte,
|
||||||
|
keyId string,
|
||||||
|
privateKeyBytes []byte,
|
||||||
|
useEd bool,
|
||||||
|
) (*http.Response, error) {
|
||||||
|
req, err := http.NewRequest(method, target, bytes.NewBuffer(slices.Clone(body)))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
applyDefaultHeaders(req)
|
||||||
|
var prefs []httpsig.Algorithm
|
||||||
|
var key crypto.PrivateKey
|
||||||
|
if useEd {
|
||||||
|
log.Debug().Msg("Using ed25519 cavage")
|
||||||
|
prefs = append(prefs, httpsig.ED25519)
|
||||||
|
key = ed25519.PrivateKey(privateKeyBytes)
|
||||||
|
} else {
|
||||||
|
log.Debug().Msg("Using RSA cavage")
|
||||||
|
// prefs = append(prefs, httpsig.RSA_SHA512, httpsig.RSA_SHA256)
|
||||||
|
prefs = append(prefs, httpsig.RSA_SHA256)
|
||||||
|
tempKey, err := x509.ParsePKCS1PrivateKey(privateKeyBytes)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
key = tempKey
|
||||||
|
}
|
||||||
|
digestAlgorithm := httpsig.DigestSha256
|
||||||
|
headersToSign := []string{httpsig.RequestTarget, "date", "host", "user-agent"}
|
||||||
|
if len(body) > 0 {
|
||||||
|
headersToSign = append(headersToSign, "digest")
|
||||||
|
log.Debug().Msg("Non-empty body, adding digest")
|
||||||
|
} else {
|
||||||
|
// Just to ensure the signer doesn't fuck up
|
||||||
|
body = nil
|
||||||
|
}
|
||||||
|
signer, chosenAlgorithm, err := httpsig.NewSigner(
|
||||||
|
prefs,
|
||||||
|
digestAlgorithm,
|
||||||
|
headersToSign,
|
||||||
|
httpsig.Signature,
|
||||||
|
int64(time.Hour),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
log.Debug().Any("algorithm", chosenAlgorithm).Msg("Signer chose algorithm")
|
||||||
|
if err = signer.SignRequest(key, keyId, req, body); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
log.Debug().Any("headers", req.Header).Msg("Request post signing")
|
||||||
|
return RequestClient.Do(req)
|
||||||
|
}
|
||||||
|
|
||||||
|
func applyDefaultHeaders(r *http.Request) {
|
||||||
|
r.Header.Add(
|
||||||
|
"User-Agent",
|
||||||
|
"Linstrom "+shared.Version+" ("+config.GlobalConfig.General.GetFullDomain()+")",
|
||||||
|
)
|
||||||
|
r.Header.Add("Date", time.Now().UTC().Format(http.TimeFormat))
|
||||||
|
r.Header.Add("Host", config.GlobalConfig.General.GetFullDomain())
|
||||||
|
r.Header.Add("Accept", "application/activity+json")
|
||||||
|
}
|
||||||
|
|
||||||
|
func applyBodyHash(headers http.Header, body []byte) error {
|
||||||
|
if len(body) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
hash := sha256.Sum256(body)
|
||||||
|
based := base64.StdEncoding.EncodeToString(hash[:])
|
||||||
|
headers.Set("Digest", "SHA-256="+based)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package webshared
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
|
@ -15,7 +16,7 @@ import (
|
||||||
// result
|
// result
|
||||||
func CreateSignatureRSA(
|
func CreateSignatureRSA(
|
||||||
method string,
|
method string,
|
||||||
target string,
|
target *url.URL,
|
||||||
headers map[string]string,
|
headers map[string]string,
|
||||||
privateKeyBytes []byte,
|
privateKeyBytes []byte,
|
||||||
) (string, []string, error) {
|
) (string, []string, error) {
|
||||||
|
@ -40,7 +41,7 @@ func CreateSignatureRSA(
|
||||||
// encoded result
|
// encoded result
|
||||||
func CreateSignatureED(
|
func CreateSignatureED(
|
||||||
method string,
|
method string,
|
||||||
target string,
|
target *url.URL,
|
||||||
headers map[string]string,
|
headers map[string]string,
|
||||||
privateKeyBytes []byte,
|
privateKeyBytes []byte,
|
||||||
) (string, []string, error) {
|
) (string, []string, error) {
|
||||||
|
@ -52,14 +53,20 @@ func CreateSignatureED(
|
||||||
return base64.StdEncoding.EncodeToString(signed), usedHeaders, nil
|
return base64.StdEncoding.EncodeToString(signed), usedHeaders, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func genPreSignatureString(method, target string, headers map[string]string) (string, []string) {
|
func genPreSignatureString(
|
||||||
|
method string,
|
||||||
|
target *url.URL,
|
||||||
|
headers map[string]string,
|
||||||
|
) (string, []string) {
|
||||||
dataBuilder := strings.Builder{}
|
dataBuilder := strings.Builder{}
|
||||||
dataBuilder.WriteString("(request-target): ")
|
dataBuilder.WriteString("(request-target): ")
|
||||||
dataBuilder.WriteString(strings.ToLower(method) + " ")
|
dataBuilder.WriteString(strings.ToLower(method) + " ")
|
||||||
dataBuilder.WriteString(target + "\n")
|
dataBuilder.WriteString(target.Path + "\n")
|
||||||
|
dataBuilder.WriteString("host: ")
|
||||||
|
dataBuilder.WriteString(target.Host + "\n")
|
||||||
// dataBuilder.WriteString("algorithm: rsa-sha256\n")
|
// dataBuilder.WriteString("algorithm: rsa-sha256\n")
|
||||||
// usedHeaders := []string{"(request-target)", "algorithm"}
|
// usedHeaders := []string{"(request-target)", "algorithm"}
|
||||||
usedHeaders := []string{"(request-target)"}
|
usedHeaders := []string{"(request-target)", "host"}
|
||||||
for k, v := range headers {
|
for k, v := range headers {
|
||||||
dataBuilder.WriteString(k + ": " + v + "\n")
|
dataBuilder.WriteString(k + ": " + v + "\n")
|
||||||
usedHeaders = append(usedHeaders, k)
|
usedHeaders = append(usedHeaders, k)
|
||||||
|
|
Loading…
Reference in a new issue