package main
import (
"crypto/ed25519"
"encoding/base64"
"fmt"
"net/url"
"sort"
"strings"
"time"
)
// buildSortedQueryString sorts query parameters by key.
func buildSortedQueryString(query url.Values) string {
keys := make([]string, 0, len(query))
for k := range query {
keys = append(keys, k)
}
sort.Strings(keys)
pairs := make([]string, 0, len(keys))
for _, k := range keys {
pairs = append(pairs, k+"="+query.Get(k))
}
return strings.Join(pairs, "&")
}
// signRequest signs the request using Ed25519.
// signData = sorted_query_string + "\n" + body + "\n" + timestamp
func signRequest(privateKeyB64 string, queryString string, body []byte) (signature string, timestamp string) {
privateKey, _ := base64.StdEncoding.DecodeString(privateKeyB64)
ts := fmt.Sprintf("%d", time.Now().Unix())
signData := queryString + "\n" + string(body) + "\n" + ts
sig := ed25519.Sign(ed25519.PrivateKey(privateKey), []byte(signData))
return base64.StdEncoding.EncodeToString(sig), ts
}
func verifySignature(publicKeyB64 string, queryString string, body []byte, timestampStr string, signatureB64 string) bool {
publicKey, _ := base64.StdEncoding.DecodeString(publicKeyB64)
signData := queryString + "\n" + string(body) + "\n" + timestampStr
signature, _ := base64.StdEncoding.DecodeString(signatureB64)
return ed25519.Verify(ed25519.PublicKey(publicKey), []byte(signData), signature)
}