Sign responses as well

This commit is contained in:
Ian Gulliver
2023-06-03 21:12:48 -07:00
parent 4da068ed5c
commit 8c8133ff52
2 changed files with 31 additions and 7 deletions

View File

@@ -10,6 +10,7 @@ import (
"time" "time"
"github.com/dchest/uniuri" "github.com/dchest/uniuri"
"github.com/samber/lo"
) )
// TODO: Ensure promotion takes longer than demotion // TODO: Ensure promotion takes longer than demotion
@@ -141,12 +142,12 @@ func (c *Candidate) ServeHTTP(w http.ResponseWriter, r *http.Request) {
return return
} }
js = lo.Must(json.Marshal(c.resp))
w.Header().Set("Content-Type", "application/json") w.Header().Set("Content-Type", "application/json")
// TODO: Sign responses w.Header().Set("Signature", mac(js, c.signingKey))
enc := json.NewEncoder(w) _, err = w.Write(js)
err = enc.Encode(c.resp)
if err != nil { if err != nil {
http.Error( http.Error(
w, w,

View File

@@ -1,6 +1,7 @@
package elect package elect
import ( import (
"crypto/hmac"
"encoding/json" "encoding/json"
"log" "log"
"time" "time"
@@ -109,13 +110,12 @@ func (v *Voter) sendVote() {
} }
js := lo.Must(json.Marshal(v.vote)) js := lo.Must(json.Marshal(v.vote))
vr := &voteResponse{}
resp, err := v.client.R(). resp, err := v.client.R().
SetHeader("Signature", mac(js, v.signingKey)). SetHeader("Signature", mac(js, v.signingKey)).
SetHeader("Content-Type", "application/json"). SetHeader("Content-Type", "application/json").
SetHeader("Accept", "application/json").
SetBody(js). SetBody(js).
SetResult(vr).
Post("") Post("")
if err != nil { if err != nil {
log.Printf("vote response: %s", err) log.Printf("vote response: %s", err)
@@ -126,13 +126,32 @@ func (v *Voter) sendVote() {
} }
if resp.IsError() { if resp.IsError() {
log.Printf("vote response: [%d] %s\n%s", resp.StatusCode(), resp.Status(), resp.String()) v.log("response: [%d] %s\n%s", resp.StatusCode(), resp.Status(), resp.String())
v.vote.NumPollsSinceChange = 0 v.vote.NumPollsSinceChange = 0
return return
} }
sig := resp.Header().Get("Signature")
if sig == "" {
v.log("missing Signature response header")
return
}
if !hmac.Equal([]byte(sig), []byte(mac(resp.Body(), v.signingKey))) {
v.log("invalid Signature response header")
return
}
vr := &voteResponse{}
err = json.Unmarshal(resp.Body(), vr)
if err != nil {
v.log("invalid response: %s", resp.String())
return
}
if vr.CandidateID == v.vote.LastSeenCandidateID { if vr.CandidateID == v.vote.LastSeenCandidateID {
v.vote.NumPollsSinceChange++ v.vote.NumPollsSinceChange++
} else { } else {
@@ -140,3 +159,7 @@ func (v *Voter) sendVote() {
v.vote.NumPollsSinceChange = 0 v.vote.NumPollsSinceChange = 0
} }
} }
func (v *Voter) log(format string, args ...any) {
log.Printf("[voter] "+format, args...)
}