Began write-up on pass-check.sh
This commit is contained in:
109
content/post/password_checker.md
Normal file
109
content/post/password_checker.md
Normal file
@@ -0,0 +1,109 @@
|
||||
---
|
||||
title: "Password Checking Script"
|
||||
date: 2019-04-13
|
||||
lastmod: 2019-04-13
|
||||
draft: true
|
||||
tags: ["linux","code"]
|
||||
categories: ["Blog"]
|
||||
contentCopyright: false
|
||||
hideHeaderAndFooter: false
|
||||
---
|
||||
Having been inspired by the HIBP[^1] password checker, I set out to write a
|
||||
script with the following goals:
|
||||
|
||||
1. Check for duplicate/re-used passwords
|
||||
1. Check the strength of each password
|
||||
1. Check passwords against the `pwnedpass` API
|
||||
|
||||
<!--more-->
|
||||
# Preface
|
||||
It's worth nothing that I use [`passwordstore`](https://www.passwordstore.org/)
|
||||
to generate, and manage my passwords. On mobile, this is done using the official
|
||||
[OpenKeychain](https://www.openkeychain.org/), and
|
||||
[Password Store](https://github.com/zeapo/Android-Password-Store). Passwords are
|
||||
shared across my devices using Git[^2]
|
||||
|
||||
# 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 `sha1sum`[^3]. The API supports sending the first 5 characters of a `sha1sum`,
|
||||
returning a list of all `sha1sum`s 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 array_[^4]) of
|
||||
passwords and their `pass` path was to use `find` to look for `*.gpg` files in
|
||||
my `.password-store` directory:
|
||||
```bash
|
||||
# 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".
|
||||
```bash
|
||||
# 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!
|
||||
```bash
|
||||
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_
|
||||
|
||||
# TODO
|
||||
|
||||
[^1]: [Have I Been Pwned](https://haveibeenpwned.com/Passwords)
|
||||
[^2]: [`pass` Extended Git Example](https://git.zx2c4.com/password-store/about/#EXTENDED%20GIT%20EXAMPLE)
|
||||
[^3]: [SHA-1 (Secure Hashing Algorithm)](https://en.wikipedia.org/wiki/SHA-1)
|
||||
[^4]: [Arrays (Bash Reference Manual)](https://www.gnu.org/software/bash/manual/html_node/Arrays.html)
|
||||
[^5]: [`man read`](https://linux.die.net/man/2/read)
|
||||
Reference in New Issue
Block a user