FWIW, our Information Security Engineer requested the use of
RNGCryptoServiceProvider because Get-Random uses the system clock as the
default seed, so in his opinion, deriving the generated string would be
relatively trivial. In his explanation, the resulting Base64 string using
RNGCryptoServiceProvider is longer than 15 characters, but the entropy is
coming from the original 15 bytes, which should put cracking beyond
nation-state capabilities...possibly. In the end, we've opted for a
combination of both methods to ensure complexity requirements are met.

==========

$randombytes = new-object byte[] 15
(new-object
System.Security.Cryptography.RNGCryptoServiceProvider).GetBytes($randombytes)
$pass = [System.Convert]::ToBase64String($randombytes)
$a = ([char[]](get-random -input (33..47) -count 2)) -join ""
$b = ([char[]](get-random -input (48..57) -count 2)) -join ""
$password = $a + $pass + $b

==========

As stated earlier, we use the above in an automated script that runs on a
routine basis to change passwords for disabled accounts. I used the same
technique to put together a quick random password generator for other use
cases. A handy little trick was incorporating an automatic copy to the
clipboard to make recording the password easier, and then emptying the
clipboard upon exit. Sticking with the "secure" theme, I wanted to prevent
the script from be stopped or exited prior to the clipboard being emptied,
so I incorporated the code from here: http://mymsworld.kahsky.com/?p=154 to
prevent the powershell window from being closed, and used Try/Finally
blocks to handle Ctrl+C input.

==========

#Calling user32.dll methods for Windows and Menus
$MethodsCall = '
[DllImport("user32.dll")] public static extern long GetSystemMenu(IntPtr
hWnd, bool bRevert);
[DllImport("user32.dll")] public static extern bool EnableMenuItem(long
hMenuItem, long wIDEnableItem, long wEnable);
[DllImport("user32.dll")] public static extern long SetWindowLongPtr(long
hWnd, long nIndex, long dwNewLong);
[DllImport("user32.dll")] public static extern bool EnableWindow(long hWnd,
int bEnable);
'

#Create a new namespace for the Methods to be able to call them
Add-Type -MemberDefinition $MethodsCall -name NativeMethods -namespace Win32

#WM_SYSCOMMAND Message
$MF_GRAYED = 0x00000001L    #Indicates that the menu item is disabled and
grayed so that it cannot be selected.
$MF_BYCOMMAND = 0x0               #Gives the identifier of the menu item.
If neither the MF_BYCOMMAND nor MF_BYPOSITION flag is specified, the
MF_BYCOMMAND flag is the default flag.
$MF_DISABLED = 0x00000002L #Indicates that the menu item is disabled, but
not grayed, so it cannot be selected.
$MF_ENABLED = 0x00000000L #Indicates that the menu item is enabled and
restored from a grayed state so that it can be selected.
#...
http://msdn.microsoft.com/en-us/library/windows/desktop/ms647636(v=vs.85).aspx

$SC_CLOSE = 0xF060
$SC_CONTEXTHELP = 0xF180
$SC_MAXIMIZE = 0xF030
$SC_MINIMIZE = 0xF020
$SC_TASKLIST = 0xF130
$SC_MOUSEMENU = 0xF090
$SC_KEYMENU = 0xF100
#...
http://msdn.microsoft.com/en-us/library/windows/desktop/ms646360(v=vs.85).aspx

$GWL_EXSTYLE = -20
$GWL_STYLE = -16
#...
http://msdn.microsoft.com/en-us/library/windows/desktop/ms644898(v=vs.85).aspx

#WM_SETICON Message  -
http://msdn.microsoft.com/en-us/library/ms632643%28VS.85%29.aspx
$WM_SETICON = 0x0080;
$ICON_SMALL = 0;
$ICON_BIG = 1;

