Created
March 10, 2023 08:34
-
-
Save mikkorantalainen/0be0a4682369772694f8acd755481b0d to your computer and use it in GitHub Desktop.
Bash script to create full Bitwarden vault backup on Ubuntu host, backup file will be saved as AES-256 encrypted ZIP file
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# | |
# Backup Bitwarden vault to AES-256 encrypted ZIP file | |
# Copyright 2023 Mikko Rantalainen <[email protected]> | |
# License: MIT | |
# | |
set -o errexit | |
DATE="$(date +%Y-%m-%d)" | |
ZIPFILENAME="$(pwd)/bitwarden-backup-$DATE.zip" | |
echo | |
echo "Backup Bitwarden vault to AES-256 encrypted ZIP file:" | |
echo | |
echo "Using following binaries to create the Bitwarden backup:" | |
which expect # apt install expect | |
which 7za # apt install p7zip-full | |
which bw # snap install bw | |
which cat # apt install coreutils | |
echo "If you don't trust these to handle your password, use Ctrl+C to abort." | |
echo | |
test -e "$ZIPFILENAME" && printf "Notice: %s will be overwritten!\n\n" "$ZIPFILENAME" || true | |
cd "/var/run/user/$UID" | |
printf "Changing to directory %s to create the sensitive files...\n" "$(pwd)" | |
FSTYPE="$(findmnt --target . -no FSTYPE)" | |
# verify that we're using storage in RAM only | |
test "$FSTYPE" = "tmpfs" || { echo "Error: expected filesystem to be tmpfs, got '$FSTYPE' instead, aborting." 2>&1; exit 1; } | |
mkdir "bitwarden-backup.$$" | |
chmod 700 "bitwarden-backup.$$" | |
cd "bitwarden-backup.$$" | |
echo | |
read -e -i "$EMAIL" -p "Enter Bitwarden login (email) > " EMAIL | |
read -p "Enter Bitwarden password for login $EMAIL > " -s BITWARDENPW | |
echo | |
echo | |
cat > password <<EOF | |
$BITWARDENPW | |
EOF | |
cat > expect.encrypt-backup <<EOF | |
set timeout 5 | |
spawn 7za a -tzip -p -mem=AES256 bitwarden-backup.zip bitwarden-backup.json | |
expect "Enter password (will not be echoed):" | |
send -- "$BITWARDENPW\\r" | |
expect "Verify password (will not be echoed) :" | |
send -- "$BITWARDENPW\\r" | |
expect eof | |
EOF | |
BITWARDENPW="overwrite the existing password in the RAM before running any additional programs" | |
echo "Logging to Bitwarden..." | |
(bw status | grep -q userEmail) || (cat password | bw login "$EMAIL") >> output | |
echo "Unlocking and synchronizing the vault..." | |
cat password | bw unlock >> output | |
bw sync >> output | |
echo "Exporting the vault to JSON..." | |
cat password | bw export --format json --raw > bitwarden-backup.json | |
echo "Logging out from the Bitwarden..." | |
bw logout >> output | |
echo "Encrypting the JSON copy of the vault..." | |
# Compress and encrypt the file with AES-256 encryption. | |
# However, 7za doesn't want to read input from stdin so we have to use | |
# expect script to emulate end user entering the password twice. | |
# The only other alternative is to include the plaintext password | |
# on the command line but that could be captured by any other | |
# process running in the system! | |
#7za a -tzip -p"$BITWARDENPW" -mem=AES256 bitwarden-backup.zip bitwarden-backup.json | |
expect -f expect.encrypt-backup >> output | |
echo | |
echo "Removing all sensitive files..." | |
rm password expect.encrypt-backup bitwarden-backup.json output | |
echo "Moving generated backup file..." | |
mv bitwarden-backup.zip "$ZIPFILENAME" | |
echo "Cleaning up..." | |
cd .. | |
rmdir "bitwarden-backup.$$" | |
printf "\nThe copy of your Bitwarden vault in plaintext JSON format | |
is now in following AES256 encrypted zip file: | |
%s | |
Use your Bitwarden vault password to decrypt the zip file.\n" "$ZIPFILENAME" | |
echo |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment