Powershell GUI to encrypt string

written by Tomas Johansson
21 · 03 · 09

I’ve often found myself with tasks eligible for automation. Automating is great with PowerShell until you need to pass credentials into a script.

I have seen many administrators put passwords into the body of their script. For testing purposes, this could considered a forgivable offense. In production scripts, putting your passwords in plain view is not only a bad thing…it’s a terrifying thing. It should be a cardinal sin. But you can secure a password with PowerShell (or at least reduce password visibility).

I use MDT to deploy windows servers and clients and o often need to have some credentials and password to install  or create a service. I have start tu use use ConvertTo-SecureString and ConvertFrom-SecureString with a Key.

Powershell will use Windows Data Protection API (DPAPI) to encrypt/decrypt your strings. This means that it will only work for the same user on the same computer.

When you use a Key/SecureKey, the Advanced Encryption Standard (AES –wiki link) encryption algorithm is used. You are able to use the stored credential from any machine with any user so long as you know the AES Key that was used. AES encryption only supports 128-bit (16 bytes), 192-bit (24 bytes) or 256-bit key (32 bytes) lengths.

For example my MDTKey: 38,230,188,167,44,99,91,228,216,236,174,130,166,233,239,22

And String to encrypt is SuperSecretP@ssw0rd and that creates a new string that looks like this:

76492d1116743f0423413b16050a5345MgB8AEIAeQA4AHkARwBxAFUAdwBnAHcATABlAGIAOQA5ADUAeQBXAEEATgByAGcAPQA9AHwANABlADYAYgBkADUAYQBkAGIAMgBjADkAMgA2AGUANgBjADgAMgAyADgAMABjAGQAMgBhAGQAOQA1ADYANgBlADAANAAyAGQANgBmADMANQA3ADEAOAAwADcANwBkADgAMAA3ADUAZgA0ADcANQBiADEANwBhADAAOQAyADIANgA2ADUAMwA3ADYANQA3ADkAMQA0AGQANQA1AGMAMwA0AGEANQAyAGUAMwAxAGYANQA0ADEANgA1ADgAMQBkAGYA

This going to work an any  installation that use same key and encrypted string.

GUI for Encode String with Key

<#
Solution: Microsoft Deployment Toolkit
 Purpose: Encrypt Text GUI
 Version: 1.0.0
    Date: 08 March 2021

  Author: Tomas Johansson
 Twitter: @deploymentnoob
     Web: https://www.4thcorner.net

This script is provided "AS IS" with no warranties, confers no rights and 
is not supported by the author
#>

#Add WPF and Windows Forms assemblies
try {
    Add-Type -AssemblyName PresentationCore
    Add-Type -AssemblyName PresentationFramework
    Add-Type -AssemblyName system.windows.forms
}
catch {
    Throw "Failed to load Windows Presentation Framework assemblies."
}

# Export Dialog
[xml]$XAML = @'
<Window
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Encrypt Text" Height="475" Width="500" Topmost="True" ResizeMode="NoResize">
    <Grid>
        <Label x:Name="Labeltext" Content="Text to Encrypt:" HorizontalAlignment="Left" Margin="20,15,0,0" VerticalAlignment="Top" Width="198"/>
        <TextBox Name="TextBox_Clear" HorizontalAlignment="Left" Margin="20,40,0,0" Text="" TextWrapping="Wrap" VerticalAlignment="Top" Width="450" Height="24" Opacity="1"/>
        <Label Name="LabelKey" Content="Key to use for obfuscate text (Leave Empty to create new Key):" HorizontalAlignment="Left" Margin="20,70,0,0" VerticalAlignment="Top"/>
        <TextBox Name="TextBox_key" HorizontalAlignment="Left" Margin="20,95,0,0" Text="" TextWrapping="NoWrap" VerticalAlignment="Top" Width="450" Height="24" />
        <GroupBox Name="GroupBox_keylength" Header="Key Length" Margin="20,130,0,0" HorizontalAlignment="Left" VerticalAlignment="Top" VerticalContentAlignment="Center">
            <Grid Height="Auto" Margin="20,20,0,0">
                <Grid.RowDefinitions>
                    <RowDefinition Height="8*"/>
                    <RowDefinition Height="8*"/>
                </Grid.RowDefinitions>
                <RadioButton Name="RadioButton16" Content="16" HorizontalAlignment="Left" VerticalAlignment="Center" Padding="0" Margin="-19,-11,0,5"/>
                <RadioButton Name="RadioButton24" Content="24" HorizontalAlignment="Left" Margin="22,-10,0,5" VerticalAlignment="Center" Padding="0"/>
                <RadioButton Name="RadioButton32" Content="32" HorizontalAlignment="Left" Margin="65,-10,0,5" VerticalAlignment="Center" Padding="0,0,5,0"/>
            </Grid>
        </GroupBox>
        <TextBox Name="Textbox_Obfuscated" HorizontalAlignment="Left" Margin="20,197,0,0" Text="" TextWrapping="Wrap" VerticalAlignment="Top" Width="450" Height="181"/>
        <Button Name="Button_obfuscate" Content="Encrypt" HorizontalAlignment="Left" Margin="300,395,0,0" VerticalAlignment="Top" Width="75" Height="20"/>
        <Button Name="Button_cancel" Content="Cancel" HorizontalAlignment="Left" Margin="395,395,0,0" VerticalAlignment="Top" Width="75" Height="20"/>
    </Grid>
