使用 PowerShell 快速建立安全密碼的幾種方法 (密碼產生器) | The Will Will Web

The Will Will Web

記載著 Will 在網路世界的學習心得與技術分享

使用 PowerShell 快速建立安全密碼的幾種方法 (密碼產生器)

最近看到有人在影片中利用 PowerShell 產生亂數密碼,但是為了簡單產生個密碼,都要打長長的命令也不太實用了吧。所以我打算整理幾個密碼產生器的 PS1 函式,並加入到 $PROFILE 設定檔中,如此一來,日後產生密碼就方便多了! 👍

使用自訂字元亂數產生密碼

  • 單行命令

    ("!@#$%^&*0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz".ToCharArray() | sort {Get-Random})[0..8] -join ''
    
  • 自訂函式

    function New-RandomPassword {
        param(
            [Parameter()]
            [int]$MinimumPasswordLength = 8,
            [Parameter()]
            [int]$MaximumPasswordLength = 12,
            [Parameter()]
            [switch]$ConvertToSecureString
        )
        $length = Get-Random -Minimum $MinimumPasswordLength -Maximum $MaximumPasswordLength
        $password = ("!@#$%^&*0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz".ToCharArray() | sort {Get-Random})[0..$length] -join ''
        if ($ConvertToSecureString.IsPresent) {
            ConvertTo-SecureString -String $password -AsPlainText -Force
        } else {
            $password
        }
    }
    
  • 使用方式

    產生長度 8 ~ 12 字元的密碼

    New-RandomPassword
    

    產生長度 8 ~ 12 字元的密碼,並使用 ConvertTo-SecureString 轉成一組安全字串(SecureString)

    New-RandomPassword -MinimumPasswordLength 10 -MaximumPasswordLength 15 -ConvertToSecureString
    
  • 基本限制

    簡單、易用、跨平台,唯一缺點是 亂數強度 比較沒那麼高,但應該大部分的使用情境下應該都沒問題,當成個人密碼已經綽綽有餘。

  • 參考資料

