summaryrefslogtreecommitdiffstats
path: root/roseh.moe.go
diff options
context:
space:
mode:
authorRose Hogenson <rosehogenson@posteo.net>2025-09-23 22:48:50 -0700
committerRose Hogenson <rosehogenson@posteo.net>2025-09-23 22:48:50 -0700
commit95df5d765a3a71a4ff75d598fbba1bceb6fa2e6c (patch)
tree15ed491bc3589a35420acaa9ce52f77d154107cf /roseh.moe.go
parent40ad220fd0e26e3bf3be93c536b25cde1c00490f (diff)
downloadroseh.moe-95df5d765a3a71a4ff75d598fbba1bceb6fa2e6c.tar.zst
Don't reuse cipher.AEAD between threads
I'm not sure if it's safe or not, but better to be cautious
Diffstat (limited to 'roseh.moe.go')
-rw-r--r--roseh.moe.go53
1 files changed, 34 insertions, 19 deletions
diff --git a/roseh.moe.go b/roseh.moe.go
index f24bc58..99d1bed 100644
--- a/roseh.moe.go
+++ b/roseh.moe.go
@@ -40,7 +40,7 @@ var (
privateKey []byte
encryptionKeyMu sync.Mutex
- encryptionKey cipher.AEAD
+ encryptionKey []byte
)
func loadSecrets() error {
@@ -51,7 +51,7 @@ func loadSecrets() error {
for _, line := range bytes.Split(bytes.TrimSuffix(secrets, []byte("\n")), []byte("\n")) {
if pw, ok := bytes.CutPrefix(line, []byte("notepad-password=")); ok {
buf := make([]byte, hex.DecodedLen(len(pw)))
- if _, err := hex.Decode(notepadPassword, pw); err != nil {
+ if _, err := hex.Decode(buf, pw); err != nil {
return err
}
notepadPasswordSalt, notepadPassword = buf[:pwhash.SaltLen], buf[pwhash.SaltLen:]
@@ -215,7 +215,7 @@ type loginTemplateArgs struct {
}
func login(w http.ResponseWriter, r *http.Request) {
- keyBytes, pwHash, err := pwhash.Hash(r.FormValue("password"), notepadPasswordSalt)
+ key, pwHash, err := pwhash.Hash(r.FormValue("password"), notepadPasswordSalt)
if err != nil {
http.Error(w, fmt.Sprintf("Unable to hash password: %s", err), http.StatusInternalServerError)
return
@@ -226,12 +226,6 @@ func login(w http.ResponseWriter, r *http.Request) {
}
return
}
- block, err := aes.NewCipher(keyBytes)
- if err != nil {
- http.Error(w, fmt.Sprintf("Could not create AES key: %s", err), http.StatusInternalServerError)
- return
- }
- key, err := cipher.NewGCMWithRandomNonce(block)
encryptionKeyMu.Lock()
if encryptionKey == nil {
encryptionKey = key
@@ -241,6 +235,26 @@ func login(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, r.FormValue("redirect"), http.StatusSeeOther)
}
+func readNotepad(key []byte) (string, error) {
+ encrypted, err := os.ReadFile(*notepadFile)
+ if err != nil {
+ return "", err
+ }
+ block, err := aes.NewCipher(key)
+ if err != nil {
+ return "", err
+ }
+ aead, err := cipher.NewGCMWithRandomNonce(block)
+ if err != nil {
+ return "", err
+ }
+ decrypted, err := aead.Open(nil, nil, encrypted, nil)
+ if err != nil {
+ return "", err
+ }
+ return string(decrypted), nil
+}
+
var (
//go:embed templates/note.html.template
notepadString string
@@ -269,16 +283,9 @@ func notepad(w http.ResponseWriter, r *http.Request) {
}
return
}
- var currentContent string
- if currentContentBytes, err := os.ReadFile(*notepadFile); err != nil {
+ currentContent, err := readNotepad(key)
+ if err != nil {
currentContent = fmt.Sprintf("Error reading notepad file: %s", err)
- } else {
- decrypted, err := key.Open(nil, nil, currentContentBytes, nil)
- if err != nil {
- currentContent = fmt.Sprintf("Could not decrypt notepad contents: %s", err)
- } else {
- currentContent = string(decrypted)
- }
}
if err := notepadTemplate.Execute(w, notepadTemplateArgs{Content: currentContent, CSRFToken: csrfToken}); err != nil {
log.Printf("Warning: notepad: %s", err)
@@ -298,12 +305,20 @@ func saveNote(w http.ResponseWriter, r *http.Request) error {
if key == nil {
return fmt.Errorf("not logged in")
}
+ block, err := aes.NewCipher(key)
+ if err != nil {
+ return err
+ }
+ aead, err := cipher.NewGCMWithRandomNonce(block)
+ if err != nil {
+ return err
+ }
f, err := os.CreateTemp(filepath.Dir(*notepadFile), "notepad")
if err != nil {
return err
}
defer f.Close()
- if _, err = f.Write(key.Seal(nil, nil, []byte(r.FormValue("content")), nil)); err != nil {
+ if _, err = f.Write(aead.Seal(nil, nil, []byte(r.FormValue("content")), nil)); err != nil {
return err
}
if err := f.Close(); err != nil {