<div dir="ltr">I thought it was pretty neat both because of its simplicity and its 'bruteness', but I can't take the credit. I grabbed it from <a href="http://unix.stackexchange.com/a/230676/56148">this answer</a> to a question on generating random strings on the Unix & Linux Stack Exchange site.<div><br></div><div>But I can't reproduce the bug you claimed exists. Here's how I tried to reproduce it.</div><div><br></div><div>I created a text file named "test.txt" with the initial contents of "0123456789".</div><div><br></div><div>I ran this and it worked as expected:</div><div><br></div><div>```</div><div><div>$ head test.txt | tr -dc '0-9' | head -c 10 && echo</div><div>0123456789</div></div><div>```</div><div><br></div><div>I then edited "test.txt", inserted a newline between the `4` and `5`, and saved the file. I reran the same command as before:</div><div><br></div><div>```</div><div><div>$ head test.txt | tr -dc '0-9' | head -c 10 && echo</div><div>0123456789</div></div><div>```</div><div><br></div><div>Is running `head` with a text file containing newlines somehow different than reading from /dev/urandom and reading bytes matching newline character byte values?</div><div><br></div></div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Nov 9, 2016 at 2:32 PM, Kevin Cox <span dir="ltr"><<a href="mailto:kevincox@kevincox.ca" target="_blank">kevincox@kevincox.ca</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="auto">I'm not sure whether I am impressed by the simplicity or scared by the bruteness. Obviously the performance will drop as you have a smaller character set but that is probably not w problem as even with one character you will only need 256 bytes per character in the resulting password. <div dir="auto"><br></div><div dir="auto">You do have a bug though. You shouldn't use head because then if you happen to draw 10 newlines before the characters you need your generated password will be shorter then you expected. Try the following. </div><div dir="auto"><br></div><div dir="auto">tr -nd ... </dev/random | ...</div></div><div class="HOEnZb"><div class="h5"><div class="gmail_extra"><br><div class="gmail_quote">On Nov 9, 2016 16:56, "Kenny Evitt" <<a href="mailto:kenny.evitt@gmail.com" target="_blank">kenny.evitt@gmail.com</a>> wrote:<br type="attribution"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr">Replacing `pwgen` shouldn't be a big deal. The only Pass command that uses it is `generate` and the only options passed to are whether to include symbols and the length of the password.<div><br></div><div>Incidentally, I cobbled together a handy way of generating arbitrary passwords of any length using only specific special characters. It should work on most any Unix or Unix-like system. Here's an example for generating a password of 32 characters with only a limited set of special characters:</div><div><br></div><div>```</div><div>head /dev/urandom | tr -dc 'A-Za-z0-9!@#$%^&*()' | head -c 32 && echo<br></div><div>```</div><div><br></div><div>Here's an example with all of the OWASP special characters, which would be a good default if no set of { symbols / special characters } are specified:</div><div><br></div><div>```</div><div>head /dev/urandom | tr -dc 'A-Za-z0-9!"#$%&'\''()*+,-./:;<wbr><=>?@[\]^_`{|}~' | head -c 32 && echo<br></div><div>```</div><div><br></div><div>`pwgen` by default "generates passwords which are designed to be easily memorized by humans, while being as secure as possible". Pass hard-codes the call to `pwgen` to use the 'secure' option which will "generate completely random, hard-to-memorize passwords", so just reading from */dev/urandom* is probably just as good (and likely pretty similar to whatever `pwgen` is doing when the secure option is specified).</div><div><br></div><div>Below is a patch with changes that replace `pwgen` with my above commands.</div><div><br></div><div>Both `apg` and `mkpasswd` have some nice options for ensuring that passwords definitely contain certain types of characters, which is particularly useful for passwords that need to meet certain requirements, e.g. always include a special character.</div><div><br></div><div>But perhaps, instead of Pass depending directly on any particular password generator, it simply call another specified program to do so. If some passwords didn't (annoyingly) necessitate *excluding* certain special characters `pwgen` should be more than good enough. But given that generating arbitrary passwords for all of the possible sets of valid passwords is (annoyingly) difficult, perhaps Pass shouldn't bother to try to implement that itself beyond its current okay-ish default dependency on `pwgen`.</div><div><br></div><div><br></div><div><br></div><div>```</div><div><div>diff --git a/src/password-store.sh b/src/password-store.sh</div><div>index 63be840..10463cb 100755</div><div>--- a/src/password-store.sh</div><div>+++ b/src/password-store.sh</div><div>@@ -16,6 +16,7 @@ PREFIX="${PASSWORD_STORE_DIR:-<wbr>$HOME/.password-store}"</div><div> X_SELECTION="${PASSWORD_STORE<wbr>_X_SELECTION:-clipboard}"</div><div> CLIP_TIME="${PASSWORD_STORE_C<wbr>LIP_TIME:-45}"</div><div> GENERATED_LENGTH="${PASSWORD_<wbr>STORE_GENERATED_LENGTH:-25}"</div><div>+DEFAULT_SYMBOLS="${PASSWORD_S<wbr>TORE_DEFAULT_SYMBOLS:-\!\"#\$%<wbr>&\'()*+,-./:;<=>?@[\]^_\`{|\}~<wbr>}"</div><div><br></div><div> export GIT_DIR="${PASSWORD_STORE_GIT:<wbr>-$PREFIX}/.git"</div><div> export GIT_WORK_TREE="${PASSWORD_STOR<wbr>E_GIT:-$PREFIX}"</div><div>@@ -235,8 +236,8 @@ cmd_usage() {</div><div>                overwriting existing password unless forced.</div><div>            $PROGRAM edit pass-name</div><div>                Insert a new password or edit an existing password using ${EDITOR:-vi}.</div><div>-           $PROGRAM generate [--no-symbols,-n] [--clip,-c] [--in-place,-i | --force,-f] pass-name [pass-length]</div><div>-               Generate a new password of pass-length (or $GENERATED_LENGTH if unspecified) with optionally no symbols.</div><div>+           $PROGRAM generate [--clip,-c] [--in-place,-i | --force,-f] pass-name [pass-length] [symbols]</div><div>+               Generate a new password of pass-length (or $GENERATED_LENGTH if unspecified) with optional set of symbols to use (or $DEFAULT_SYMBOLS if unspecified).</div><div>                Optionally put it on the clipboard and clear board after $CLIP_TIME seconds.</div><div>                Prompt before overwriting existing password unless forced.</div><div>                Optionally replace only the first line of an existing file with a new password.</div><div>@@ -431,21 +432,21 @@ cmd_edit() {</div><div> }</div><div><br></div><div> cmd_generate() {</div><div>-       local opts clip=0 force=0 symbols="-y" inplace=0</div><div>-       opts="$($GETOPT -o ncif -l no-symbols,clip,in-place,force -n "$PROGRAM" -- "$@")"</div><div>+       local opts clip=0 force=0 inplace=0</div><div>+       opts="$($GETOPT -o cif -l clip,in-place,force -n "$PROGRAM" -- "$@")"</div><div>        local err=$?</div><div>        eval set -- "$opts"</div><div>        while true; do case $1 in</div><div>-               -n|--no-symbols) symbols=""; shift ;;</div><div>                -c|--clip) clip=1; shift ;;</div><div>                -f|--force) force=1; shift ;;</div><div>                -i|--in-place) inplace=1; shift ;;</div><div>                --) shift; break ;;</div><div>        esac done</div><div><br></div><div>-       [[ $err -ne 0 || ( $# -ne 2 && $# -ne 1 ) || ( $force -eq 1 && $inplace -eq 1 ) ]] && die "Usage: $PROGRAM $COMMAND [--no-symbols,-n] [--clip,-c] [--in-place,-i | --force,-f] pass-name [pass-length]"</div><div>+       [[ $err -ne 0 || ( $# -ne 3 && $# -ne 2 && $# -ne 1 ) || ( $force -eq 1 && $inplace -eq 1 ) ]] && die "Usage: $PROGRAM $COMMAND [--clip,-c] [--in-place,-i | --force,-f] pass-name [pass-length] [symbols]"</div><div>        local path="$1"</div><div>        local length="${2:-$GENERATED_LENGTH<wbr>}"</div><div>+       local symbols="${3:-$DEFAULT_SYMBOLS<wbr>}"</div><div>        check_sneaky_paths "$path"</div><div>        [[ ! $length =~ ^[0-9]+$ ]] && die "Error: pass-length \"$length\" must be a number."</div><div>        mkdir -p -v "$PREFIX/$(dirname "$path")"</div><div>@@ -454,7 +455,7 @@ cmd_generate() {</div><div><br></div><div>        [[ $inplace -eq 0 && $force -eq 0 && -e $passfile ]] && yesno "An entry already exists for $path. Overwrite it?"</div><div><br></div><div>-       local pass="$(pwgen -s $symbols $length 1)"</div><div>+       local pass="$(head /dev/urandom | tr -dc "A-Za-z0-9$symbols" | head -c "$length" && echo)"</div><div>        [[ -n $pass ]] || exit 1</div><div>        if [[ $inplace -eq 0 ]]; then</div><div>                $GPG -e "${GPG_RECIPIENT_ARGS[@]}" -o "$passfile" "${GPG_OPTS[@]}" <<<"$pass" || die "Password encryption aborted."</div></div><div>```</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Tue, Nov 8, 2016 at 5:23 PM, Diego Depaoli <span dir="ltr"><<a href="mailto:trebestie@gmail.com" target="_blank">trebestie@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div dir="ltr" class="m_3721146321964768174m_189061519198084053m_-2492182617681352069gmail_msg">I agree.<br class="m_3721146321964768174m_189061519198084053m_-2492182617681352069gmail_msg">
This is not a big issue, but sometimes limited pwgen features are annoying.<br class="m_3721146321964768174m_189061519198084053m_-2492182617681352069gmail_msg">Could apg or makepassword bè reliable replacements?<br></div><div dir="ltr" class="m_3721146321964768174m_189061519198084053m_-2492182617681352069gmail_msg"><br></div><div dir="ltr" class="m_3721146321964768174m_189061519198084053m_-2492182617681352069gmail_msg">My best regards</div><div><div class="m_3721146321964768174m_189061519198084053h5"><div dir="ltr" class="m_3721146321964768174m_189061519198084053m_-2492182617681352069gmail_msg"><br></div><div dir="ltr" class="m_3721146321964768174m_189061519198084053m_-2492182617681352069gmail_msg"><span style="font-size:13px">Il mar 8 nov 2016 20:55 Michael Hoff <</span><a href="mailto:mail@michael-hoff.net" class="m_3721146321964768174m_189061519198084053m_-2492182617681352069gmail_msg" style="font-size:13px" target="_blank">mail@michael-hoff.net</a><span style="font-size:13px">> ha scritto:</span></div></div></div><div class="gmail_quote m_3721146321964768174m_189061519198084053m_-2492182617681352069gmail_msg"><blockquote class="gmail_quote m_3721146321964768174m_189061519198084053m_-2492182617681352069gmail_msg" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div><div class="m_3721146321964768174m_189061519198084053h5">
  

    
  
  <div bgcolor="#FFFFFF" text="#000000" class="m_3721146321964768174m_189061519198084053m_-2492182617681352069gmail_msg">
    Hello,<br class="m_3721146321964768174m_189061519198084053m_-2492182617681352069gmail_msg">
    <br class="m_3721146321964768174m_189061519198084053m_-2492182617681352069gmail_msg">
    first of all: Really nice project!<br class="m_3721146321964768174m_189061519198084053m_-2492182617681352069gmail_msg">
    <br class="m_3721146321964768174m_189061519198084053m_-2492182617681352069gmail_msg">
    I very often encounter the problem that services do not allow all
    symbols used by pass/pwgen.<br class="m_3721146321964768174m_189061519198084053m_-2492182617681352069gmail_msg">
    "Your password has to contain at least one of the following symbols
    '*#_!'" (e.g. '<' is forbidden)<br class="m_3721146321964768174m_189061519198084053m_-2492182617681352069gmail_msg">
    <br class="m_3721146321964768174m_189061519198084053m_-2492182617681352069gmail_msg">
    This does hinder my work-flow as I have to manually adapt the
    password to match the criteria.<br class="m_3721146321964768174m_189061519198084053m_-2492182617681352069gmail_msg">
    <br class="m_3721146321964768174m_189061519198084053m_-2492182617681352069gmail_msg">
    Straight-forward solution to this problem would be to provide the
    symbol set via optional command line argument to the generate
    command.<br class="m_3721146321964768174m_189061519198084053m_-2492182617681352069gmail_msg">
    <br class="m_3721146321964768174m_189061519198084053m_-2492182617681352069gmail_msg">
    Example: pass generate <b class="m_3721146321964768174m_189061519198084053m_-2492182617681352069gmail_msg">-s "*#_!"</b> path/to/password 20<br class="m_3721146321964768174m_189061519198084053m_-2492182617681352069gmail_msg">
    <br class="m_3721146321964768174m_189061519198084053m_-2492182617681352069gmail_msg">
    I already checked man page and source code of pwgen. Unfortunately
    this feature is not provided out of the box.<br class="m_3721146321964768174m_189061519198084053m_-2492182617681352069gmail_msg">
    <br class="m_3721146321964768174m_189061519198084053m_-2492182617681352069gmail_msg">
    I see multiple possible solutions to this:<br class="m_3721146321964768174m_189061519198084053m_-2492182617681352069gmail_msg">
    - Exchange pwgen with apg (possibly massive side-effects)<br class="m_3721146321964768174m_189061519198084053m_-2492182617681352069gmail_msg">
    - Extend pwgen<br class="m_3721146321964768174m_189061519198084053m_-2492182617681352069gmail_msg">
    - Let pass itself convert unwanted symbols generated by pwgen
    (hacky)<br class="m_3721146321964768174m_189061519198084053m_-2492182617681352069gmail_msg">
    <br class="m_3721146321964768174m_189061519198084053m_-2492182617681352069gmail_msg">
    What do you think?<br class="m_3721146321964768174m_189061519198084053m_-2492182617681352069gmail_msg">
    <br class="m_3721146321964768174m_189061519198084053m_-2492182617681352069gmail_msg">
    Cheers,<br class="m_3721146321964768174m_189061519198084053m_-2492182617681352069gmail_msg">
    Michael Hoff
    <pre class="m_3721146321964768174m_189061519198084053m_-2492182617681352069m_-6090593353007391630m_7498965962380501004moz-signature m_3721146321964768174m_189061519198084053m_-2492182617681352069gmail_msg" cols="72">-- 
