Random discussion in a Matrix chat today on people apparently asking AIs for random passwords today, linking to this article in The Register and I said:
Not that I'd ask an AI for a random anything. I might ask it for "some code to draw four random words from /usr/share/wordlist and combine them with some punctuation, and then make up a little story about the words so I can remember it" - that would meet the xkcd good password guidelines, and probably actually would be random. And it'd even be auditable.
Of course having said that, I had to actually do it as well...
So, here's the final script, which - in line with the XKCD correct horse battery staple approach:
- Gets four random words from /usr/share/dict/words
- Gets three random punctuation characters from a list
- Asks a local AI for a little story about them
#!/bin/bash
# Password generator by Andrew McMillan licensed CC-0
# See: https://creativecommons.org/publicdomain/zero/1.0/
#
# Configuration
DICT_FILE="/usr/share/dict/words"
AI_URL="http://localhost:1234/v1/chat/completions"
AI_MODEL="local-model"
# Check dependencies
if ! command -v jq &> /dev/null; then
echo "Error: jq is required but not installed."
exit 1
fi
if [ ! -f "$DICT_FILE" ]; then
echo "Error: Dictionary file not found at $DICT_FILE"
exit 1
fi
# 1. Generate Words
# Filter for lowercase, 4-8 chars, shuffle, pick 4
raw_words=$(grep -E '^[a-z]{4,8}$' "$DICT_FILE" | shuf -n 4)
words=($raw_words)
# 2. Generate Random Punctuation
# Define allowed separators (safe for passwords and typing)
separators=('-' '_' '.' '+' '!' '?' '=' ':')
num_seps=${#separators[@]}
# Pick 3 random separators
s1=${separators[$((RANDOM % num_seps))]}
s2=${separators[$((RANDOM % num_seps))]}
s3=${separators[$((RANDOM % num_seps))]}
# 3. Format Password
password="${words[0]}${s1}${words[1]}${s2}${words[2]}${s3}${words[3]}"
echo "----------------------------------------"
echo "PASSWORD: $password"
echo "----------------------------------------"
echo "Asking local AI for a story..."
# 4. Construct JSON Payload using jq (handles escaping safely)
# We ask the AI to uppercase the specific words so they stand out.
make_prompt() {
local w1="$(echo $1 | tr 'a-z' 'A-Z')"
local w2="$(echo $2 | tr 'a-z' 'A-Z')"
local w3="$(echo $3 | tr 'a-z' 'A-Z')"
local w4="$(echo $4 | tr 'a-z' 'A-Z')"
cat <<EOF
Create a very short, memorable, bizarre one-sentence story using
the following four words, in order, in uppercase. DO NOT USE
DIFFERENT WORDS: The story must contain these EXACT words, in
EXACTLY this sequence:"
${w1} ${w2} ${w3} ${w4} .
Your story will be scored according to how many of these words
are used, how many are in the correct order, and how many are
in UPPERCASE.
EOF
}
prompt="$(make_prompt ${words[0]} ${words[1]} ${words[2]} ${words[3]})"
json_payload=$(jq -n \
--arg model "$AI_MODEL" \
--arg prompt "$prompt" \
'{
model: $model,
messages: [
{
role: "system",
content: "You are a creative assistant."
},
{ role: "user", content: $prompt }
],
temperature: 0.7,
max_tokens: 150
}')
# 5. Send Request via Curl and parse immediately with jq
story=$(curl -s -X POST "$AI_URL" \
-H "Content-Type: application/json" \
-d "$json_payload" | jq -r '.choices[0].message.content')
# 6. Output
if [ "$story" == "null" ] || [ -z "$story" ]; then
echo "Error: Could not retrieve story from AI."
else
echo ""
echo -e "\033[1;32m$story\033[0m"
echo ""
fi
echo "----------------------------------------"
Now that's how to get an AI to give you some passwords.