</Window>
'@

# Create Hashtable and Runspace for GUI
$syncHash = [hashtable]::Synchronized(@{})
$NewRunspace =[runspacefactory]::CreateRunspace()
$NewRunspace.ApartmentState = "STA"
$NewRunspace.ThreadOptions = "ReuseThread"         
$NewRunspace.Open()
$NewRunspace.SessionStateProxy.SetVariable("syncHash",$syncHash)      


# Create the XAML reader using a new XML node reader
$XAMLReader = New-Object System.Xml.XmlNodeReader $XAML
$syncHash.Window = [Windows.Markup.XamlReader]::Load($XAMLReader)
$XAML.SelectNodes("//*[@*[contains(translate(name(.),'n','N'),'Name')]]") | 
ForEach-Object {
    $syncHash.Add($_.Name,$syncHash.Window.FindName($_.Name))
}

Function New-ByteKey {
<#
.SYNOPSIS
    Create a Byte Array
.DESCRIPTION
    Create an New Byte Array
.PARAMETER Lenght
    Set key Lengt, Must be 16,24 or 32 (Maximal is 32)
.INPUTS
    Lenght : Interger
.OUTPUTS
    Key    : String
.EXAMPLE
    New-EncryptedString -PlainTextString "I am about to become encrypted!" -Key $Key
#>
    Param (
        [Parameter(Mandatory=$True,Position=0,ValueFromPipeLine=$true)]
        [ValidateSet("16","24","32")]
        [Alias("KeyLength")]
        [INT]$Length
    )
    BEGIN  {
        
    }
    PROCESS {
        $KeyByte = New-Object Byte[] $Length # You can use 16, 24, or 32 for AES
        [Security.Cryptography.RNGCryptoServiceProvider]::Create().GetBytes($KeyByte)
        $Key = $KeyByte -join ","
    }
    END {
        Return $Key
    }
}

Function New-EncryptedString {
<#
.SYNOPSIS
    Encrypt String with Secret Key
.DESCRIPTION
    Create an New String from input
.PARAMETER PlainTextString
    String to Encrypt
.PARAMETER Key
    Byte array
.INPUTS
    PlainTextString  : String
    Key              : Byte array
.OUTPUTS
    EncryptedString  : String
.EXAMPLE
    New-EncryptedString -PlainTextString "I am about to become encrypted!" -Key $Key
#>
    Param(
        [Parameter(Mandatory=$True,Position=0,ValueFromPipeLine=$true)]
        [Alias("String")]
        [String]$PlainTextString,
        [Parameter(Mandatory=$True,Position=1)]
        [Alias("Key")]
        [byte[]]$EncryptionKey
    )
    BEGIN {
    }
    PROCESS { 
        Try{
            $secureString = Convertto-SecureString $PlainTextString -AsPlainText -Force
            $EncryptedString = ConvertFrom-SecureString -SecureString $secureString -Key $EncryptionKey
        }
        Catch{
            $EncryptedString  = $null
        }
    }
    END {
        Return $EncryptedString
    }
}

