The XOR Cipher in PowerShell

DISCLAIMER: This is presented for educational purposes only. It is not intended for use as production cryptography. The example here is not secure and is vulnerable to multiple attacks.

Inspired by my son’s recent interest in ciphers, I decided to write a basic XOR cipher in PowerShell. Given your plaintext and key, the script returns the ciphertext.

What does it do?
The plaintext and the key are strings. If the key is shorter then the plaintext, then we repeat the key until it’s as long as the plaintext. A string is made up of bytes. And bytes are made up bits. For each bit in the plaintext, we do an Exclusive Or (XOR) Operation with the coresponding bit in the repeated key. The result is stored in the ciphertext.

What is Exclusive Or?

Exclusive Or is an operation that outputs TRUE when the inputs differ.
For example:

Plaintext  01010000
Key        01101011
Ciphertext 00111011

A nice feature of XOR is that it is easly reversable. If we XOR the key with the ciphertext, we get the plaintext back.

The code:

function encode($plaintext, $key)
    $cyphertext = ""
    $keyposition = 0
    $KeyArray = $key.ToCharArray()
    $plaintext.ToCharArray() | foreach-object -process {
        $cyphertext += [char]([byte][char]$_ -bxor $KeyArray[$keyposition])
        $keyposition += 1
        if ($keyposition -eq $key.Length) {$keyposition = 0}
    return $cyphertext

PowerShell Hex Functions

I wrote some basic functions to convert a string to hexadecimal, to convert hexadecimal to a string. Also a function to dump a string to it’s component bytes, listing on each line, the character, it’s ASCII code in hexadecimal, and ASCII code in decimal. Example output:

PS C:\> StringToHex "This is an example!@#"
PS C:\> HexToString "4861726B212053686F77206D6520616E206578616D706C653F3F"
Hark! Show me an example??
PS C:\> HexDump "So how is this?"
S 0x53 83
o 0x6F 111
  0x20 32
h 0x68 104
o 0x6F 111
w 0x77 119
  0x20 32
i 0x69 105
s 0x73 115
  0x20 32
t 0x74 116
h 0x68 104
i 0x69 105
s 0x73 115
? 0x3F 63

The code. They are basic functions, not Advanced Functions, so nothing fancy.

function StringToHex($i) {
    $r = ""
    $i.ToCharArray() | foreach-object -process {
        $r += '{0:X}' -f [int][char]$_
    return $r

function HexToString($i) {
    $r = ""
    for ($n = 0; $n -lt $i.Length; $n += 2)
        {$r += [char][int]("0x" + $i.Substring($n,2))}
    return $r

function HexDump($i) {
    $i.ToCharArray() | foreach-object -process {
        $num = [int][char]$_
        $hex = "0x" + ('{0:X}' -f $num)
        "$_ $hex $num"

PowerShell function to calculate data transfer time

This PowerShell function will calculate how long it will take to transfer a given number of bytes at a given speed (in bits per second). Optionally, you can specify transfer overhead, which defaults to ten percent.

Example Usage

PS C:\> Get-TransferTime -FileSize 4.4gb -Speed 2mb

Days         : 0
Hours        : 5
Minutes      : 0
Seconds      : 22
TotalDays    : 0.208587962962963
TotalHours   : 5.00611111111111
TotalMinutes : 300.366666666667
TotalSeconds : 18022

The Function

Data transfer time calculation.
Calculate how long it would take to transfer a given number of bytes at a given speed.
File Size in bytes. Can specify with GB, MB, etc.
Transfer speed in bits. Can specify with GB, MB, etc.
.PARAMETER OverheadPercent
Transfer overhead percent. Defaults to 10.
Get-TransferTime -FileSize 4.4gb -Speed 2mb
Get-TransferTime -FileSize 50mb -Speed 10mb -OverheadPercent 6
Ken Bradley, 2015-12-10
function Get-TransferTime
        [double]$FileSize, # bytes, can specify GB, MB, etc

        #Speed help!
        [double]$Speed, # bits, can specify GB, MB, etc


    # Scale percent so 100% = 1.0
    $ScaledPercent = 1 + ($OverheadPercent / 100)
    # Calculate seconds
    $Result = ($FileSize * 8 * $ScaledPercent) / $Speed

    # Output the result nicely formated
    New-TimeSpan -Seconds $Result | Format-List -Property Days, Hours, Minutes, Seconds, TotalDays, TotalHours, TotalMinutes, TotalSeconds

[EDIT: Previously, there was an error with OverheadPercent being excluded from the calculation. It has been added back. Thanks to JG for catching this.]

How to output objects from your own PowerShell functions

This example of PowerShell code shows how to output objects from your own functions. The basic tasks you do to accomplish this in your function are:

  1. Assemble the values into a hash table
  2. Create an object using that hash table
  3. Output the object

Once you do this, then you can treat your output as you would any other object in PowerShell.

  1. Assemble the values into a hash table
    • See my example below, it is the lines like $Properties =  @{…}
    • More info at about_Splatting
  2. Create an object using that hash table
    • See my example, the line starting with $Object = New-Object…
  3. Output the object
    • Simply Write-Output $Object
# Example Function
function Get-SystemInfo {

    # Prepare the info
    $OS = Get-CimInstance -ClassName Win32_OperatingSystem # for FreePhysicalMemory, Caption, PSComputerName, SystemDrive
    $LoadPercentage = (Get-CimInstance -ClassName Win32_Processor).LoadPercentage
    $ProcessCount = (Get-Process).Count
    $SystemDrive = Get-CimInstance -ClassName Win32_LogicalDisk -filter "Name = '$($OS.SystemDrive)'" 
    $ComputerSystem = Get-CimInstance -ClassName Win32_ComputerSystem

    # Prepare the properties in a hash table
    $Properties = @{
        ComputerName = $ComputerSystem.DNSHostName;
        Domain = $ComputerSystem.Domain;
        FreePhysicalMemory = "{0:n0}" -f ($OS.FreePhysicalMemory /1KB) + " MB";
        OS = $OS.Caption;
        LastBootUpTime = $OS.LastBootUpTime;
        LoadPercentage = $LoadPercentage;
        ProcessCount = $ProcessCount;
        SysVolFree = "{0:n1}" -f ($SystemDrive.FreeSpace /1GB) + " GB"
    # Create an object using the properties
    $Object = New-Object -TypeName PSObject -Property $Properties

    # Output the object
    Write-Output $Object     

# Example Usage

# Using the results, put them into an object "$Result"
$Result = Get-SystemInfo

# Access the values inside the object

Exploring COM with PowerShell

What is COM?

I hope to explain how to use COM object in PowerShell. A COM object is an interface into an application or Windows. For example the Excel COM object will allow you to work with an Excel spreadsheet, or the iTunes COM object will allow you to control iTunes via PowerShell. It’s not always pretty, or easy. If you have a built-in PowerShell command, use it. (For example Export-Csv is easier then using Excel to work with CSV.)

Getting Started

Maybe you don’t know the exact name of the COM object you want to use? Sometimes a quick web search will uncover it. If not, this bit of PowerShell code will list the COM objects available on your machine.

Get-ChildItem HKLM:\Software\Classes -ErrorAction SilentlyContinue | Where-Object { $_.PSChildName -match '^\w+\.\w+$' -and (Test-Path -Path "$($_.PSPath)\CLSID") } | Select-Object -ExpandProperty PSChildName

(via PowerShell Magazine)

The list may take a few minutes. I see “iTunes.Application” in there. That’s what I want.

Using the COM Object

I tell PowerShell to create a new object:

$Itunes = New-Object  -ComObject iTunes.Application

To see what we can do with this object, execute the above then type this PowerShell command (gm is the alias for Get-Member):

$Itunes | gm

This tells me the methods and properties supported by this COM object. Browsing through this will reveal more details, if you need it. “$itunes.LibraryPlaylist.Tracks” is all the tracks. And

$itunes.LibraryPlaylist.Tracks[1] | gm

shows you the methods and properties relating to tracks. (I use the “[1]” to make the listing faster. Since tracks is an array of all the tracks in iTunes, this could take a long time to list all the methods and properties, if you have many tracks. Since all tracks have the same member names (like Artist, Year, Name, etc), I’ll just list the members from the first track.)

So for example, if you wanted iTunes to play, you could do:


Or this little script goes through all your tracks and counts the artists in your collection:

$Itunes = New-Object  -ComObject iTunes.Application
# Get a list of artists from tracks
$Artist = @()
foreach ($Track in  $Itunes.LibraryPlaylist.Tracks)
    $Artist += $Track.Artist
# eliminate duplicates in the list
$artist = $artist | sort -Unique 
Write-Host "$($artist.count) artists found in your iTunes collection"

PowerShell script to generate a Rainmeter skin

I recently discovered Rainmeter, a desktop customization tool that lets you use some really nice looking gadgets. I wanted a simple skin to show disk free space.


I have five volumes, I could have manually written a custom skin. (Rainmeter skins are INI files.) That would involve setting a measure section for each disk and a in another section define how the output looks. Or I could take the much more time consuming task of writing a PowerShell script to iterate through my disks and write the skin INI file.

Download RainmeterDisksSkin.ZIP

The body of the script:

# Stop on the first error
$ErrorActionPreference = "Stop"

$RainmeterPath = [environment]::getfolderpath("mydocuments") + "\Rainmeter\Skins\"
$SkinName = "Kenward"
$FileName = "disks.ini"

If (-Not (Test-Path $($RainmeterPath + $SkinName))) {
    Set-Location $RainmeterPath
    mkdir $SkinName

$OutFile = $RainmeterPath + $SkinName + "\" + $FileName
$Disks = Get-Volume | where {$_.DriveType -eq "Fixed"} | sort -Property DriveLetter

$Header = @"

vFontName=Segoe UI Light

$MeterCommon = @"

Out-File -FilePath $Outfile -InputObject $Header

foreach ($Disk in $Disks) {
    Out-File -FilePath $Outfile -Append -InputObject "`n[MeasureFreeDiskSpace$($Disk.DriveLetter)]"
    Out-File -FilePath $Outfile -Append -InputObject "Measure=FreeDiskSpace"
    Out-File -FilePath $Outfile -Append -InputObject "Drive=$($Disk.DriveLetter):"
    Out-File -FilePath $Outfile -Append -InputObject "UpdateDivider=5"

Out-File -FilePath $Outfile -Append -InputObject $MeterCommon

for ($i = 0; $i -le $Disks.count - 1; $i++)
    if ($i -eq 0) {
        $Output = "MeasureName=MeasureFreeDiskSpace$($Disks[$i].DriveLetter)"
        $TextValue = "text = ""$($Disks[$i].DriveLetter) drive %1B free"
        else {
            $Output = "MeasureName$($i+1)=MeasureFreeDiskSpace$($Disks[$i].DriveLetter)"
            $TextValue += "#crlf#$($Disks[$i].DriveLetter) drive %$($i + 1)B free"
    Out-File -FilePath $Outfile -Append -InputObject $Output

Out-File -FilePath $Outfile -Append -InputObject $($TextValue + '"')

PowerShell and the Registry, a Quick Start

It’s very easy to access the registry in PowerShell. Usually you will want to read or write to the registry. These examples show how.

The registry key in these examples is “HKLM:\SOFTWARE\MyAwesomeKey“.

Suppose I wanted to read the data from a value called “Kenward”, into a variable. I would use this command:

$myvalue = (Get-ItemProperty -Path HKLM:\SOFTWARE\MyAwesomeKey).Kenward

Easy huh?

If you want to write to the registry, it’s also very easy, for example:

Set-ItemProperty -Path HKLM:\SOFTWARE\MyAwesomeKey -Name "Kenward" -Value "somevalue"

PowerShell is smart enough to know that you are writing a string to the registry, so that it automatically makes the value type a string (“REG_SZ”) in the registry.

If you write a number to the registry, like this:

Set-ItemProperty -Path HKLM:\SOFTWARE\MyAwesomeKey -Name "Meaning" -Value 42

It will make the value of type “REG_DWORD”, a 32 bit number.

If for some reason you need to force the value type to be a certain type, you can use the -type parameter of Set-ItemProperty to specify Binary, Dword, ExpandStrind, MultiString, None, Qword (64 bit number), String, or Unknown.

That’s it! Let me know if you have any questions.