#Extended Window Styles
$WS_EX_DLGMODALFRAME = 0x00000001L
$WS_EX_NOACTIVATE = 0x08000000L
$WS_EX_TOOLWINDOW = 0x00000080L
$WS_EX_STATICEDGE = 0x00020000L
$WS_EX_WINDOWEDGE = 0x00000100L
$WS_EX_TRANSPARENT = 0x00000020L
$WS_EX_CLIENTEDGE = 0x00000200L
$WS_EX_LAYERED = 0x00080000
$WS_EX_TOPMOST = 0x00000008L
#...
http://msdn.microsoft.com/en-us/library/windows/desktop/ff700543(v=vs.85).aspx

#Get window handle of Powershell process (Ensure there is only one
Powershell window opened)
$PSWindow = (Get-Process Powershell) | where {$_.MainWindowTitle -like
"*Powershell*"}
$hwnd = $PSWindow.MainWindowHandle

#Get System menu of windows handled
$hMenu = [Win32.NativeMethods]::GetSystemMenu($hwnd, 0)

#Window Style : TOOLWINDOW
[Win32.NativeMethods]::SetWindowLongPtr($hwnd, $GWL_EXSTYLE,
$WS_EX_TOOLWINDOW) | Out-Null

#Disable X Button and window itself
[Win32.NativeMethods]::EnableMenuItem($hMenu, $SC_CLOSE, $MF_DISABLED) |
Out-Null
[Win32.NativeMethods]::EnableWindow($hwnd, 0) | Out-Null

Try {
      [Console]::TreatControlCAsInput = $True

      # Header Information
      Write-Host "Random Password Generator" -ForeGroundColor Magenta
      Write-Host "Created on: 2/3/2016" -ForeGroundColor Magenta
      Write-Host "Author: Sean Martin" -ForeGroundColor Magenta
      Write-Host ""
      Write-Host "This script will generate a randomized 24 character
password that meets existing complexity requirements." -ForeGroundColor
Magenta
      Write-Host
"---------------------------------------------------------------------------------------------------------"
-ForeGroundColor Yellow

     # Generate Random Password
     $randombytes = new-object byte[] 15
     (new-object
System.Security.Cryptography.RNGCryptoServiceProvider).GetBytes($randombytes)
     $pass = [System.Convert]::ToBase64String($randombytes)
     $a = ([char[]](get-random -input (33..47) -count 2)) -join ""
     $b = ([char[]](get-random -input (48..57) -count 2)) -join ""
     $password = $a + $pass + $b
     $password | clip

    # Display Password
    Write-Host ""
    Write-Host "Your password is: " -ForeGroundColor Cyan
    Write-Host ""
    Write-Host "$Password" -ForeGroundColor Yellow
    Write-Host ""
    Write-Host "The password has been automatically copied to the clipboard
for your convenience."
    Write-Host "Please paste the password to a safe location as the
clipboard will be cleared upon exit."
    Write-Host ""
    Write-Host "The script exit automatically in 10 seconds"
-ForeGroundColor Cyan
    Start-sleep 10

   # Clear Clipboard
   $null | clip

} Finally {
  [Console]::TreatControlCAsInput = $False
}

#Enable X Button
[Win32.NativeMethods]::EnableMenuItem($hMenu, $SC_CLOSE, $MF_ENABLED) |
Out-Null
[Win32.NativeMethods]::EnableWindow($hwnd, 1) | Out-Null

Exit

==========

- Sean

On Mon, Feb 8, 2016 at 7:25 AM, Sean Martin <[email protected]> wrote:

