How to generate thousands of usernames and halfway decent passwords with Bash💯💯

Pascal Thormeier - May 17 '21 - - Dev Community

Have you ever needed, say, an astonishing number of user names and passwords? I recently did and thought to myself: "I can automate that!"

But, first of all...

What kind of user names and passwords are we talking about?

Some tools use them a lot, especially for anonymous users: Positive adjectives together with animal names. For example: "Knowledgeable ibex" or... See, it's quite hard to come up with those, especially if English isn't your first language. I was thinking for a good 5 minutes and the ibex was the only example I could come up with. To be fair, I haven't had a coffee yet... I'm getting off topic. Where was I? Anyways, you get the idea: "Positive adjective + animal". Such user names can be used as testing data, anonymous users or basically any use case where a lot of unique user names are necessary.

The password should ideally be something random, too. 16 characters, including numbers, uppercase and lowercase letters, and some special characters like !._-,;?^$+"*%&/()=.

Getting the data

So, let's first gather some data. I need animals and positive adjectives. I found a pretty large list of animals over at a-z-animals.com and a large list of positive adjectives at grammar.yourdictionary.com. Perfect. I create two lists, separated by newlines and put them in two files, namely animals.txt and adjectives.txt. So far so good, that's all the data I need, the rest is done with Bash.

Mapping a file using mapfile

Since Bash 4.0 there's a neat command called mapfile that reads a file line by line and creates an array out of it. I use this to read out all adjectives and animals:

#!/bin/bash

mapfile ADJECTIVES < ./adjectives.txt
mapfile ANIMALS < ./animals.txt
Enter fullscreen mode Exit fullscreen mode

Generating the usernames

To generate a large number of user names, I could now randomly select one of each and concatenate them:

#!/bin/bash

mapfile ADJECTIVES < ./adjectives.txt
mapfile ANIMALS < ./animals.txt

