Created
July 18, 2021 14:45
-
-
Save ollybh/7b1b508d717854341b7864d73aa50730 to your computer and use it in GitHub Desktop.
Script for transferring passwords from LastPass to Password Safe
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/sh | |
# Converts a CSV export of a LastPass [https://www.lastpass.com/] vault into a | |
# format that can be imported by Password Safe [https://pwsafe.org]. Uses | |
# csvkit [https://github.com/wireservice/csvkit] to manipulate the CSV data. | |
if [ $# -ne 2 ]; then | |
echo "Usage: $(basename $0) [INFILE] [OUTFILE]" | |
exit 1 | |
fi | |
SRCFILE=$1 | |
DSTFILE=$2 | |
# The LastPass export has these fields: | |
# 1: url | |
# 2: username | |
# 3: password | |
# 4: totp | |
# 5: extra | |
# 6: name | |
# 7: grouping | |
# 8: fav | |
# | |
# The fields that the Password Safe plain text exporter/importer recognises are: | |
# 1: Group/Title | |
# 2: Username | |
# 3: Password | |
# 4: URL | |
# 5: AutoType | |
# 6: Created Time | |
# 7: Password Modified Time | |
# 8: Last Access Time | |
# 9: Password Expiry Date | |
# 10: Password Expiry Interval | |
# 11: Record Modified Time | |
# 12: Password Policy | |
# 13: Password Policy Name | |
# 14: History | |
# 15: Run Command | |
# 16: DCA | |
# 17: Shift+DCA | |
# 18: e-mail | |
# 19: Protected | |
# 20: Symbols | |
# 21: Notes | |
# | |
# This gives a LastPass to Password Safe mapping of: | |
# grouping + name → Group/Title | |
# username → Username | |
# password → Password | |
# url → URL | |
# extra → Notes | |
# | |
# In LastPass the group hierarchy uses backslash as a separator. Password Safe | |
# uses a period, which is also the separator between the group and title fields. | |
# LastPass uses line breaks for multiline notes, Password Safe uses double | |
# right quotation marks (»), which is also used to replace any periods in the | |
# group and title names. | |
# | |
# A 'Created Time' field is added to the output file with a value of 'now', | |
# which tells the importer to use the current date and time. An undocumented | |
# feature of the Password Safe plain text importer is that the Notes field must | |
# be the last one. If it isn't, everything later in the row is assumed to be | |
# part of the Notes and the importer falls over with errors from missing | |
# fields. | |
# | |
# LastPass secure notes could be handled better. These appear in the LastPass | |
# export with a blank password, a URL of http://sn and the note information | |
# stored as text in the 'extra' field. Password Safe refuses to import anything | |
# with a missing password, so this is set to a period to ensure that the note | |
# gets imported. | |
QUERY=" | |
SELECT REPLACE(REPLACE(COALESCE(grouping, ''), '.', '»'), '\\', '.') | |
|| | |
'.' | |
|| | |
REPLACE(name, '.', '»') AS 'Group/Title', | |
COALESCE(username, '') AS 'Username', | |
COALESCE(password, '.') AS 'Password', | |
COALESCE(url, '') AS 'URL', | |
'now' AS 'Created Time', | |
REPLACE(COALESCE(extra, ''), CHAR(10), '»') AS 'Notes' | |
FROM $(basename ${SRCFILE%.*}) | |
" | |
# Password Safe doesn't like missing Notes fields, they must be shown by an | |
# emptry string. This is done by telling csvformat to quote all non-numeric | |
# values. This causes the values in the header row to also be quoted, which | |
# results in a failed import, so sed is used to strip the quotes on the first | |
# line. | |
csvsql --query "${QUERY}" ${SRCFILE} \ | |
| csvformat --out-tabs --out-quoting 2 \ | |
| sed -e '1s/\"//g' \ | |
> ${DSTFILE} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment