chrly/internal/http/signer.go

61 lines
1.6 KiB
Go
Raw Normal View History

package http
import (
"encoding/base64"
"fmt"
"io"
"net/http"
"github.com/gorilla/mux"
)
type Signer interface {
Sign(data io.Reader) ([]byte, error)
GetPublicKey(format string) ([]byte, error)
}
type SignerApi struct {
Signer
}
func (s *SignerApi) Handler() *mux.Router {
router := mux.NewRouter().StrictSlash(true)
router.HandleFunc("/", s.signHandler).Methods(http.MethodPost)
router.HandleFunc("/public-key.{format:(?:pem|der)}", s.getPublicKeyHandler).Methods(http.MethodGet)
return router
}
func (s *SignerApi) signHandler(resp http.ResponseWriter, req *http.Request) {
signature, err := s.Signer.Sign(req.Body)
if err != nil {
apiServerError(resp, fmt.Errorf("unable to sign the value: %w", err))
return
}
resp.Header().Set("Content-Type", "application/octet-stream+base64")
buf := make([]byte, base64.StdEncoding.EncodedLen(len(signature)))
base64.StdEncoding.Encode(buf, signature)
_, _ = resp.Write(buf)
}
func (s *SignerApi) getPublicKeyHandler(resp http.ResponseWriter, req *http.Request) {
format := mux.Vars(req)["format"]
publicKey, err := s.Signer.GetPublicKey(format)
if err != nil {
apiServerError(resp, fmt.Errorf("unable to retrieve public key: %w", err))
return
}
if format == "pem" {
resp.Header().Set("Content-Type", "application/x-pem-file")
resp.Header().Set("Content-Disposition", `attachment; filename="yggdrasil_session_pubkey.pem"`)
} else {
resp.Header().Set("Content-Type", "application/octet-stream")
resp.Header().Set("Content-Disposition", `attachment; filename="yggdrasil_session_pubkey.der"`)
}
_, _ = resp.Write(publicKey)
}