RANDOM_ADJECTIVE=$(echo ${ADJECTIVES[$RANDOM % ${#ADJECTIVES[@]} ]})
RANDOM_ANIMAL=$(echo ${ANIMALS[$RANDOM % ${#ANIMALS[@]} ]})
Enter fullscreen mode Exit fullscreen mode

I'm using $RANDOM here to generate a random number. This random number mod the size of the list guarantees to create a random number that is one of the array indices of that list. with ${LIST[...]} I then get the randomly chosen element.

Next, I concatenate them and massage the string a bit:

# ...

RANDOM_ADJECTIVE=$(echo ${ADJECTIVES[$RANDOM % ${#ADJECTIVES[@]} ]})
RANDOM_ANIMAL=$(echo ${ANIMALS[$RANDOM % ${#ANIMALS[@]} ]})

# Concat
ADJECTIVE_ANIMAL=$(echo $RANDOM_ADJECTIVE-$RANDOM_ANIMAL)

# Make it machine readable
MACHINEREADABLE=$(echo $ADJECTIVE_ANIMAL | iconv -t ascii//TRANSLIT | sed -r s/[^a-zA-Z0-9]+/-/g | tr A-Z a-z)
Enter fullscreen mode Exit fullscreen mode

First, all characters that are not ASCII are transliterated as such using iconv, for example äàá should all become a. Then I replace all non-alphanumeric characters with - using sed -r. In the last step, I transform the string to lower case using tr.

This now produces things like these:

fantastic-poodle
giving-dalmadoodle
glowing-sheepadoodle
focused-pointer
articulate-fly
glittering-stag-beetle
articulate-leopard-frog
unique-estrela-mountain-dog
excellent-russell-terrier
splendid-echidna
brilliant-italian-greyhound
magnificent-barnacle
polite-saint-bernard
glittering-eastern-bluebird
imaginative-manta-ray
willing-doberman-pinscher
faithful-drever
Enter fullscreen mode Exit fullscreen mode

Gotta love the fantastic poodle!

Generating the password

Now for the fun part: Generating a decent password. I rely on the OS here by using /dev/urandom:

# ...
PASSWORD=$(cat /dev/urandom | tr -cd '[:graph:]' | fold -w 24 | head -n 1)
Enter fullscreen mode Exit fullscreen mode

So a random bit string is read from /dev/urandom, which is then transformed into a string containing all printable characters (using [:graph:]). The string is then folded into words with 24 characters length. The first one of these words is then selected with head -n 1. This produces passwords like these:

Lb6UR+-iF5xj5`q}g1t(d3Dn
W]Aai"t,<H:)M[QV$lJi~H.%
V~2=Jq2InaGAU^Y\Uzx^9500
+XuY\[7-]g<[FyYKpE+"G[r7
=LYmTQ$D"}MN5]wC{$;ySE.}
jsE:y+A)NV{0CHvO-D)wazx*
2TB1~~Q~8d<_'Zj)ED$1yQ8\
!=bV.w0ko0F/Y"98M`ZzS1'%
IVmd4XfNR3'iffVUuwJ"[_IT
CR,Iq`},c5X7JdFfF7b@bi3!
:{y%'0%M~ys1lhR=$d,xNE"%
D*0AJikOKcBUo&6hku]g<(ZC
fQK'%R8("+*/o;.Vfd<7;/"W
Enter fullscreen mode Exit fullscreen mode

Looks pretty secure to me. Let's test =LYmTQ$D"}MN5]wC{$;ySE.} with some "password security testing tools" that a popular search engine is suggesting.

Password strength checker number 1

Password strength checker number 2

Password strength checker number 3

Ok, those numbers are dizzying, but differ widely. Here's a checker that actually tells you how they calculate the strength of a password:

A verbose password strength checker

Sounds good to me. For a one time login/password, that should be more than enough.

The final script

I also added a loop around the thing to generate multiple usernames and passwords.

#!/bin/bash

mapfile ANIMALS < ./animals.txt
mapfile ADJECTIVES < ./adjectives.txt

for ((N=0; N<$1; N++))
do
  RANDOM_ADJECTIVE=$(echo ${ADJECTIVES[$RANDOM % ${#ADJECTIVES[@]} ]})
  RANDOM_ANIMAL=$(echo ${ANIMALS[$RANDOM % ${#ANIMALS[@]} ]})

  ADJECTIVE_ANIMAL=$(echo $RANDOM_ADJECTIVE-$RANDOM_ANIMAL)

  MACHINEREADABLE=$(echo $ADJECTIVE_ANIMAL | iconv -t ascii//TRANSLIT | sed -r s/[^a-zA-Z0-9]+/-/g | tr A-Z a-z)

  PASSWORD=$(cat /dev/urandom | tr -cd '[:graph:]' | fold -w 24 | head -n 1)

  echo $MACHINEREADABLE $PASSWORD
done
Enter fullscreen mode Exit fullscreen mode

The first parameter of the script now determines the number of user name/password pairs generated:

user@dir $ ./create-users.sh 10
amazing-carp ACytS~_(Z+|<4fi}V<Mjy*g~
splendid-glen-of-imaal-terrier \#AK@]m[7R*>hzuOO^%r1ZY@
capable-blue-lacy-dog ?;CnSkJW's.<|PN:wQDOikI/
considerate-eastern-lowland-gorilla zQxT`]miaE4m$*W`Z8tpa@N5
powerful-puffin Kh=SUqh<no18.[A$Fea+LLXg
philosophical-bernese-shepherd 1h),NV(hi<vG)~{A]x^2I?bH
hardworking-american-foxhound \pbzUC~*~VLk}$wy6dHWFcw(
amazing-canadian-eskimo-dog -x{8PIwiI$/NcZ5#}'$Wlod-
responsible-umbrellabird eDzW\1H/U/(L_fHS^(U&:ltd
agreeable-termite |Kcgx-go>$7`:}nn7-\P&"}b
Enter fullscreen mode Exit fullscreen mode

Amazing! Only need to copy/paste that now.

Whats your favorite positive-adjective + animal username you could generate? Leave a comment!


I hope you enjoyed reading this article as much as I enjoyed writing it! If so, leave a ❤️ or a 🦄! I write tech articles in my free time and like to drink coffee every once in a while.

If you want to support my efforts, buy me a coffee or follow me on Twitter 🐦! You can also support me directly via Paypal!

Buy me a coffee button

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Terabox Video Player