Я пытаюсь подписать HTTP-запрос, используя Go, и у меня есть что-то вроде
const testSpecPublicKeyPEM = `-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDCFENGw33yGihy92pDjZQhl0C3
6rPJj+CvfSC8+q28hxA161QFNUd13wuCTUcq0Qd2qsBe/2hFyc2DCJJg0h1L78+6
Z4UMR7EOcpfdUE9Hf3m/hs+FUR45uBJeDK1HSFHD8bHKD6kv8FPGfJTotc+2xjJw
oYi+1hqp1fIekaxsyQIDAQAB
-----END PUBLIC KEY-----`
const testSpecPrivateKeyPEM = `-----BEGIN RSA PRIVATE KEY-----
MIICXgIBAAKBgQDCFENGw33yGihy92pDjZQhl0C36rPJj+CvfSC8+q28hxA161QF
NUd13wuCTUcq0Qd2qsBe/2hFyc2DCJJg0h1L78+6Z4UMR7EOcpfdUE9Hf3m/hs+F
UR45uBJeDK1HSFHD8bHKD6kv8FPGfJTotc+2xjJwoYi+1hqp1fIekaxsyQIDAQAB
AoGBAJR8ZkCUvx5kzv+utdl7T5MnordT1TvoXXJGXK7ZZ+UuvMNUCdN2QPc4sBiA
QWvLw1cSKt5DsKZ8UETpYPy8pPYnnDEz2dDYiaew9+xEpubyeW2oH4Zx71wqBtOK
kqwrXa/pzdpiucRRjk6vE6YY7EBBs/g7uanVpGibOVAEsqH1AkEA7DkjVH28WDUg
f1nqvfn2Kj6CT7nIcE3jGJsZZ7zlZmBmHFDONMLUrXR/Zm3pR5m0tCmBqa5RK95u
412jt1dPIwJBANJT3v8pnkth48bQo/fKel6uEYyboRtA5/uHuHkZ6FQF7OUkGogc
mSJluOdc5t6hI1VsLn0QZEjQZMEOWr+wKSMCQQCC4kXJEsHAve77oP6HtG/IiEn7
kpyUXRNvFsDE0czpJJBvL/aRFUJxuRK91jhjC68sA7NsKMGg5OXb5I5Jj36xAkEA
gIT7aFOYBFwGgQAQkWNKLvySgKbAZRTeLBacpHMuQdl1DfdntvAyqpAZ0lY0RKmW
G6aFKaqQfOXKCyWoUiVknQJAXrlgySFci/2ueKlIE1QqIiLSZ8V8OlpFLRnb1pzI
7U1yQXnTAEFYM560yJlzUpOb1V4cScGd365tiSMvxLOvTA==
-----END RSA PRIVATE KEY-----`
func signPro(privateKey crypto.PrivateKey, pubKeyId string, r *http.Request, body []byte) error {
prefs := []httpsig.Algorithm{httpsig.RSA_SHA256}
headersToSign := []string{httpsig.RequestTarget, "date", "host", "content-length", "digest"}
signer, _, err := httpsig.NewSigner(prefs, httpsig.DigestSha256, headersToSign, httpsig.Signature)
if err != nil {
return err
}
// If r were a http.ResponseWriter, call SignResponse instead.
return signer.SignRequest(privateKey, pubKeyId, r, body)
}
_data := map[string]interface{} {
"@context": []string{"https://www.w3.org/ns/activitystreams", "https://w3id.org/security/v1"},
"id": "http://localhost:10000/activity/7e88dfd5-51db-4c51-afbe-dfcdd24e8da8",
"type": "Follow",
"actor": "http://localhost:10000/test1",
"object": "http://somefriend.local/test2",
"instrument": map[string]interface{}{
"type": "Service",
"name": "lala lele",
"url": "http://localhost:10000",
},
"to": []string{"http://somefriend.local/test2"},
}
data, _ := json.Marshal(_data)
contentLength := strconv.Itoa(binary.Size(data))
privateKey, err := lib.ParseRsaPrivateKeyFromPemStr(testSpecPrivateKeyPEM)
if err != nil {
log.Error("error getting private key")
log.Error(err)
app.JsonResponse(w, http.StatusInternalServerError, "")
return
}
// we do this machinations for headers now
client := &http.Client{}
req, err := http.NewRequest("POST", "http://somefriend.local/profile/test2/inbox", bytes.NewReader(data))
if err != nil {
log.Error(fmt.Sprintf("error creating request"))
log.Error(err)
app.JsonResponse(w, http.StatusInternalServerError, "")
return
}
req.Header.Set("Content-Type", "application/activity+json")
req.Header.Set("Date", "2020-03-11 21:11:11")
req.Header.Set("Content-Length", contentLength)
req.Header.Set("Host", u.Host)
err = signPro(privateKey, "#main-key", req, data)
if err != nil {
log.Error(fmt.Sprintf("error signing request"))
log.Error(err)
app.JsonResponse(w, http.StatusInternalServerError, "")
return
}
В основном это должно добавить заголовки дайджеста и подписи к запросу, но другой конец возвращает недопустимую подпись при проверке.
У кого-нибудь есть пример, как правильно создать подпись HTTP-запроса с Go и что он подчиняется https://tools.ietf.org/html/draft-cavage-http-signatures-12?