> That is very cool. As much as I appreciate the mention, this is where I
> came up with the concept:
>
>
> https://gallery.technet.microsoft.com/scriptcenter/Simple-random-code-b2c9c9c9
>
> - Sean
>
> On Fri, Feb 5, 2016 at 5:58 PM, Michael B. Smith <[email protected]>
> wrote:
>
>> Ok. Here is my final version, and I’ll probably blog about it. J Great
>> stuff. I love these kinds of conversations!
>>
>>
>>
>> -----start-----
>>
>> ##
>>
>> ## Create-Password
>>
>> ##
>>
>> ## February 5, 2016
>>
>> ## michael at TheEssentialExchange dot com
>>
>> ##
>>
>> ## Based on an idea from Sean Martin
>>
>> ## seanmartin14 at gmail dot com
>>
>> ##
>>
>>
>>
>> Param(
>>
>>                [int] $Length = 20,
>>
>>                [bool] $AllPrintableAscii = $false
>>
>> )
>>
>>
>>
>>                function range
>>
>>                {
>>
>>                               Param(
>>
>>                                              [char] $start,
>>
>>                                              [char] $finish
>>
>>                               )
>>
>>
>>
>>                               [int]$start .. [int]$finish
>>
>>                }
>>
>>
>>
>>                ## ASCII table:
>>
>>                ##
>> https://en.wikipedia.org/wiki/ASCII#ASCII_printable_characters
>>
>>
>>
>>                ## I intentionally exclude <space>, since if a space
>> occurs as the first
>>
>>                ## or last character, most password input dialogs will
>> trim the <space>.
>>
>>
>>
>>                $password = ''
>>
>>                if( $AllPrintableAscii )
>>
>>                {
>>
>>                               $password = ( [char[]]( Get-Random
>> -InputObject ( 33..126 ) -Count 20 ) ) -Join ''
>>
>>                }
>>
>>                else
>>
>>                {
>>
>>                               $validChars =   ( range 'a' 'z' ) +
>>
>>                                                             ( range 'A'
>> 'Z' ) +
>>
>>                                                             ( range '0'
>> '9' ) +
>>
>>                                                             ( [char[]]
>> '!@#$%^&*()' )
>>
>>
>>
>>                               $password = ( [char[]]( Get-Random
>> -InputObject $validChars -Count 20 ) ) -Join ''
>>
>>                }
>>
>>
>>
>>                $password
>>
>> -----end-----
>>
>>
>>
>> *From:* [email protected] [mailto:
>> [email protected]] *On Behalf Of *Michael B. Smith
>> *Sent:* Friday, February 5, 2016 9:31 PM
>>
>> *To:* [email protected]
>> *Subject:* RE: [powershell] Random Password Generator
>>
>>
>>
>> Here is the medium easier-to-understand version:
>>
>>
>>
>> function range { param( [char]$start, [char]$finish ) [int]$start ..
>> [int]$finish }
>>
>>
>>
>> $validChars = ( range 'a' 'z' ) + ( range 'A' 'Z' ) + ( range '0' '9' ) +
>> ( [char[]] '!@#$%^&*()' )
>>
>>
>>
>> ( [char[]]( Get-Random -InputObject $validChars -Count 20 ) ) -Join ''
>>
>>
>>
>>
>>
>> *From:* [email protected] [
>> mailto:[email protected] <[email protected]>] *On
>> Behalf Of *Michael B. Smith
>> *Sent:* Friday, February 5, 2016 9:16 PM
>> *To:* [email protected]
>> *Subject:* RE: [powershell] Random Password Generator
>>
>>
>>
>> You can do that with this solution as well.
>>
>>
>>
>> Here is the long version:
>>
>>
>>
>> $upperCase = 65..90
>>
>> $lowerCase = 97..122
>>
>> $numbers   = 48..57
>>
>> $bang      = , ( [char] '!' )
>>
>> $splat     = , ( [char] '@' )
>>
>> $hash      = , ( [char] '#' )
>>
>> $dollar    = , ( [char] '$' )
>>
>> $percent   = , ( [char] '%' )
>>
>> $carat     = , ( [char] '^' )
>>
>> $amp       = , ( [char] '&' )
>>
>> $star      = , ( [char] '*' )
>>
>> $lparen    = , ( [char] '(' )
>>
>> $rparen    = , ( [char] ')' )
>>
>>
>>
>> $characters = $upperCase + $lowerCase + $numbers + $bang + $splat + $hash
>> + $dollar + $percent + $carat + $amp + $star + $lparen + $rparen
>>
>>
>>
>> ( [char[]]( Get-Random -InputObject $characters -Count 20 ) ) -Join ''
>>
>>
>>
>> Here is the short version:
>>
>>
>>
>> [char[]] $validChars = 65..90 + 97..122 + 48..57 + ( [char[]]
>> '!@#$%^&*()' )
>>
>> ( [char[]]( Get-Random -InputObject $validChars -Count 20 ) ) -Join ''
>>
>>
>>
>>
>>
>> *From:* [email protected] [
>> mailto:[email protected] <[email protected]>] *On
>> Behalf Of *Scott Crawford
>> *Sent:* Friday, February 5, 2016 8:31 PM
>> *To:* [email protected]
>> *Subject:* RE: [powershell] Random Password Generator
>>
>>
>>
>> That’s fantastic.
>>
>>
>>
>> This had been my solution and I do kinda like seeing the actual valid
>> characters cuz it makes it easy to edit out quotes or other possible
>> illegal values. But, it’s tough to beat the elegance of yours when valid
>> characters aren’t a concern.
>>
>>
>>
>> $Chars =
>> "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*()"
>>
>> $Rand = New-Object System.Random
>>
>> For ($i = 1; $i -le 20; $i++) {
>>
>>                 $Password = $Password + $Chars.Substring($Rand.Next(0,
>> $Chars.Length), 1)
>>
>> }
>>
>> $Password
>>
>>
>>
>> *From:* [email protected] [
>> mailto:[email protected] <[email protected]>] *On
>> Behalf Of *Michael B. Smith
>> *Sent:* Friday, February 5, 2016 7:07 PM
>> *To:* [email protected]
>> *Subject:* RE: [powershell] Random Password Generator
>>
>>
>>
>> Interestingly enough, you can take Get-Random and get an even better
>> random password. Take a look at this:
>>
>>
>>
>> ( [char[]]( Get-Random -Input ( 33..126 ) -Count 20 ) ) -Join ''
>>
>>
>>
>> Great solution using all of the printable ASCII characters (except for
>> the <space> character).
>>
>>
>>
>> *From:* [email protected] [
>> mailto:[email protected] <[email protected]>] *On
>> Behalf Of *Michael B. Smith
>> *Sent:* Thursday, February 4, 2016 3:39 PM
>> *To:* [email protected]
>> *Subject:* RE: [powershell] Random Password Generator
>>
>>
>>
>> That’s very nice. I never would have thought of that application of
>> Get-Random.
>>
>>
>>
>> *From:* [email protected] [
>> mailto:[email protected] <[email protected]>] *On
>> Behalf Of *Sean Martin
>> *Sent:* Thursday, February 4, 2016 10:44 AM
>> *To:* [email protected]
>> *Subject:* Re: [powershell] Random Password Generator
>>
>>
>>
>> You make a good point. How about this?
>>
>>
>>
>> $randombytes = new-object byte[] 15
>>  (new-object
>> System.Security.Cryptography.RNGCryptoServiceProvider).GetBytes($randombytes)
>>  $pass = [System.Convert]::ToBase64String($randombytes)
>>  $a = ([char[]](get-random -input (33..47 + 48..57) -count 4)) -join ""
>>  $password = $a + $pass
>>
>>
>>
>> - Sean
>>
>>
>>
>>
>>
>> On Wed, Feb 3, 2016 at 6:36 PM, Michael B. Smith <[email protected]>
>> wrote:
>>
>> The maximum entropy you get from Base64 is 2.58 bits per character, kinda
>> by definition( ln2( 6 ) ). Given that your maximum length is 15 digits,
>> that limits you to ~38 bits of entropy. At a thousand guesses a second,
>> that’s about 8 years to brute force. Not bad.
>>
>>
>>
>> However, you’ve GIVEN UP over 10 bits of entropy because of four constant
>> characters, taking you to about 28 bits of entropy. Believe it or not,
>> having constants makes a password far far easier to crack. (This is why the
>> revelation of a non-random non-prime in netcat/socat is such a big deal –
>> it makes Diffie-Helman much much simpler to crack.)
>>
>>
>>
>> That’s about 3 days to brute force.
>>
>>
>>
>> That is completely believable for someone to spend the time/energy to
>> crack. (And remember, the 3 days assumes that your password is the last one
>> checked, out of the entire “password universe” – on average, assume half
>> that.)
>>
>>
>>
>> So, the lesson here is that 15 bytes of base64 is fine (if impossible to
>> remember). But don’t use constants. Evah.
>>
>>
>>
>> *From:* [email protected] [mailto:
>> [email protected]] *On Behalf Of *Sean Martin
>> *Sent:* Wednesday, February 3, 2016 3:24 PM
>> *To:* [email protected]
>> *Subject:* [powershell] Random Password Generator
>>
>>
>>
>> I don't get the opportunity to contribute all that often so I thought I
>> would throw this out there in case it helps anyone.
>>
>>
>> I got the method from this article:
>> https://www.scriptjunkie.us/2013/09/secure-random-password-generation/
>>
>>
>>
>> I modify the resulting password by prepending/appending a couple of
>> special and numerical characters to ensure it meets complexity requirements
>> in my current environment.
>>
>>
>>
>> Easy way to generate a secure password whenever the need arises.
>> Critiques are always welcome.
>>
>>
>>
>> ===================================================================
>>
>>
>>
>> # Generate Random Password
>>
>>
>> $randombytes = new-object byte[] 15
>> (new-object
>> System.Security.Cryptography.RNGCryptoServiceProvider).GetBytes($randombytes)
>> $pass = [System.Convert]::ToBase64String($randombytes)
>> $password = "&#" + $pass + "82"
>>
>>
>> Write-Host ""
>> Write-Host "Your password is: " -ForeGroundColor Cyan -NoNewLine
>> Write-Host "$Password" -ForeGroundColor Yellow
>> Write-Host ""
>> Write-Host ""
>> Write-Host "Press enter to exit script..." -ForeGroundColor Cyan
>>
>>
>> $Pause = Read-Host
>>
>> Exit
>>
>>
>>
>> ==================================================================
>>
>>
>>
>> - Sean
>>
>>
>> ================================================
>> Did you know you can also post and find answers on PowerShell in the
>> forums?
>> http://www.myitforum.com/forums/default.asp?catApp=1
>>
>>
>> ================================================
>> Did you know you can also post and find answers on PowerShell in the
>> forums?
>> http://www.myitforum.com/forums/default.asp?catApp=1
>>
>>
>>
>>
>> ================================================
>> Did you know you can also post and find answers on PowerShell in the
>> forums?
>> http://www.myitforum.com/forums/default.asp?catApp=1
>>
>>
>> ================================================
>> Did you know you can also post and find answers on PowerShell in the
>> forums?
>> http://www.myitforum.com/forums/default.asp?catApp=1
>>
>>
>> ================================================
>> Did you know you can also post and find answers on PowerShell in the
>> forums?
>> http://www.myitforum.com/forums/default.asp?catApp=1
>>
>>
>> ================================================
>> Did you know you can also post and find answers on PowerShell in the
>> forums?
>> http://www.myitforum.com/forums/default.asp?catApp=1
>>
>>
>> ================================================
>> Did you know you can also post and find answers on PowerShell in the
>> forums?
>> http://www.myitforum.com/forums/default.asp?catApp=1
>>
>>
>> ================================================
>> Did you know you can also post and find answers on PowerShell in the
>> forums?
>> http://www.myitforum.com/forums/default.asp?catApp=1
>>
>> ================================================
>> Did you know you can also post and find answers on PowerShell in the
>> forums?
>> http://www.myitforum.com/forums/default.asp?catApp=1
>>
>
>
> ================================================
> Did you know you can also post and find answers on PowerShell in the
> forums?
> http://www.myitforum.com/forums/default.asp?catApp=1
>


================================================
Did you know you can also post and find answers on PowerShell in the forums?
http://www.myitforum.com/forums/default.asp?catApp=1

Reply via email to