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