S/MIME and PGP (0xA79D31C0) supported
<a class="m_3721146321964768174m_189061519198084053m_-2492182617681352069m_-6090593353007391630m_7498965962380501004moz-txt-link-freetext m_3721146321964768174m_189061519198084053m_-2492182617681352069gmail_msg" href="https://michael-hoff.net" target="_blank">https://michael-hoff.net</a></pre>
  </div></div></div>

______________________________<wbr>_________________<br class="m_3721146321964768174m_189061519198084053m_-2492182617681352069gmail_msg">
Password-Store mailing list<br class="m_3721146321964768174m_189061519198084053m_-2492182617681352069gmail_msg">
<a href="mailto:Password-Store@lists.zx2c4.com" class="m_3721146321964768174m_189061519198084053m_-2492182617681352069gmail_msg" target="_blank">Password-Store@lists.zx2c4.com</a><br class="m_3721146321964768174m_189061519198084053m_-2492182617681352069gmail_msg">
<a href="http://lists.zx2c4.com/mailman/listinfo/password-store" rel="noreferrer" class="m_3721146321964768174m_189061519198084053m_-2492182617681352069gmail_msg" target="_blank">http://lists.zx2c4.com/mailman<wbr>/listinfo/password-store</a><span class="m_3721146321964768174m_189061519198084053HOEnZb"><font color="#888888"><br class="m_3721146321964768174m_189061519198084053m_-2492182617681352069gmail_msg">
</font></span></blockquote></div><span class="m_3721146321964768174m_189061519198084053HOEnZb"><font color="#888888"><div dir="ltr">-- <br></div><div data-smartmail="gmail_signature"><div dir="ltr">Diego Depaoli</div></div>
</font></span><br>______________________________<wbr>_________________<br>
Password-Store mailing list<br>
<a href="mailto:Password-Store@lists.zx2c4.com" target="_blank">Password-Store@lists.zx2c4.com</a><br>
<a href="http://lists.zx2c4.com/mailman/listinfo/password-store" rel="noreferrer" target="_blank">http://lists.zx2c4.com/mailman<wbr>/listinfo/password-store</a><br>
<br></blockquote></div><br></div>
<br>______________________________<wbr>_________________<br>
Password-Store mailing list<br>
<a href="mailto:Password-Store@lists.zx2c4.com" target="_blank">Password-Store@lists.zx2c4.com</a><br>
<a href="http://lists.zx2c4.com/mailman/listinfo/password-store" rel="noreferrer" target="_blank">http://lists.zx2c4.com/mailman<wbr>/listinfo/password-store</a><br>
<br></blockquote></div></div>
</div></div></blockquote></div><br></div>