Coming up with strong, random passwords is a challenge that every administrator and developer faces regularly — whether setting up service accounts, provisioning user credentials, or generating API keys. This guide covers multiple methods for generating secure random passwords across different platforms, along with best practices for password complexity and storage.

Password Complexity Requirements

Before generating passwords, understand what makes a password strong:

  • Length — Minimum 14 characters for administrative accounts, 12 for standard users
  • Character variety — Include uppercase letters, lowercase letters, digits, and special characters
  • Randomness — Use a cryptographically secure random number generator, not a predictable pattern
  • Uniqueness — Every account should have a different password

Most compliance frameworks (NIST, PCI-DSS, HIPAA) require passwords to meet specific complexity rules. NIST SP 800-63B recommends focusing on password length over complexity requirements, but many systems still enforce mixed character types.

PowerShell Methods

Using the Membership Class

The simplest method in PowerShell uses the System.Web.Security.Membership class:

# Load the System.Web assembly
Add-Type -AssemblyName System.Web

# Generate a single password (16 characters, minimum 4 special characters)
[System.Web.Security.Membership]::GeneratePassword(16, 4)

# Generate multiple passwords
1..10 | ForEach-Object {
    [System.Web.Security.Membership]::GeneratePassword(20, 5)
}

The first parameter is the total length, and the second is the minimum number of non-alphanumeric characters.

Custom PowerShell Password Generator

For more control over character sets and formatting:

function New-RandomPassword {
    param(
        [int]$Length = 16,
        [int]$MinUpperCase = 2,
        [int]$MinLowerCase = 2,
        [int]$MinDigits = 2,
        [int]$MinSpecial = 2
    )

    $upper   = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
    $lower   = 'abcdefghijklmnopqrstuvwxyz'
    $digits  = '0123456789'
    $special = '!@#$%^&*()-_=+[]{}|;:,.<>?'

    $password = @()

    # Ensure minimum requirements
    $password += ($upper.ToCharArray()   | Get-Random -Count $MinUpperCase)
    $password += ($lower.ToCharArray()   | Get-Random -Count $MinLowerCase)
    $password += ($digits.ToCharArray()  | Get-Random -Count $MinDigits)
    $password += ($special.ToCharArray() | Get-Random -Count $MinSpecial)

    # Fill remaining length with random characters from all sets
    $allChars = $upper + $lower + $digits + $special
    $remaining = $Length - $password.Count
    if ($remaining -gt 0) {
        $password += ($allChars.ToCharArray() | Get-Random -Count $remaining)
    }

    # Shuffle the result
    $password = $password | Get-Random -Count $password.Count

    return -join $password
}

# Generate a single password
New-RandomPassword -Length 20

# Generate a batch of passwords
1..25 | ForEach-Object { New-RandomPassword -Length 16 }

Cryptographically Secure PowerShell Method

For the highest security, use System.Security.Cryptography.RandomNumberGenerator:

function New-SecurePassword {
    param([int]$Length = 20)

    $charSet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*'
    $bytes = New-Object byte[] $Length
    $rng = [System.Security.Cryptography.RandomNumberGenerator]::Create()
    $rng.GetBytes($bytes)

    $password = New-Object char[] $Length
    for ($i = 0; $i -lt $Length; $i++) {
        $password[$i] = $charSet[$bytes[$i] % $charSet.Length]
    }

    return -join $password
}

New-SecurePassword -Length 24

.NET Cryptographic Password Generation

In .NET, RandomNumberGenerator (which replaced the older RNGCryptoServiceProvider) is the correct way to generate cryptographically secure random data:

using System.Security.Cryptography;

public static string GeneratePassword(int length = 20)
{
    const string chars =
        "abcdefghijklmnopqrstuvwxyz" +
        "ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
        "0123456789" +
        "!@#$%^&*()-_=+[]{}|;:,.<>?";

    var password = new char[length];
    var randomBytes = new byte[length];

    using (var rng = RandomNumberGenerator.Create())
    {
        rng.GetBytes(randomBytes);
    }

    for (int i = 0; i < length; i++)
    {
        password[i] = chars[randomBytes[i] % chars.Length];
    }

    return new string(password);
}

Why Not System.Random?

Never use System.Random for password generation:

