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.*)`, WithCrypto(renderer.Template("templates/register.html"), crypto)) rtr.Post(`/(?P.*)`, WithUserStore(WithCrypto(renderer.Template("templates/registered.html"), crypto), udb)) return http.HandlerFunc(rtr.ServeHTTP) }