diff --git a/cmd/api/api.go b/cmd/api/api.go index a7fb5bc..8f1ba20 100644 --- a/cmd/api/api.go +++ b/cmd/api/api.go @@ -81,7 +81,7 @@ func main() { flag.IntVar(&cfg.smtp.port, "smtpport", 1025, "smtp host") flag.StringVar(&cfg.smtp.username, "smtpuser", "user", "smtp user") flag.StringVar(&cfg.smtp.password, "smtppwd", "password", "smtp password") - flag.StringVar(&cfg.secretkey, "secret", "secRetKeY", "secret key") + flag.StringVar(&cfg.secretkey, "secretkey", "b47df3d8380241c1177f13bdd69c6a60", "secret key") flag.StringVar(&cfg.frontend, "frontend", "http://localhost:4000", "frontend address") flag.Parse() diff --git a/cmd/api/handlers-api.go b/cmd/api/handlers-api.go index 627c26e..7063b57 100644 --- a/cmd/api/handlers-api.go +++ b/cmd/api/handlers-api.go @@ -5,6 +5,7 @@ import ( "errors" "fmt" "myapp/internal/cards" + "myapp/internal/cards/encryption" "myapp/internal/models" "myapp/internal/urlsigner" "net/http" @@ -480,7 +481,18 @@ func (app *application) ResetPassword(w http.ResponseWriter, r *http.Request) { return } - user, err := app.DB.GetUserByEmail(payload.Email) + encryptor := encryption.Encryption{ + Key: []byte(app.config.secretkey), + } + + realEmail, err := encryptor.Decrypt(payload.Email) + if err != nil { + app.errorLog.Println(err) + app.badRequest(w, r, err) + return + } + + user, err := app.DB.GetUserByEmail(realEmail) if err != nil { app.errorLog.Println(err) app.badRequest(w, r, err) diff --git a/cmd/web/handlers.go b/cmd/web/handlers.go index 7e8e77c..79c2890 100644 --- a/cmd/web/handlers.go +++ b/cmd/web/handlers.go @@ -3,6 +3,7 @@ package main import ( "fmt" "myapp/internal/cards" + "myapp/internal/cards/encryption" "myapp/internal/models" "myapp/internal/urlsigner" "net/http" @@ -328,6 +329,7 @@ func (app *application) ForgotPassword(w http.ResponseWriter, r *http.Request) { } func (app *application) ShowResetPassword(w http.ResponseWriter, r *http.Request) { + email := r.URL.Query().Get("email") theURL := r.RequestURI testURL := fmt.Sprintf("%s%s", app.config.frontend, theURL) @@ -347,8 +349,18 @@ func (app *application) ShowResetPassword(w http.ResponseWriter, r *http.Request return } + encryptor := encryption.Encryption{ + Key: []byte(app.config.secretkey), + } + + encryptedEmail, err := encryptor.Encrypt(email) + if err != nil { + app.errorLog.Println("Encryption failed", err) + return + } + data := make(map[string]interface{}) - data["email"] = r.URL.Query().Get("email") + data["email"] = encryptedEmail if err := app.renderTemplate(w, r, "reset-password", &templateData{ Data: data, }); err != nil { diff --git a/cmd/web/main.go b/cmd/web/main.go index be68217..38331a1 100644 --- a/cmd/web/main.go +++ b/cmd/web/main.go @@ -85,7 +85,7 @@ func main() { "DSN", ) flag.StringVar(&cfg.api, "api", "http://localhost:4001", "URL to api") - flag.StringVar(&cfg.secretkey, "secret", "secRetKeY", "secret key") + flag.StringVar(&cfg.secretkey, "secretkey", "b47df3d8380241c1177f13bdd69c6a60", "secret key") flag.StringVar(&cfg.frontend, "frontend", "http://localhost:4000", "frontend address") flag.Parse() diff --git a/cmd/web/templates/forgot-password.page.gohtml b/cmd/web/templates/forgot-password.page.gohtml index 5c6a810..d500db3 100644 --- a/cmd/web/templates/forgot-password.page.gohtml +++ b/cmd/web/templates/forgot-password.page.gohtml @@ -34,8 +34,15 @@ Forgot Password {{define "js"}} {{end}} diff --git a/internal/cards/encryption/encryption.go b/internal/cards/encryption/encryption.go new file mode 100644 index 0000000..cd1107a --- /dev/null +++ b/internal/cards/encryption/encryption.go @@ -0,0 +1,54 @@ +package encryption + +import ( + "crypto/aes" + "crypto/cipher" + "crypto/rand" + "encoding/base64" + "io" +) + +type Encryption struct { + Key []byte +} + +func (e *Encryption) Encrypt(text string) (string, error) { + plaintext := []byte(text) + + block, err := aes.NewCipher(e.Key) + if err != nil { + return "", err + } + + cipherText := make([]byte, aes.BlockSize+len(plaintext)) + iv := cipherText[:aes.BlockSize] + if _, err := io.ReadFull(rand.Reader, iv); err != nil { + return "", err + } + + stream := cipher.NewCFBEncrypter(block, iv) + stream.XORKeyStream(cipherText[aes.BlockSize:], plaintext) + + return base64.URLEncoding.EncodeToString(cipherText), nil +} + +func (e *Encryption) Decrypt(cryptoText string) (string, error) { + cipherText, _ := base64.URLEncoding.DecodeString(cryptoText) + + block, err := aes.NewCipher(e.Key) + if err != nil { + return "", err + } + + if len(cipherText) < aes.BlockSize { + return "", err + } + + iv := cipherText[:aes.BlockSize] + cipherText = cipherText[aes.BlockSize:] + + stream := cipher.NewCFBDecrypter(block, iv) + stream.XORKeyStream(cipherText, cipherText) + + return string(cipherText), nil +}