使用 System.Web.Security.Membership 靜態類別來建立密碼

  • 單行命令

    Add-Type -AssemblyName 'System.Web'; [System.Web.Security.Membership]::GeneratePassword(12, 3)
    
  • 自訂函式

    function GeneratePassword {
        param(
            [Parameter()]
            [int]$MinimumPasswordLength = 8,
            [Parameter()]
            [int]$MaximumPasswordLength = 12,
            [Parameter()]
            [int]$NumberOfAlphaNumericCharacters = 5,
            [Parameter()]
            [switch]$ConvertToSecureString
        )
    
        Add-Type -AssemblyName 'System.Web'
        $length = Get-Random -Minimum $MinimumPasswordLength -Maximum $MaximumPasswordLength
        $password = [System.Web.Security.Membership]::GeneratePassword($length,$NumberOfAlphaNumericCharacters)
        if ($ConvertToSecureString.IsPresent) {
            ConvertTo-SecureString -String $password -AsPlainText -Force
        } else {
            $password
        }
    }
    
  • 使用方式

    產生長度 8 ~ 12 字元的密碼,其所產生密碼中的非英數字元數下限預設為 5 碼 (例如 @、#、!、%、& 等等)。

    GeneratePassword
    

    產生長度 8 ~ 12 字元的密碼,其所產生密碼中的非英數字元數下限為 6 碼 (例如 @、#、!、%、& 等等)。

    GeneratePassword -NumberOfAlphaNumericCharacters 6
    

    產生長度 10 ~ 15 字元的密碼,並使用 ConvertTo-SecureString 轉成一組安全字串(SecureString)

    GeneratePassword -MinimumPasswordLength 10 -MaximumPasswordLength 15 -ConvertToSecureString
    
  • 基本限制

    簡單、易用、亂數強度高,唯一缺點是僅限 Windows 可用,而且不支援PowerShell Core (pwsh.exe) 環境,因為 System.Web 只有 Windows 平台的 .NET Framework 才有。

  • 參考資料

批次產生多組密碼

  • 自訂函式

    function New-Password {
        <#
        .SYNOPSIS
            Generate a random password.
        .DESCRIPTION
            Generate a random password.
        .NOTES
            Change log:
                27/11/2017 - faustonascimento - Swapped Get-Random for System.Random.
                                                Swapped Sort-Object for Fisher-Yates shuffle.
                17/03/2017 - Chris Dent - Created.
        #>
    
        [CmdletBinding()]
        [OutputType([String])]
        param (
            # The length of the password which should be created.
            [Parameter(ValueFromPipeline)]
            [ValidateRange(8, 255)]
            [Int32]$Length = 10,
    
            # The character sets the password may contain. A password will contain at least one of each of the characters.
            [String[]]$CharacterSet = ('abcdefghijklmnopqrstuvwxyz',
                                      'ABCDEFGHIJKLMNOPQRSTUVWXYZ',
                                      '0123456789',
                                      '!$%&^.#;'),
    
            # The number of characters to select from each character set.
            [Int32[]]$CharacterSetCount = (@(1) * $CharacterSet.Count),
            [Parameter()]
            [switch]$ConvertToSecureString
        )
    
        begin {
            $bytes = [Byte[]]::new(4)
            $rng = [System.Security.Cryptography.RandomNumberGenerator]::Create()
            $rng.GetBytes($bytes)
    
            $seed = [System.BitConverter]::ToInt32($bytes, 0)
            $rnd = [Random]::new($seed)
    
            if ($CharacterSet.Count -ne $CharacterSetCount.Count) {
                throw "The number of items in -CharacterSet needs to match the number of items in -CharacterSetCount"
            }
    
            $allCharacterSets = [String]::Concat($CharacterSet)
        }
    
        process {
            try {
                $requiredCharLength = 0
                foreach ($i in $CharacterSetCount) {
                    $requiredCharLength += $i
                }
    
                if ($requiredCharLength -gt $Length) {
                    throw "The sum of characters specified by CharacterSetCount is higher than the desired password length"
                }
    
                $password = [Char[]]::new($Length)
                $index = 0
    
                for ($i = 0; $i -lt $CharacterSet.Count; $i++) {
                    for ($j = 0; $j -lt $CharacterSetCount[$i]; $j++) {
                        $password[$index++] = $CharacterSet[$i][$rnd.Next($CharacterSet[$i].Length)]
                    }
                }
    
                for ($i = $index; $i -lt $Length; $i++) {
                    $password[$index++] = $allCharacterSets[$rnd.Next($allCharacterSets.Length)]
                }
    
                # Fisher-Yates shuffle
                for ($i = $Length; $i -gt 0; $i--) {
                    $n = $i - 1
                    $m = $rnd.Next($i)
                    $j = $password[$m]
                    $password[$m] = $password[$n]
                    $password[$n] = $j
                }
    
                $password = [String]::new($password)
                if ($ConvertToSecureString.IsPresent) {
                    ConvertTo-SecureString -String $password -AsPlainText -Force
                } else {
                    $password
                }
            } catch {
                Write-Error -ErrorRecord $_
            }
        }
    }
    
  • 使用方式

    產生長度 10 字元的密碼 (預設長度為 10 個字元)

    New-Password
    

    產生長度 12 字元的密碼

    New-Password -Length 12
    

    產生長度 12 個字元的密碼,但指定 2 個小寫字母、3 個大寫字母、5 個數字、2 個特殊符號

    New-Password -Length 12 -CharacterSetCount 2,3,5,2
    

    產生長度 15 字元的密碼,並使用 ConvertTo-SecureString 轉成一組安全字串(SecureString)

    New-Password -Length 15 -ConvertToSecureString
    

    產生 20 組長度 12 個字元的密碼

    @(12) * 20 | New-Password
    
  • 基本限制

    簡單、易用、跨平台、多功能,唯一缺點是不能產生變動長度的密碼

  • 參考資料

相關連結