package webshared import ( "encoding/base64" "strings" "github.com/rs/zerolog/log" "git.mstar.dev/mstar/linstrom/config" "git.mstar.dev/mstar/linstrom/shared" ) // Generate the signed string of the headers, method and target // and sign it using the given RSA key. Returns the base64 encoded // result func CreateSignatureRSA( method string, target string, headers map[string]string, privateKeyBytes []byte, ) (string, []string, error) { message, usedHeaders := genPreSignatureString(method, target, headers) signed, err := shared.Sign(message, privateKeyBytes, true) return base64.StdEncoding.EncodeToString(signed), usedHeaders, err } // Generate the signed string of the headers, method and target // and sign it using the given ED25519 key. Returns the base64 // encoded result func CreateSignatureED( method string, target string, headers map[string]string, privateKeyBytes []byte, ) (string, []string, error) { message, usedHeaders := genPreSignatureString(method, target, headers) signed, err := shared.Sign(message, privateKeyBytes, false) if err != nil { return "", nil, err } return base64.StdEncoding.EncodeToString(signed), usedHeaders, nil } func genPreSignatureString(method, target string, headers map[string]string) (string, []string) { dataBuilder := strings.Builder{} dataBuilder.WriteString("(request-target): ") dataBuilder.WriteString(strings.ToLower(method) + " ") dataBuilder.WriteString(target + "\n") dataBuilder.WriteString("algorithm: rsa-sha256\n") usedHeaders := []string{"(request-target)", "algorithm"} for k, v := range headers { dataBuilder.WriteString(k + ": " + v + "\n") usedHeaders = append(usedHeaders, k) } tmp := dataBuilder.String() log.Debug().Str("Raw signature string", tmp).Send() return tmp, usedHeaders } // Generate the content of the "Signature" header based on // The user who's key was used, the hashed and base64 encoded // signed string, as returned by CreateSignatureED/RSA func CreateSignatureHeaderContent(userId string, hash string, headerNames ...string) string { builder := strings.Builder{} builder.WriteString("keyId=\"") builder.WriteString(config.GlobalConfig.General.GetFullPublicUrl()) builder.WriteString("/api/activitypub/user/") builder.WriteString(userId) builder.WriteString("\",headers=\"") for i, header := range headerNames { builder.WriteString(header) if i+1 < len(headerNames) { builder.WriteRune(' ') } } builder.WriteString("\",algorithm=\"rsa-sha256\",signature=\"") builder.WriteString(hash) builder.WriteRune('"') return builder.String() }