PSaru.Security.psm1
Set-StrictMode -Version 'Latest' function Get-RandomPassword { [OutputType('String')] [OutputType('System.Security.SecureString')] [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Low')] param ( [int]$Length = 17, [string[]]$IncludeChars = @('~', '!', '@', '#', '$', '%', '^', '&', '*', '_', '-', '+', '=', '`', '|', '\', '(', ')', '{', '}', '[', ']', ':', '<', '>', ',', '.', '?', '/'), [string[]]$ExcludeChars = @(), [switch]$AsPlainText ) 65..90 | ForEach-Object { $IncludeChars += [char]$_ } 97..122 | ForEach-Object { $IncludeChars += [char]$_ } $IncludeChars = $IncludeChars | Where-Object {$_ -NotIn $ExcludeChars} [System.Security.SecureString]$SecurePassword = New-Object -TypeName 'System.Security.SecureString' $Randomness = Get-CryptoRandomByte -Length $Length -Minimum 0 -Maximum ($IncludeChars.Length - 1) 0..($Length - 1) | ForEach-Object { $SecurePassword.AppendChar( $IncludeChars[$Randomness[$_]]) } if ($AsPlainText.IsPresent) { $ret = ConvertTo-PlainText -SecureString $SecurePassword } else { $ret = $SecurePassword } $ret } function ConvertTo-PlainText { [OutputType('System.String')] [CmdletBinding()] param ( [Parameter(Mandatory = $true, ValueFromPipeline = $true)] [System.Security.SecureString]$SecureString ) PROCESS { $BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecureString) $PlainText = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR) $PlainText } } function Get-StringHash { [OutputType('System.String')] [CmdletBinding()] param ( [Parameter(Mandatory = $true, Position = 1, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [ValidatenotNullOrEmpty()] [string[]]$String, [Parameter(Position = 2, ValueFromPipelineByPropertyName = $true)] [ValidateSet('SHA1', 'SHA256', 'SHA384', 'SHA512', 'MACTripleDES', 'MD5', 'RIPEMD160')] [string]$Algorithm = 'SHA256', [Alias('Lower')] [switch]$LowerCase, [switch]$Group, [ValidateRange(1, 8)] [Int32]$GroupSize = 4, [ValidateNotNullOrEmpty()] [char]$GroupSepChar = '-' ) PROCESS { $String | ForEach-Object { try { $Bytes = [System.Text.Encoding]::UTF8.GetBytes($String) $Stream = New-Object -TypeName 'System.IO.MemoryStream' $Stream.Write($Bytes, 0, $Bytes.Length) $Stream.Seek(0, 'Begin') | Out-Null $Hash = Get-FileHash -InputStream $Stream -Algorithm $Algorithm $Stream.Close() $Stream.Dispose() [string]$Ret = $Hash.Hash; if ($LowerCase.IsPresent) { $Ret = $Ret.ToLower() } if ($Group.IsPresent) { $tmp = '' for ($i = 0; $i -lt ($Ret.Length - $GroupSize); $i += $GroupSize) { $tmp += $Ret.Substring($i, $GroupSize) $tmp += $GroupSepChar } $tmp += $Ret.Substring($i, $GroupSize) $Ret = $tmp } $Ret } finally { if ($Stream) { $Stream.Close() $Stream.Dispose() } } } } } function ConvertTo-ByteArray { [OutputType('System.Byte')] [CmdletBinding()] param ( [Parameter(Mandatory = $true, Position = 1, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)] [ValidatenotNullOrEmpty()] [string[]]$Value ) PROCESS { foreach ($HexString in $Value ) { if ($HexString -notmatch '^([0-9a-f][0-9a-f])+$') { if ($HexString.Length -gt 20) { $HexString = $HexString.Substring(0, 20) + '...' } throw "Invalid hex string '$HexString'" } for ($i = 0; $i -lt $HexString.Length; $i += 2) { [byte]::Parse($HexString.Substring($i, 2), [System.Globalization.NumberStyles]::HexNumber) } } } } function Get-CryptoRandomByte { [OutputType('System.Byte')] param ( [Parameter(Mandatory = $true)] [Int32]$Length, [Alias('Min')] [Byte]$Minimum = 0, [Alias('Max')] [Byte]$Maximum = 255 ) [System.Security.Cryptography.RNGCryptoServiceProvider]$RandomNumberGenerator = New-Object -TypeName 'System.Security.Cryptography.RNGCryptoServiceProvider' [Byte[]]$Bytes = New-Object -TypeName 'Byte[]' -ArgumentList 1024 $RandomNumberGenerator.GetBytes($Bytes) $Bytes | Where-Object {$_ -ge $Minimum -and $_ -le $Maximum} | Select-Object -First $Length } |