felt/register/register.go

92 lines
2.4 KiB
Go
Raw Normal View History

package register
import (
"context"
"crypto/aes"
"crypto/cipher"
"encoding/base64"
"html/template"
"net/http"
"hacklab.nilfm.cc/quartzgun/auth"
"hacklab.nilfm.cc/quartzgun/renderer"
"hacklab.nilfm.cc/quartzgun/router"
)
var bytes = []byte{99, 207, 33, 57, 28, 01, 50, 76, 01}
type SymmetricCrypto interface {
Encode(b []byte) string
Decode(s string) []byte
Encrypt(text string) (string, error)
Decrypt(text string) (string, error)
}
type SymmetricCrypt struct {
Secret string
}
func (self *SymmetricCrypt) Encode(b []byte) string {
return base64.StdEncoding.EncodeToString(b)
}
func (self *SymmetricCrypt) Decode(s string) []byte {
data, err := base64.StdEncoding.DecodeString(s)
if err != nil {
panic(err)
}
return data
}
func (self *SymmetricCrypt) Encrypt(text string) (string, error) {
block, err := aes.NewCipher([]byte(self.Secret))
if err != nil {
return "", err
}
plainText := []byte(text)
cfb := cipher.NewCFBEncrypter(block, bytes)
cipherText := make([]byte, len(plainText))
cfb.XORKeyStream(cipherText, plainText)
return self.Encode(cipherText), nil
}
func (self *SymmetricCrypt) Decrypt(text string) (string, error) {
block, err := aes.NewCipher([]byte(self.Secret))
if err != nil {
return "", err
}
cipherText := self.Decode(text)
cfb := cipher.NewCFBDecrypter(block, bytes)
plainText := make([]byte, len(cipherText))
cfb.XORKeyStream(plainText, cipherText)
return string(plainText), nil
}
func WithCrypto(next http.Handler, crypto SymmetricCrypto) http.Handler {
handlerFunc := func(w http.ResponseWriter, req *http.Request) {
*req = *req.WithContext(context.WithValue(req.Context(), "crypto", crypto))
next.ServeHTTP(w, req)
}
return http.HandlerFunc(handlerFunc)
}
func WithUserStore(next http.Handler, udb auth.UserStore) http.Handler {
handlerFunc := func(w http.ResponseWriter, req *http.Request) {
*req = *req.WithContext(context.WithValue(req.Context(), "udb", udb))
next.ServeHTTP(w, req)
}
return http.HandlerFunc(handlerFunc)
}
func CreateRegistrationInterface(udb auth.UserStore, secret string) http.Handler {
rtr := &router.Router{Fallback: *template.Must(template.ParseFiles("templates/error.html"))}
crypto := &SymmetricCrypt{Secret: secret}
rtr.Get(`/(?P<cipher>.*)`, WithCrypto(renderer.Template("templates/register.html"), crypto))
rtr.Post(`/(?P<cipher>.*)`, WithUserStore(WithCrypto(renderer.Template("templates/registered.html"), crypto), udb))
return http.HandlerFunc(rtr.ServeHTTP)
}