Math is hard.

But this is very cool! I like it a lot.

Just one comment – your current PowerShell process id is always in $pid. So:

               $PSWindow = ( Get-Process –pid $pid )

That allows you to have multiple PowerShell windows open at the same time when 
using your script.

From: [email protected] [mailto:[email protected]] On 
Behalf Of Sean Martin
Sent: Monday, February 8, 2016 1:48 PM
To: [email protected]
Subject: Re: [powershell] Random Password Generator

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]<mailto:[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]<mailto:[email protected]>> wrote:
Ok. Here is my final version, and I’ll probably blog about it. ☺ 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]> 
[mailto:[email protected]<mailto:[email protected]>] 
On Behalf Of Michael B. Smith
Sent: Friday, February 5, 2016 9:31 PM

To: [email protected]<mailto:[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]> 
[mailto:[email protected]] On Behalf Of Michael B. Smith
Sent: Friday, February 5, 2016 9:16 PM
To: [email protected]<mailto:[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]> 
[mailto:[email protected]] On Behalf Of Scott Crawford
Sent: Friday, February 5, 2016 8:31 PM
To: [email protected]<mailto:[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]> 
[mailto:[email protected]] On Behalf Of Michael B. Smith
Sent: Friday, February 5, 2016 7:07 PM
To: [email protected]<mailto:[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]> 
[mailto:[email protected]] On Behalf Of Michael B. Smith
Sent: Thursday, February 4, 2016 3:39 PM
To: [email protected]<mailto:[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]> 
[mailto:[email protected]] On Behalf Of Sean Martin
Sent: Thursday, February 4, 2016 10:44 AM
To: [email protected]<mailto:[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]<mailto:[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]> 
[mailto:[email protected]<mailto:[email protected]>] 
On Behalf Of Sean Martin
Sent: Wednesday, February 3, 2016 3:24 PM
To: [email protected]<mailto:[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

================================================
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