3 min read
Migrate From Pass to KeepassXC
In 2017 I migrated from KeePass to Pass and now migrated back to KeePassXC. For almost 9 years I was a happy pass user. It still does a very good job and keeping password management simple. But setting up pass on a new device was always a bit difficult.
Whenever I wanted to access my passwords on a new deceive I had to:
- Get ssh key to clone the pass repo
- Import the pgp key to access the pass repo
Moreover, I missed two essential features:
- Browser-Plugin
- Passkey support
And KeePassXC supports both of these cases. In addition I already used KeePassXC:
- To store and load my ssh key
- As password management for my company
Export
There were over 400 entries in my pass store. A manual migration was out of question. I created script that parsed the pass entries and handled the following cases:
- OTP entries
- Fallback to default username
- Escaping strings
- Process additional fields
And here is the script / bash function:
export-keepass-csv() {
if test -z "$1"; then
echo "\$1 is empty." >&2
return 1
fi
OUTPUT_FILE="$1"
PASS_DIR="${PASSWORD_STORE_DIR:-$HOME/.password-store}"
# Validate PASS_DIR exists
if [[ ! -d "$PASS_DIR" ]]; then
echo "Error: Password store directory not found: $PASS_DIR" >&2
return 1
fi
# Header (already properly quoted)
echo '"Group","Title","Username","Password","URL","Notes","TOTP"' > "$OUTPUT_FILE"
# Use process substitution to avoid subshell
while read -r FILE; do
echo "Parse pass file: ${FILE#$PASS_DIR/}"
REL_PATH="${FILE#$PASS_DIR/}"
REL_PATH="${REL_PATH%.gpg}"
GROUP="Root/Pass/$(dirname $REL_PATH)"
FOLDER="$(dirname "$GROUP")"
TITLE="$(basename "$REL_PATH")"
ENTRY="$(pass show "$REL_PATH")"
# Extract password (first line)
PASSWORD="$(printf '%s' "$ENTRY" | head -n1)"
# Initialize fields
USERNAME=""
URL="https://$TITLE"
NOTES=""
TOTP=""
# Parse additional key-value lines (skip first line)
while IFS= read -r LINE; do
case "$LINE" in
username:*) USERNAME="${LINE#username: }" ;;
Username:*) USERNAME="${LINE#Username: }" ;;
notes:*) NOTES="${LINE#notes: }" ;;
Notes:*) NOTES="${LINE#Notes: }" ;;
url:*) URL="${LINE#url: }" ;;
Url:*) URL="${LINE#Url: }" ;;
totp:*) TOTP="${LINE#totp: }" ;;
esac
done <<< "$(printf '%s\n' "$ENTRY" | tail -n +2)"
# If password starts with otpauth://, extract the secret and set as TOTP
if [[ "$PASSWORD" == otpauth://* ]]; then
# Extract secret from otpauth URL using query parameter parsing
SECRET=$(echo "$PASSWORD" | sed -n 's/.*secret=\([^&]*\).*/\1/p' | tr '[:lower:]' '[:upper:]')
if [[ -n "$SECRET" ]]; then
TOTP="$SECRET"
fi
fi
# Use fallback username based on folder
if [[ "$USERNAME" == "" ]]; then
if [[ "$FOLDER" == *"private"* ]]; then
USERNAME="$FALLBACK_USERNAME_private"
elif [[ "$FOLDER" == *"mint-system"* ]]; then
USERNAME="$FALLBACK_USERNAME_mint_system"
elif [[ "$FOLDER" == *"sozialinfo"* ]]; then
USERNAME="$FALLBACK_USERNAME_sozialinfo"
fi
fi
# Function to escape double quotes and wrap in quotes for CSV
PASSWORD_CSV=$(printf '%s' "$PASSWORD" | sed 's/"/""/g; s/.*/"&"/')
USERNAME_CSV=$(printf '%s' "$USERNAME" | sed 's/"/""/g; s/.*/"&"/')
NOTES_CSV=$(printf '%s' "$NOTES" | sed 's/"/""/g; s/.*/"&"/')
TOTP_CSV=$(printf '%s' "$TOTP" | sed 's/"/""/g; s/.*/"&"/')
# URL is usually safe, but still escape if needed
URL_CSV=$(printf '%s' "$URL" | sed 's/"/""/g; s/.*/"&"/')
# Group and Title should also be escaped
GROUP_CSV=$(printf '%s' "$GROUP" | sed 's/"/""/g; s/.*/"&"/')
TITLE_CSV=$(printf '%s' "$TITLE" | sed 's/"/""/g; s/.*/"&"/')
# Write to CSV
printf '%s,%s,%s,%s,%s,%s,%s\n' \
"$GROUP_CSV" \
"$TITLE_CSV" \
"$USERNAME_CSV" \
"$PASSWORD_CSV" \
"$URL_CSV" \
"$NOTES_CSV" \
"$TOTP_CSV" >> "$OUTPUT_FILE"
done < <(find "$PASS_DIR" -name "*.gpg" ! -name ".gpg" -print)
echo "All pass entries exported to $OUTPUT_FILE."
}
Note that this bash function was added to a task script and called with ./task export-keepass-csv in context of the .password-store folder.
I am quite happy with the decision to go back using KeePass. The browser plugin and the passkey support are a great help.
Category: securityTags: 100daystooffload , passkeys , password , keepass
Edit Page / Show Statistic