// DO NOT use this for passwords -- it is predictable!
var random = new Random();
// An attacker who knows the seed can predict every output

System.Random uses a deterministic pseudo-random number generator. If an attacker can guess or determine the seed (for example, the system time at initialization), they can reproduce the entire sequence. RandomNumberGenerator uses the operating system’s cryptographic random source, which is suitable for security-sensitive operations.

Linux Command-Line Methods

Using openssl

# Generate a 24-character random password (base64 encoded)
openssl rand -base64 24

# Generate a hex-encoded password
openssl rand -hex 16

Using pwgen

The pwgen utility generates pronounceable (or fully random) passwords:

# Install pwgen
sudo apt install pwgen    # Debian/Ubuntu
sudo yum install pwgen    # RHEL/CentOS

# Generate one 16-character secure password
pwgen -s 16 1

# Generate 20 passwords of 20 characters each, fully random
pwgen -s -y 20 20

# Options:
#   -s  Fully random (not pronounceable)
#   -y  Include special characters
#   -c  Include at least one capital letter (default)
#   -n  Include at least one number (default)

Using /dev/urandom

# Generate a 20-character alphanumeric password
< /dev/urandom tr -dc 'A-Za-z0-9!@#$%^&*' | head -c 20; echo

# Generate multiple passwords
for i in $(seq 1 10); do
    < /dev/urandom tr -dc 'A-Za-z0-9!@#$%^&*()-_=+' | head -c 20
    echo
done

Using Python

# One-liner for a 20-character password
python3 -c "import secrets, string; print(''.join(secrets.choice(string.ascii_letters + string.digits + string.punctuation) for _ in range(20)))"

The secrets module in Python 3.6+ is specifically designed for generating cryptographically secure tokens and passwords.

Bulk Password Generation for User Provisioning

When provisioning multiple accounts, you can combine password generation with CSV output:

PowerShell: Generate Passwords for a User List

# Read a list of usernames and generate passwords
$users = Import-Csv -Path "C:\users.csv"

$results = foreach ($user in $users) {
    [PSCustomObject]@{
        Username = $user.Username
        Password = [System.Web.Security.Membership]::GeneratePassword(16, 4)
    }
}

$results | Export-Csv -Path "C:\user-passwords.csv" -NoTypeInformation

Bash: Generate Passwords from a User List

#!/bin/bash
while IFS= read -r username; do
    password=$(< /dev/urandom tr -dc 'A-Za-z0-9!@#$%^&*' | head -c 16)
    echo "$username,$password"
done < users.txt > user-passwords.csv

Secure Password Storage Practices

Generating strong passwords is only half the battle. Storing them securely is equally important.

For User Authentication (Hashing)

Never store user passwords in plain text. Use a one-way hashing algorithm with a unique salt:

  • bcrypt — The most widely recommended algorithm for password hashing. Includes built-in salting and a configurable work factor.
  • scrypt — Memory-hard algorithm that resists GPU-based attacks.
  • Argon2 — Winner of the Password Hashing Competition. Offers the best resistance to modern attacks.

Avoid MD5 and SHA-1/SHA-256 for password hashing — they are too fast, which makes brute-force attacks feasible.

For Application Secrets (Secrets Management)

For passwords used by applications (database credentials, API keys, service account passwords):

  • Azure Key Vault — Managed secrets store for Azure environments
  • AWS Secrets Manager — Managed secrets store with automatic rotation support
  • HashiCorp Vault — Open-source secrets management for any environment
  • Environment variables — Acceptable for development, but use a secrets manager in production

Never store secrets in:

  • Source code repositories
  • Configuration files checked into version control
  • Unencrypted text files on servers
  • Shared documents or wikis

Password Manager for Personal Use

For managing individual passwords, use a password manager:

  • Bitwarden — Open-source, cross-platform
  • 1Password — Feature-rich, with team and family plans
  • KeePass — Offline, open-source

Summary

Generating secure random passwords requires using cryptographically secure random number generators — whether through PowerShell’s Membership class, .NET’s RandomNumberGenerator, or Linux tools like openssl and pwgen. Avoid predictable sources like System.Random or simple keyboard mashing. For bulk provisioning, script the generation process and export to a secure format. Always store passwords using proper hashing algorithms for authentication or a secrets manager for application credentials.