Password Generation & Security Operations
Password Generation & Security Operations
Comprehensive guide to generating cryptographically secure passwords and secrets on Linux systems.
Quick Reference
# 32-char alphanumeric (most compatible)
openssl rand -base64 32 | tr -d '/+=' | head -c 32 && echo
# 24-char with symbols (high entropy)
openssl rand -base64 24
# Hex string (tokens, API keys)
openssl rand -hex 32
# UUID v4
uuidgen
# pass generate (stores automatically)
pass generate ARCANA/api/service-name 32
Password Generation Methods
1. OpenSSL (Recommended)
OpenSSL provides cryptographically secure random bytes from
/dev/urandom.
Alphanumeric Only
# 32 characters - clean, no special chars
openssl rand -base64 32 | tr -d '/+=' | head -c 32
# Output: 5kFxc5M6xuI6myLaSKWDX7tU8VRtujOU
# With length variable
LEN=24 && openssl rand -base64 $((LEN * 2)) | tr -d '/+=' | head -c $LEN
2. /dev/urandom Direct
# Alphanumeric
< /dev/urandom tr -dc 'A-Za-z0-9' | head -c 32
# With symbols
< /dev/urandom tr -dc 'A-Za-z0-9!@#$%^&*' | head -c 32
# Lowercase + numbers only
< /dev/urandom tr -dc 'a-z0-9' | head -c 32
3. UUID Generation
# UUID v4 (random)
uuidgen
# Output: f47ac10b-58cc-4372-a567-0e02b2c3d479
# Without dashes (32 hex chars)
uuidgen | tr -d '-'
# Lowercase
uuidgen | tr '[:upper:]' '[:lower:]'
4. Python One-Liners
# Secure random string
python3 -c "import secrets; print(secrets.token_urlsafe(24))"
# Hex token
python3 -c "import secrets; print(secrets.token_hex(16))"
# Custom alphabet
python3 -c "import secrets,string; print(''.join(secrets.choice(string.ascii_letters + string.digits) for _ in range(32)))"
Pass Integration
Generate and Store
# Generate 32-char password and store
pass generate ARCANA/api/ise-02 32
# Generate without symbols
pass generate -n ARCANA/api/ise-02 32
# Generate and copy to clipboard
pass generate -c ARCANA/api/ise-02 32
# Generate, don't print, copy to clipboard
pass generate -c -n ARCANA/api/ise-02 32
Insert with Metadata
# Generate password first
PASS=$(openssl rand -base64 32 | tr -d '/+=' | head -c 32)
# Insert with metadata using heredoc
pass insert -m ARCANA/api/ise-02 << EOF
${PASS}
---
type: cisco-ise-ers
node: ise-02
role: secondary-pan
connection:
host: ise-02.inside.domusdigitalis.dev
ip: 10.50.1.21
port: 9060
protocol: https
endpoint: /ers/config
credentials:
username: ersadmin
auth: basic
meta:
created: $(date +%Y-%m-%d)
version: "3.2"
notes: ERS API for automation scripts
EOF
Batch Password Generation Script
#!/bin/bash
# generate-pass-entry.sh - Generate password with metadata
CATEGORY="$1"
NAME="$2"
LENGTH="${3:-32}"
if [[ -z "$CATEGORY" || -z "$NAME" ]]; then
echo "Usage: $0 <category> <name> [length]"
echo "Example: $0 ARCANA/api ise-02 32"
exit 1
fi
PASS=$(openssl rand -base64 $((LENGTH * 2)) | tr -d '/+=' | head -c "$LENGTH")
CREATED=$(date +%Y-%m-%d)
echo "Generated: $PASS"
echo "Path: $CATEGORY/$NAME"
echo ""
read -p "Add metadata? [y/N] " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
read -p "Service type: " SERVICE_TYPE
read -p "Username: " USERNAME
read -p "Host/Endpoint: " ENDPOINT
read -p "Notes: " NOTES
pass insert -m "$CATEGORY/$NAME" << EOF
${PASS}
---
type: ${SERVICE_TYPE}
credentials:
username: ${USERNAME}
endpoint: ${ENDPOINT}
meta:
created: ${CREATED}
notes: ${NOTES}
EOF
else
echo "$PASS" | pass insert -m "$CATEGORY/$NAME"
fi
echo "Stored at: $CATEGORY/$NAME"
Entropy Calculation
Understanding Password Strength
| Character Set | Pool Size | Bits per Char |
|---|---|---|
Numeric (0-9) |
10 |
3.32 |
Lowercase (a-z) |
26 |
4.70 |
Uppercase (A-Z) |
26 |
4.70 |
Alphanumeric |
62 |
5.95 |
+ Symbols (32) |
94 |
6.55 |
Base64 |
64 |
6.00 |
Hex |
16 |
4.00 |
Common Password Strengths
| Length | Alphanumeric | With Symbols | Hex |
|---|---|---|---|
16 |
95 bits |
105 bits |
64 bits |
24 |
143 bits |
157 bits |
96 bits |
32 |
190 bits |
210 bits |
128 bits |
64 |
381 bits |
419 bits |
256 bits |
Quick Entropy Calculator
#!/bin/bash
# entropy.sh - Calculate password entropy
calc_entropy() {
local password="$1"
local length=${#password}
local pool=0
[[ "$password" =~ [0-9] ]] && ((pool += 10))
[[ "$password" =~ [a-z] ]] && ((pool += 26))
[[ "$password" =~ [A-Z] ]] && ((pool += 26))
[[ "$password" =~ [^a-zA-Z0-9] ]] && ((pool += 32))
# entropy = length * log2(pool)
local entropy=$(echo "scale=2; $length * l($pool)/l(2)" | bc -l)
echo "Length: $length"
echo "Pool size: $pool"
echo "Entropy: $entropy bits"
if (( $(echo "$entropy >= 128" | bc -l) )); then
echo "Strength: EXCELLENT"
elif (( $(echo "$entropy >= 80" | bc -l) )); then
echo "Strength: STRONG"
elif (( $(echo "$entropy >= 60" | bc -l) )); then
echo "Strength: MODERATE"
else
echo "Strength: WEAK"
fi
}
calc_entropy "$1"
Device-Specific Requirements
Cisco ISE Password Policy
ISE enforces strict password requirements:
-
Minimum: 6 characters (default policy)
-
Must contain: uppercase, lowercase, number, special character
-
AVOID these characters in GUI passwords:
$"'\'\-
ISE web security filter blocks
$as potential injection -
Quotes and backticks cause parsing issues
-
Safe special characters for ISE:
! @ # % ^ & * ( ) - _ = + [ ] { } | ; : , . < > ?
Quick ISE-safe password (one-liner):
< /dev/urandom tr -dc 'A-Za-z0-9!@#%^&*' | head -c 24 && echo
# ISE-compliant password function (GUI-safe characters only)
generate_ise_password() {
local length=${1:-20}
local password=""
local safe_symbols='!@#%^&*()-_=+'
# Ensure at least one of each required type
password+=$(< /dev/urandom tr -dc 'A-Z' | head -c 1)
password+=$(< /dev/urandom tr -dc 'a-z' | head -c 1)
password+=$(< /dev/urandom tr -dc '0-9' | head -c 1)
password+=$(< /dev/urandom tr -dc "$safe_symbols" | head -c 1)
# Fill remaining with mixed chars (NO $ symbol)
password+=$(< /dev/urandom tr -dc "A-Za-z0-9${safe_symbols}" | head -c $((length - 4)))
# Shuffle the password
echo "$password" | fold -w1 | shuf | tr -d '\n'
echo
}
# Usage
generate_ise_password 24
Shell Functions
Add to ~/.bashrc or ~/.config/fish/functions/:
Bash
# ~/.bashrc
# Quick password generation
randpass() {
local length=${1:-32}
openssl rand -base64 $((length * 2)) | tr -d '/+=' | head -c "$length"
echo
}
# With symbols
randpass-sym() {
local length=${1:-32}
openssl rand -base64 "$length"
}
# Hex token
randtoken() {
local bytes=${1:-32}
openssl rand -hex "$bytes"
}
# ISE-compliant (NO $ - ISE GUI blocks it)
randpass-ise() {
local length=${1:-20}
local p=""
local safe='!@#%^&*()-_=+'
p+=$(< /dev/urandom tr -dc 'A-Z' | head -c 1)
p+=$(< /dev/urandom tr -dc 'a-z' | head -c 1)
p+=$(< /dev/urandom tr -dc '0-9' | head -c 1)
p+=$(< /dev/urandom tr -dc "$safe" | head -c 1)
p+=$(< /dev/urandom tr -dc "A-Za-z0-9${safe}" | head -c $((length - 4)))
echo "$p" | fold -w1 | shuf | tr -d '\n'
echo
}
# Generate and copy to clipboard
randpass-clip() {
local pass=$(randpass "${1:-32}")
echo "$pass" | wl-copy
echo "Copied to clipboard (32 chars)"
}
Fish
# ~/.config/fish/functions/randpass.fish
function randpass -d "Generate random password"
set -l length $argv[1]
test -z "$length"; and set length 32
openssl rand -base64 (math "$length * 2") | tr -d '/+=' | head -c $length
echo
end
function randtoken -d "Generate hex token"
set -l bytes $argv[1]
test -z "$bytes"; and set bytes 32
openssl rand -hex $bytes
end
function randpass-clip -d "Generate and copy to clipboard"
set -l pass (randpass $argv[1])
echo $pass | wl-copy
echo "Copied to clipboard"
end
Security Best Practices
DO
# Use cryptographically secure sources
openssl rand ...
/dev/urandom
python3 secrets module
# Use sufficient length
# Minimum 16 chars, recommended 24-32 chars
# Store securely
pass insert ...
age -e ...
# Clear clipboard after use
wl-copy --clear # after 45 seconds by default with pass -c
DON’T
# Never use $RANDOM (predictable)
echo $RANDOM # BAD
# Never use date-based seeds
date +%s | sha256sum # BAD
# Never use /dev/random (blocks, not more secure)
< /dev/random # Unnecessary, /dev/urandom is fine
# Never echo passwords to terminal logs
echo "password is $PASS" # Logged in history
Secure Temporary Storage
# Use process substitution (no temp file)
pass insert mypass < <(openssl rand -base64 24)
# Or heredoc (also no temp file)
pass insert -m mypass << EOF
$(openssl rand -base64 24)
EOF
# If temp file needed, secure it
TMPFILE=$(mktemp)
chmod 600 "$TMPFILE"
openssl rand -base64 24 > "$TMPFILE"
# ... use file ...
shred -u "$TMPFILE"
Automation Scripts
Bulk Password Rotation
#!/bin/bash
# rotate-passwords.sh - Rotate multiple pass entries
ENTRIES=(
"ARCANA/api/ise-01"
"ARCANA/api/ise-02"
"ARCANA/ssh/ise-01"
"ARCANA/ssh/ise-02"
)
for entry in "${ENTRIES[@]}"; do
echo "Rotating: $entry"
# Backup old
OLD=$(pass show "$entry" | head -1)
echo "Old: ${OLD:0:4}****"
# Generate new (keeps metadata if using pass generate with -i)
pass generate -i "$entry" 32
NEW=$(pass show "$entry" | head -1)
echo "New: ${NEW:0:4}****"
echo "---"
done
echo "Done. Don't forget to update actual services!"
Export for Ansible Vault
#!/bin/bash
# export-to-vault.sh - Export pass entries to Ansible vault format
OUTPUT="secrets.yml"
cat > "$OUTPUT" << 'HEADER'
---
# Ansible Vault Secrets
# Encrypted with: ansible-vault encrypt secrets.yml
HEADER
# Add entries
echo "ise_api_password: \"$(pass show ARCANA/api/ise-02 | head -1)\"" >> "$OUTPUT"
echo "ise_ssh_password: \"$(pass show ARCANA/ssh/ise-02 | head -1)\"" >> "$OUTPUT"
# Encrypt
ansible-vault encrypt "$OUTPUT"
echo "Created encrypted: $OUTPUT"
Quick Reference Card
+------------------------------------------------------------------+ | PASSWORD GENERATION | +------------------------------------------------------------------+ | ALPHANUMERIC (32 chars) | | openssl rand -base64 32 | tr -d '/+=' | head -c 32 | | | | WITH SYMBOLS | | openssl rand -base64 24 | | | | HEX TOKEN | | openssl rand -hex 32 | | | | UUID | | uuidgen | | | | PASS GENERATE | | pass generate PATH 32 | | pass generate -c PATH 32 # copy to clipboard | | pass generate -n PATH 32 # no symbols | +------------------------------------------------------------------+ | ENTROPY TARGETS | +------------------------------------------------------------------+ | 80+ bits = Strong (16 alphanumeric) | | 128+ bits = Very Strong (22 alphanumeric) | | 256+ bits = Maximum (43 alphanumeric) | +------------------------------------------------------------------+ | SHELL FUNCTIONS | +------------------------------------------------------------------+ | randpass [len] # alphanumeric | | randpass-sym [len] # with symbols | | randtoken [bytes] # hex token | | randpass-clip [len] # generate + copy | +------------------------------------------------------------------+
Generate password
NEWPASS=$(< /dev/urandom tr -dc ‘A-Za-z0-9’ | head -c 32) echo “New password: $NEWPASS”