Private/Crypto/New-PukCngRandomValue.ps1
|
function New-PukCngRandomValue { [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseShouldProcessForStateChangingFunctions', '', Justification = 'Pure in-memory computation (draws cryptographically random digits via CNG); changes no external or persistent state.')] [CmdletBinding()] [OutputType([string])] param( [Parameter(Mandatory)] [ValidateRange(1, [int]::MaxValue)] [int]$Length ) # Instance GetBytes() (not the static .NET 6+ GetInt32/Fill methods) so this runs # identically on Windows PowerShell 5.1 (.NET Framework) and PowerShell 7+ (.NET). # On Windows both call into CNG's BCryptGenRandom. $rng = [System.Security.Cryptography.RandomNumberGenerator]::Create() try { $digits = [System.Text.StringBuilder]::new($Length) $buffer = [byte[]]::new(1) while ($digits.Length -lt $Length) { $rng.GetBytes($buffer) $byteValue = $buffer[0] # 256 is not evenly divisible by 10; discard bytes >= 250 to avoid modulo bias. if ($byteValue -lt 250) { [void]$digits.Append([string]($byteValue % 10)) } } return $digits.ToString() } finally { $rng.Dispose() } } |