[PATCH] Add support for XKCD-style wordlist passwords

Adhityaa Chandrasekar pass at adtac.in
Tue Oct 30 06:50:48 CET 2018


>From bb2a4e5664b2580ed1acbe973d4f86d550b529f1 Mon Sep 17 00:00:00 2001
From: Adhityaa Chandrasekar <adtac at adtac.in>
Date: Mon, 29 Oct 2018 19:10:23 -0400
Subject: [PATCH v3] Add support for XKCD-style wordlist passwords

Oops, attempting to read line 0 with sed will result in an error, so
line_num must be greater than or equal to 1. Fixed that.

(Man, I suck at mailing list patches.)

---
man/pass.1            | 17 ++++++++++-------
src/password-store.sh | 22 +++++++++++++++++-----
2 files changed, 27 insertions(+), 12 deletions(-)

diff --git a/man/pass.1 b/man/pass.1
index 01a3fbe..72a83fc 100644
--- a/man/pass.1
+++ b/man/pass.1
@@ -122,15 +122,18 @@ ensure that temporary files are created in \fI/dev/shm\fP in order to avoid writ
difficult-to-erase disk sectors. If \fI/dev/shm\fP is not accessible, fallback to
the ordinary \fITMPDIR\fP location, and print a warning.
.TP
-\fBgenerate\fP [ \fI--no-symbols\fP, \fI-n\fP ] [ \fI--clip\fP, \fI-c\fP ] [ \fI--in-place\fP, \fI-i\fP | \fI--force\fP, \fI-f\fP ] \fIpass-name [pass-length]\fP
+\fBgenerate\fP [ \fI--no-symbols\fP, \fI-n\fP ] [ \fI--wordlist /path/to/wordlist\fP, \fI-w /path/to/wordlist\fP ][ \fI--clip\fP, \fI-c\fP ] [ \fI--in-place\fP, \fI-i\fP | \fI--force\fP, \fI-f\fP ] \fIpass-name [pass-length]\fP
Generate a new password using \fB/dev/urandom\fP of length \fIpass-length\fP
(or \fIPASSWORD_STORE_GENERATED_LENGTH\fP if unspecified) and insert into
-\fIpass-name\fP. If \fI--no-symbols\fP or \fI-n\fP is specified, do not use
-any non-alphanumeric characters in the generated password. The character sets used
-in generating passwords can be changed with the \fIPASSWORD_STORE_CHARACTER_SET\fP and
-\fIPASSWORD_STORE_CHARACTER_SET_NO_SYMBOLS\fP environment variables, described below.
-If \fI--clip\fP or \fI-c\fP is specified, do not print the password but instead copy
-it to the clipboard using
+\fIpass-name\fP. If \fI--no-symbols\fP or \fI-n\fP is specified, do not use any
+non-alphanumeric characters in the generated password. If \fI--wordlist\fP is
+specified, along with a file as argument containing a list of words to choose
+from, four words will be randomly chosen and used as password. The character
+sets used in generating passwords can be changed with the
+\fIPASSWORD_STORE_CHARACTER_SET\fP and
+\fIPASSWORD_STORE_CHARACTER_SET_NO_SYMBOLS\fP environment variables, described
+below.  If \fI--clip\fP or \fI-c\fP is specified, do not print the password but
+instead copy it to the clipboard using
.BR xclip (1)
and then restore the clipboard after 45 (or \fIPASSWORD_STORE_CLIP_TIME\fP) seconds. If \fI--qrcode\fP
or \fI-q\fP is specified, do not print the password but instead display a QR code using
diff --git a/src/password-store.sh b/src/password-store.sh
index d89d455..d8bf9e4 100755
--- a/src/password-store.sh
+++ b/src/password-store.sh
@@ -491,12 +491,13 @@ cmd_edit() {
}

