Add client-side note encryption

- WebCrypto keyring (PBKDF2 600k + AES-GCM master key) and per-note/per-image keys
- Encrypt/decrypt commands convert the note and its own images, deleting the originals
- Unlock, setup and change-password dialogs; manual lock; lock on page close
- Encrypted images are decrypted to blob URLs; pasted images are encrypted before upload
- Rewrite image links in the browser when renaming an encrypted note
- Skip local drafts for encrypted notes and confirm before closing with unsaved changes
- Show encrypted notes as locked with an explanation outside secure contexts
This commit is contained in:
eezd committed 2026-10-17 14:51:08 +08:00
1 parent 35d3138c7d
commit 5cf5a45682
20 files changed
+899 -39

No files matched your search

+2 -1
View File
@@ -1,6 +1,6 @@
<script setup lang="ts">
import Icon from './Icon.vue'
import { noteTitle } from './paths'
import { isEncrypted, noteTitle } from './paths'
import { closeTab, ws } from './workspace'
</script>
@@ -17,6 +17,7 @@ import { closeTab, ws } from './workspace'
@click="ws.active = tab.path"
@auxclick.prevent="$event.button === 1 && closeTab(tab.path)"
>
<Icon v-if="isEncrypted(tab.path)" name="lock" :size="12" class="rm-lock-icon" />
<span class="rm-tab-title">{{ noteTitle(tab.path) }}</span>
<button class="rm-tab-close" :class="{ dirty: tab.dirty }" title="关闭" @click.stop="closeTab(tab.path)">
<span class="rm-dirty-dot" />