Skip to content

Commit

Permalink
Encrypt the history with openssl
Browse files Browse the repository at this point in the history
  • Loading branch information
vitobotta committed Oct 16, 2023
1 parent ebf3958 commit 5abf07c
Show file tree
Hide file tree
Showing 4 changed files with 34 additions and 25 deletions.
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# zsh-history-sync

Syncs your zsh shell history between computers using git, easily. Only requirement is to have a **private** git repository on Github or similar.
Syncs your zsh shell history between computers using git and in encrypted format (using openssl), easily. Only requirement is to have a git repository on Github or similar (recommended private although the history is encrypted).

Notes:
- To eliminate or at least minimise the frequency of conflicts, the history is synced only when the last command was executed at least 15 seconds ago. This way even if you switch from a computer to another quickly, the chance of a sync conflict is greatly reduced compared to a sync at each command.
Expand All @@ -10,27 +10,27 @@ Notes:

## Installation

You need to clone this repo with the scripts somewhere and run the install script. The install script accepts a single argument for the path of the file to keep in sync in your private git repo, that will contain the synchronised history. The install script updates your .zshrc to load the sync functions.
You need to clone this repo with the scripts somewhere and run the install script. The install will ask you for the path of your git repository that you want to use to synchronise the history, as well as a password to encrypt it (the password will be stored in ~/.zsh-history-sync.encryption-key). The install script then updates your .zshrc to load what's required to trigger the synchronisation in background.

```bash
git clone https://github.com/vitobotta/zsh-history-sync.git
cd zsh-history-sync

./install.sh <path of synced file in your private repo>
./install.sh

source ~/.zshrc
```

I recommend you also schedule a sync every minute (just to ensure every command is synced since the automatic sync depends on when the ladt command was executed). It's better to specify an offset on the second computer, so to minimise the risk of sync conflicts. Using crontab, on the first computer:

```
* * * * * /path/of/zsh-history-sync/sync-history.sh /path/of/synced/file
* * * * * /path/of/zsh-history-sync/sync-history.sh /path/of/your/repo
```

On the second computer:

```
* * * * * sleep 30; /path/of/zsh-history-sync/sync-history.sh /path/of/synced/file
* * * * * sleep 30; /path/of/zsh-history-sync/sync-history.sh /path/of/your/repo
```


Expand Down
11 changes: 8 additions & 3 deletions install.sh
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
#!/bin/bash

FILE_TO_SYNC=$1
echo "Please enter the full path to the git repository you want to use for the syncing:"
read GIT_REPO_PATH

echo "Please enter the password to use for encryption:"
read -s ENCRYPTION_PASSWORD

SCRIPT_PATH="$(readlink -f "$0")"
SCRIPT_DIR="$(dirname "$SCRIPT_PATH")"

echo ZSH_HISTORY_SYNC_SCRIPT_PATH="${SCRIPT_DIR}/sync-history.sh" >> ~/.zshrc
echo ZSH_HISTORY_SYNC_FILE_PATH="${FILE_TO_SYNC}" >> ~/.zshrc
echo "export ZSH_HISTORY_SYNC_SCRIPT_PATH=${SCRIPT_DIR}/sync-history.sh" >> ~/.zshrc
echo "export ZSH_HISTORY_SYNC_GIT_REPO_PATH=${GIT_REPO_PATH}" >> ~/.zshrc
echo "${ENCRYPTION_PASSWORD}" > ${HOME}/.zsh-history-sync.encryption-key
echo source "${SCRIPT_DIR}/zsh.include.sh" >> ~/.zshrc
34 changes: 19 additions & 15 deletions sync-history.sh
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
#!/bin/zsh
#!/usr/bin/env zsh

home=$HOME
home="$HOME"
repo_dir="$1"
force_sync="$2"
source_file="${home}/.zsh_history"
sync_file=$1
last_command_timestamp_file="${HOME}/.zsh-last-sync"
force_sync=$2
identifier=$(hostname)
repo_dir=$(dirname $sync_file)
sync_file="${repo_dir}/zsh_history.enc"
last_command_timestamp_file="${HOME}/.zsh-history-sync.last-sync"
encryption_key_file="${HOME}/.zsh-history-sync.encryption-key"
identifier="$(hostname)"

read_file() {
if [ ! -f $1 ]; then
Expand All @@ -22,23 +23,27 @@ read_file() {
done
}

write_file() {
echo -e "$2" > $1
}

current_time=$(date +%s)
last_executed_time=$(cat $last_command_timestamp_file 2>/dev/null || echo 0)

if (( current_time - last_executed_time >= 15 )) || [ "$force_sync" = "-f" ]; then
{
git -C $repo_dir pull > /dev/null 2>&1

if [[ -f $sync_file ]]; then
temp_sync_file=$(mktemp)
openssl enc -aes-256-cbc -md sha256 -d -in "$sync_file" -out "$temp_sync_file" -pass file:"$encryption_key_file" -pbkdf2
new_items=$(read_file "$temp_sync_file")
rm "$temp_sync_file"
else
new_items=""
fi

source_items=$(read_file $source_file)
new_items=$(read_file $sync_file)
items=$(echo -e "$source_items\n$new_items" | sort | uniq)

write_file $source_file "$items"
write_file $sync_file "$items"
echo -e "$items" > $source_file
echo -e "$items" | openssl enc -aes-256-cbc -md sha256 -out "$sync_file" -pass file:"$encryption_key_file" -pbkdf2

fc -R $source_file

Expand All @@ -49,4 +54,3 @@ if (( current_time - last_executed_time >= 15 )) || [ "$force_sync" = "-f" ]; th
git -C $repo_dir push > /dev/null 2>&1
} &
fi

4 changes: 2 additions & 2 deletions zsh.include.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ __reload_history() {
}

__sync_history() {
$ZSH_HISTORY_SYNC_SCRIPT_PATH $ZSH_HISTORY_SYNC_FILE_PATH
$ZSH_HISTORY_SYNC_SCRIPT_PATH $ZSH_HISTORY_SYNC_GIT_REPO_PATH
}

add-zsh-hook preexec __reload_history
Expand All @@ -21,4 +21,4 @@ bindkey '^r' fzf-history-widget
bindkey '^[[A' fzf-history-widget
bindkey '^[OA' fzf-history-widget

alias synchistory="$ZSH_HISTORY_SYNC_SCRIPT_PATH $ZSH_HISTORY_SYNC_FILE_PATH"
alias synchistory="$ZSH_HISTORY_SYNC_SCRIPT_PATH $ZSH_HISTORY_SYNC_GIT_REPO_PATH"

0 comments on commit 5abf07c

Please sign in to comment.