4.0 KiB
title, date, lastmod, draft, tags, categories, contentCopyright, hideHeaderAndFooter
| title | date | lastmod | draft | tags | categories | contentCopyright | hideHeaderAndFooter | |||
|---|---|---|---|---|---|---|---|---|---|---|
| Password Checking Script | 2019-04-13 | 2019-04-13 | true |
|
|
false | false |
Having been inspired by the HIBP1 password checker, I set out to write a script with the following goals:
- Check for duplicate/re-used passwords
- Check the strength of each password
- Check passwords against the
pwnedpassAPI
Preface
It's worth nothing that I use passwordstore
to generate, and manage my passwords. On mobile, this is done using the official
OpenKeychain, and
Password Store. Passwords are
shared across my devices using Git2
Pump Your Brakes
Instead of jumping right into checking all my passwords, in plain-text, against
the pwnedpasswords API, it would be best to figure out how to safely transform
them to sha1sum3 . The API supports sending the first 5 characters of a sha1sum,
returning a list of all sha1sums of exposed passwords (with the exposed
count) for the user to verify them on their end.
Gathering Passwords
The easiest way to get a comprehensive list (associative array4 ) of
passwords and their pass path was to use find to look for *.gpg files in
my .password-store directory:
# Fetches all passwords in $PASSDIR and checks for duplicates (base check)
getpws()
{
# Loop over the find (newline-in-filename safe)
while read -r -d '' p; do
# Remove the root directory, and file extension
p=$(printf "%s" "$p" | sed "s|^$PASSDIR/||" | sed "s/.gpg//")
# Collect the trimmed, sha1 passwords
pwsha=$(pass "$p" | awk 'FNR==1 {printf "%s", $0}' | sha1sum | awk '{printf "%s", toupper($1)}')
pws["$p"]="$pwsha"
done < <(find "$PASSDIR" -name "*.gpg" -type f -print0)
}
To note, find with -print0 is used to avoid printing newline characters
(unlikely, but good practice), so that we can utilize the null terminator ''
within read -d ''. Also, read -r simply prevents backslashes from being
treated in a special way (also good practice!)5
It may be worth mentioning, to folks less familiar with awk, that the
FNR==1, in this context, simply helps to get rid of any newline oddities from
being piped into sha1sum. I discovered incorrect sha1sum values without
FNR==1 resulting in a useless password check!
{{% admonition note Note %}}
IFS= would not have fixed the above newline issue, as the problem stems
from the output of pass "$p" and not the filenames.
{{% /admonition %}}
That takes care of gathering our passwords, but we'll revisit this again in the next part.
Sharing is not Caring
The most efficient way of checking for duplicates was simply to iterate over the
array of passwords gathered, and check against the current one found in the
getpws() function's loop. The names of the duplicate passwords are stored in
another associative array for printing later as part of the "report".
# Checks for duplicate sha1sums of passwords in the associative array
checkdupes()
{
for i in "${!pws[@]}"; do
if [[ "$2" == "${pws[$i]}" ]]; then
pwdupes["$1"]="$i"
fi
done
}
That being done, we just incorporate it into the above getpws() loop!
getpws()
{
while read -r -d '' p; do
...
checkdupes "$p" "$pwsha"
done < <(find "$PASSDIR" -name "*.gpg" -type f -print0)
}
This accomplishes our first goal of checking duplicate passwords -- hooray!
Next up: Passwortstärke