cmd_generate() {
-	local opts qrcode=0 clip=0 force=0 characters="$CHARACTER_SET" inplace=0 pass
-	opts="$($GETOPT -o nqcif -l no-symbols,qrcode,clip,in-place,force -n "$PROGRAM" -- "$@")"
+	local opts qrcode=0 clip=0 force=0 characters="$CHARACTER_SET" wordlist=0 inplace=0 pass
+	opts="$($GETOPT -o nw:qcif -l no-symbols,wordlist:,qrcode,clip,in-place,force -n "$PROGRAM" -- "$@")"
local err=$?
eval set -- "$opts"
while true; do case $1 in
-n|--no-symbols) characters="$CHARACTER_SET_NO_SYMBOLS"; shift ;;
+		-w|--wordlist) wordlist=$2; shift; shift ;;
-q|--qrcode) qrcode=1; shift ;;
-c|--clip) clip=1; shift ;;
-f|--force) force=1; shift ;;
@@ -504,7 +505,7 @@ cmd_generate() {
--) shift; break ;;
esac done

-	[[ $err -ne 0 || ( $# -ne 2 && $# -ne 1 ) || ( $force -eq 1 && $inplace -eq 1 ) || ( $qrcode -eq 1 && $clip -eq 1 ) ]] && die "Usage: $PROGRAM $COMMAND [--no-symbols,-n] [--clip,-c] [--qrcode,-q] [--in-place,-i | --force,-f] pass-name [pass-length]"
+	[[ $err -ne 0 || ( $# -ne 2 && $# -ne 1 ) || ( $force -eq 1 && $inplace -eq 1 ) || ( $qrcode -eq 1 && $clip -eq 1 ) ]] && die "Usage: $PROGRAM $COMMAND [--no-symbols,-n] [--wordlist,-w /path/to/wordlist] [--clip,-c] [--qrcode,-q] [--in-place,-i | --force,-f] pass-name [pass-length]"
local path="$1"
local length="${2:-$GENERATED_LENGTH}"
check_sneaky_paths "$path"
@@ -517,8 +518,19 @@ cmd_generate() {

[[ $inplace -eq 0 && $force -eq 0 && -e $passfile ]] && yesno "An entry already exists for $path. Overwrite it?"

-	read -r -n $length pass < <(LC_ALL=C tr -dc "$characters" < /dev/urandom)
-	[[ ${#pass} -eq $length ]] || die "Could not generate password from /dev/urandom."
+	if [[ "$wordlist" != "" ]]; then
+		num_lines=$(wc -l "$wordlist" | cut -d ' ' -f 1)
+		pass=""
+		for i in $(seq 1 4); do
+			line_num=$((1 + ($RANDOM << 16 + $RANDOM) % $num_lines))
+			pass=$(sed "${line_num}q;d" "$wordlist" | grep -o "[a-z]" | tr -d "\n")-$pass
+		done
+		pass=${pass:0:-1}
+	else
+		read -r -n $length pass < <(LC_ALL=C tr -dc "$characters" < /dev/urandom)
+		[[ ${#pass} -eq $length ]] || die "Could not generate password from /dev/urandom."
+	fi
+
if [[ $inplace -eq 0 ]]; then
echo "$pass" | $GPG -e "${GPG_RECIPIENT_ARGS[@]}" -o "$passfile" "${GPG_OPTS[@]}" || die "Password encryption aborted."
else
--
2.19.1



On Tue, 30 Oct 2018, at 1:10 AM, Brad Knowles wrote:
> On Oct 30, 2018, at 12:00 AM, Adhityaa Chandrasekar <pass at adtac.in> wrote:
> 
>> +	if [[ "$wordlist" != "" ]]; then
>> +		pass=$(shuf -n 4 "$wordlist" | paste -sd "-" -)
>> +	else
> 
> While I think the concept is a good one, I don't think we should be depending on the user having "shuf" installed on their machine.  I don't have it on mine, and I've installed a whole boatload of extra stuff that most people don't have.
> 
> I'm also not sure about "paste", although I do happen to have a program by that name on my machine.
> 
> IMO, you're better off sticking to more standard *nix utilities.
> 
> --
> Brad Knowles <brad at shub-internet.org>
> 
> Please forgive any typos.  I'm fighting a failing keyboard on my laptop, in addition to having a broken finger.
> 


More information about the Password-Store mailing list