Secure note taker with neovim and MacOS keychain
I am not sure if I told you before but I am a terminal person and a huge neovim/vim fan.
I think it can be placed in most influential softwares besides git etc.
I had some aliases in my .zsh recently which allows me to write quick daily notes. It is super simple, creating/editing a file in my notes folder with nvim. Auto name my note with the date for traceability.
1
2
alias note='nvim ~/Documents/notes/$(date +"%d-%m-%Y").md'
alias notes='nvim ~/Documents/notes'
You may suggest me tools like, evernote, notion or obsidian but, I got never felt comfy using them, I spent my time mostly in the terminal during the day, and, I like to use the bare minimum tool if I can and It provides what I need.
So, that’s the reason I’m still using bare and simple neovim for note-taking.
Since, I am writing about security and cryptographic functions lately. I’ve decided to upgrade my tools in terms of security, using openssl and built-in keychain of MacOS.
I’ve updated note alias with this function in my .zshrc: It uses, openssl, security, mktemp and neovim.
- It generates a rand strong password if not generated already.
- It creates a dedicated keychain-db if not created with 5 minute auto-lock.
- Store the password in keychain.
- And prompt keychain password screen, when user tries to edit with
notecommand in cli. - Uses the password stored in keychain to encrypt and decrypt the note
- Creates a tmp markdown file to edit the note in nvim
- Encrypts the note again and locks the keychain after closing nvim and removes tmp file.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
NOTES_DIR="$HOME/.secure-notes"
note() {
mkdir -p "$NOTES_DIR"
local file="$NOTES_DIR/note-$(date +"%d-%m-%Y").md"
local tmp="$(mktemp -t note).md"
local SERVICE="notes-key"
local KC="$HOME/Library/Keychains/notes.keychain-db"
local ACCOUNT="$USER"
# Create dedicated keychain if missing
if [ ! -f "$KC" ]; then
echo "Creating dedicated notes keychain..."
security create-keychain -p "" notes.keychain-db
security set-keychain-settings -lut 300 notes.keychain-db
security list-keychains -d user -s notes.keychain-db login.keychain-db
echo "Keychain created (auto-lock 5 minutes)."
fi
# Try retrieving existing password
local PASS
PASS=$(security find-generic-password \
-a "$ACCOUNT" \
-s "$SERVICE" \
-w \
"$KC" 2>/dev/null)
# If password does not exist, generate and store
if [ -z "$PASS" ]; then
echo "No password found. Generating strong password..."
PASS=$(openssl rand -base64 48)
security add-generic-password \
-a "$ACCOUNT" \
-s "$SERVICE" \
-w "$PASS" \
-U \
"$KC"
echo "Password stored in dedicated keychain."
fi
if [ -f "$file" ]; then
openssl enc -d -aes-256-cbc -pbkdf2 \
-in "$file" \
-out "$tmp" \
-pass stdin <<<"$pass" 2>/dev/null || {
echo "Decryption failed"
rm -f "$tmp"
unset pass
return 1
}
fi
nvim "$tmp"
openssl enc -aes-256-cbc -pbkdf2 \
-in "$tmp" \
-out "$file" \
-pass stdin <<<"$pass"
rm -f "$tmp"
unset pass
security lock-keychain $KC
}
And here is the updated version of, notes command to select and edit existed notes and to create new one with a different name:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# make sure to brew 'gum' before this
notes() {
mkdir -p "$NOTES_DIR"
local selection
selection=$(
{
for f in "$NOTES_DIR"/*.md; do
[ -e "$f" ] && basename "$f" .md
done
echo "[Create new note]"
} | gum filter
) || return 1
if [ "$selection" = "[Create new note]" ]; then
local name
name=$(gum input --placeholder "Note name (without extension)") || return 1
[ -z "$name" ] && return 1
note "$NOTES_DIR/$name-$(date +"%d-%m-%Y")"
else
[ -z "$selection" ] && return 1
note "$NOTES_DIR/$selection"
fi
}
And, it is what it is, a simple yet secure note-taking system which utilizes neovim.
Until next time, Berk