# Click Encrypt buttton
$SyncHash.Button_obfuscate.add_Click({
    If ($SyncHash.RadioButton16.IsChecked) {
        $KeyLength = 16
    }
    ElseIf ($SyncHash.RadioButton24.IsChecked){
        $KeyLength = 24
    }
    ElseIf ($SyncHash.RadioButton32.IsChecked){
        $KeyLength = 32
    }
    Else {
        $KeyLength = $null
    }
    If (([string]::IsNullOrEmpty($syncHash.TextBox_key.Text))) {
        If ([string]::IsNullOrEmpty($KeyLength)) {
            [System.Windows.Forms.MessageBox]::Show("Key Length not Selected" , "Error")
        }
        Else {
            $NewKey = New-ByteKey $KeyLength
            $Key = $NewKey.Split(",")
        }
    }
    Else {
        $Key = ($syncHash.TextBox_key.Text).Split(",")

    }

    $TextString = $syncHash.TextBox_Clear.Text
    
    $Retval = New-EncryptedString -PlainTextString $TextString -EncryptionKey $Key

    $syncHash.Window.Dispatcher.Invoke(
        [action]{
        $SyncHash.RadioButton16.IsChecked = $false
        $SyncHash.RadioButton24.IsChecked = $false
        $SyncHash.RadioButton32.IsChecked = $false
        $SyncHash.Textbox_Obfuscated.Text = $Retval
        $SyncHash.TextBox_key.Text = $Key -join ","
        }
    )


})

# Textbox Key have key disable groupbox for selecting byte length
$syncHash.textBox_key.Add_TextChanged({
    If (!([string]::IsNullOrEmpty($syncHash.TextBox_key.Text))) {
        $syncHash.GroupBox_keylength.IsEnabled = $false
        $KeyLength = $null
    }
    Else {
        $syncHash.GroupBox_keylength.IsEnabled = $true
    }
})

# Close dialog when pressing Escape key
$objForm = New-Object System.Windows.Forms.Form 
$objForm.KeyPreview = $True

$objForm.Add_KeyDown({
    If ($_.KeyCode -eq "Escape") {
        $objForm.Close()
    }
})

# Close dialog window
$syncHash.button_cancel.add_click({
    $syncHash.Window.Close() 
})

# Launch the window
$syncHash.Window.WindowStartupLocation="CenterScreen"
$syncHash.Window.Add_Loaded( {
    $this.TopMost = $true
})
# Show the window
$syncHash.Window.ShowDialog() | out-null

Link to repository on github

Author

Tomas Johansson

I have worked in IT for more than 25 years, as a consultant, system administrator and technician. As a consultant, I have worked with system integration and development. I have also managed Windows client deployment for Swedish Armed Forces. Has a broad experience of most things in IT and still has a burning interest in learning new technologies and how to best use the technology.

Related Posts

Copy files to and from Hyper-V Guest

Using the PowerShell cmdlet Copy-VMFile To copy files to a VM using the Copy-VMFile cmdlet, we first have to enable Guest Services under Integration Services for a VM. Luckily, there is a PowerShell one-liner for...

Create NetNat Switch for Hyper-V

 In the latest versions in the Windows 10 client operating system, Microsoft already includes a “Default Virtual Switch”, which allows you to use Hyper-V NAT Networking, without doing any configuration changes. If you want to create an additional VM Switch which uses...

Hyper-V GUI in Powershell

A small powershell script that i make to test powershell script with gui. In this gui a can see all my hyper-v guest i have. I can start/stop, connect and delete machines in this...

Copy files to and from Hyper-V Guest

Using the PowerShell cmdlet Copy-VMFile To copy files to a VM using the Copy-VMFile cmdlet, we first have to enable Guest Services under Integration Services for a VM. Luckily, there is a PowerShell one-liner for...

Create NetNat Switch for Hyper-V

 In the latest versions in the Windows 10 client operating system, Microsoft already includes a “Default Virtual Switch”, which allows you to use Hyper-V NAT Networking, without doing any configuration changes. If you want to create an additional VM Switch which uses...

Hyper-V GUI in Powershell

A small powershell script that i make to test powershell script with gui. In this gui a can see all my hyper-v guest i have. I can start/stop, connect and delete machines in this...

Swedish keyboard in Windows PE

I always had trouble getting Swedish keyboard in Windows PE. Searched the web and found that you should use the following in Bootstrap.ini. S2V5Ym9hcmRMb2NhbGVQRT0wNDFkOjAwMDAwNDFk

Comments

0 Comments

Submit a Comment

Your email address will not be published. Required fields are marked *

Follow Us