Skip to the main content.

Unlocking the Power of PowerShell: Tips for Success

Encoding vs encryption? Understand the difference and choose wisely!

Understanding encoding vs encryption is essential for robust data security. But what is the difference between encoding and encryption?

Encoding is primarily used to transmit data, while encryption protects data from unauthorized access. PowerShell provides tools for both – the key to success is choosing the right method for your scenario.

In the previous parts, we explored how SecureStrings are encrypted and decrypted and how to directly access the DPAPI (Data Protection API) to securely encrypt and decrypt secrets. However, DPAPI is available only on Windows operating systems, which is why SecureStrings are no longer considered "secure" on non-Windows platforms.

In this part, we’ll examine what happens to SecureStrings on non-Windows platforms and compare encoding vs encryption.

 

Understanding the difference of encoding vs encryption

Encryption requires a secret to decrypt, preventing unauthorized access. Encoding, on the other hand, does not require a secret and is simply a way to obfuscate (make unreadable) data or to store complex binary data in a robust string format. For this reason, encoding is typically used to embed binary data such as images, audio files, or DLLs within scripts. Surprisingly, sensitive data like SecureStrings are encoded (and not encrypted) on non-Windows platforms.

Encoding vs Encryption: Let us provide some use cases so the key differences will become obvious.

 

Built-in PowerShell decoding

You can encode any type of data, and the result is always a string. Here is an example of encoding a PowerShell script block:


$command = {
    Get-ChildItem -Path $env:windir -Recurse -Filter *.ps1 -File -ErrorAction Ignore
}

$bytes = [System.Text.Encoding]::Unicode.GetBytes($command)
$encodedCommand = [Convert]::ToBase64String($bytes)

$encodedCommand 

 

The result will look something like this:

DQAKACAAIAAgACAARwBlAHQALQBDAGgAaQBsAGQASQB0AGUAbQAgAC0AUABhAHQAaAAgACQAZQBuAHYAOgB3AGkAbgBkAGkAcgAgAC0AUgBlAGMAdQByAHMAZQAgAC0ARgBpAGwAdABlAHIAIAAqAC4AcABzADEAIAAtAEYAaQBsAGUAIAAtAEUAcgByAG8AcgBBAGMAdABpAG8AbgAgAEkAZwBuAG8AcgBlAA0ACgA= 

This string can then be decoded by anyone; no special secret is required. For example, PowerShell supports this type of encoding through its -EncodedCommand parameter, allowing you to run encoded code as follows:

pwsh -EncodedCommand screenshot SecureString deep dive

When you run this, PowerShell executes the original encoded script block and begins dumping all PowerShell scripts it can find in your Windows folder.

 

Image (binary) encoding

This example illustrates the typical use of encoding vs encryption: embedding binary or otherwise complex data within strings. Encoding is not intended to protect sensitive data, making it somewhat surprising that encoding and not encryption was chosen to "protect" SecureStrings on non-Windows platforms.

In the following example, a binary PNG image file is read and converted into an encoded string. This string is then inserted into a small HTML file so that whenever someone opens this file, the web browser displays the image – without needing to keep the binary image file.


# this is for PNG files. Change image type to GIF, JPG or some other image types
$ImageType = 'png'

# make sure this points to a real image file of the image type you defined above
$ImagePath = "C:\sample\picture.$ImageType"

# read image file as byte array
$imageBytes = Get-Content -Path $ImagePath -Encoding Byte -Raw

# convert bytes to encoded string
$encodedString = [Convert]::ToBase64String($ImageBytes)

# output string for inspection
$encodedString

# do something with the encoded string, i.e. embed it into HTML
$htmlPath = Join-Path -Path $env:temp -ChildPath 'testhtml.html'
$htmlString = "<IMG SRC=""data:image/$imageType;base64,$encodedString"">"
Set-Content -Path $htmlPath -Value $htmlString -Encoding UTF8
Start-Process -FilePath $htmlPath

# output generated HTML for inspection
$htmlString 

Encoding, as illustrated above, always involves converting binary data (byte arrays) into strings. Binary files – such as images or DLLs – can easily be converted to byte arrays using Get-Content, as previously shown.

 

Text encoding

When encoding plain strings, you follow the same process. However, you first need to convert the string to a byte array. Remember: encoding requires bytes and does not care what they represent. Anything that can be converted into a byte array can be encoded.

For text, there are several options for converting it into a byte array, including ASCII, UTF7, UTF8, and Unicode.

Just ensure that the receiving side (the one decoding the encoded text) uses the same text encoding; otherwise, the decoded text may appear distorted or unreadable due to incorrect byte-to-character mapping.

For example, in the initial example where PowerShell executed an encoded command, it expected the encoded command to be Unicode text. This is why the encoding script used the following line:


$bytes = [System.Text.Encoding]::Unicode.GetBytes($command)

Since Unicode requires two bytes per character, this approach produces relatively large strings. A more efficient option is UTF7, which reduces string size by half. For your own purposes, you can select whichever text encoding best suits your needs, as long as the same encoding is used during both encoding and decoding. Here’s an example using UTF7 instead of Unicode:


# Encoding using UTF7
$text = 'Hello, here is my original text. It could be any length...'

# convert text to bytes
$bytes = [System.Text.Encoding]::UTF7.GetBytes($text)

# convert bytes to base64 string
$encoded = [Convert]::ToBase64String($bytes)
$encoded

# Decoding using UTF7
$someEncodedText = 'SGVsbG8sIGhlcmUgaXMgbXkgb3JpZ2luYWwgdGV4dC4gSXQgY291bGQgYmUgYW55IGxlbmd0aC4uLg=='

# convert base64 string to bytes
$bytes = [Convert]::FromBase64String($someEncodedText)

# convert bytes to encoded text (UTF7)
$plaintext = [System.Text.Encoding]::UTF7.GetString($bytes)
$plaintext 

 

Base64 strings

Base64 is neither encoding nor encryption; it’s simply a way to represent a byte array as a string. This is why it’s commonly used to store encoded information. However, you can use Base64 with any type of byte array:


$someArray = 1,2,3,10,12,13

$someArrayString = [Convert]::ToBase64String($somearray)
$someArrayString

# start with some Base64 text
$reverseTest = 'AQIDCgwN'
# get back the numbers
$array = [Convert]::FromBase64String($reverseTest)
$array 

 

Alternate string formats

When you use Base64 to store binary information as a string, you can use the default system API methods, as shown above. However, you can store binary information in any format you choose, which may be necessary when interacting with data generated by someone else.

For example, SecureStrings do not persist as Base64 strings; instead, they use a hex format. Here is the example from above, using the same custom hex format that SecureStrings employ when saved to a file:


$someArray = 1,2,3,10,12,13

# convert to hex string and change the format to the format used by SecureStrings (lowercase, no hyphens)
$hexEncodedString = [System.BitConverter]::ToString($someArray).Replace('-','').ToLower()
$hexEncodedString

# start with hex-encoded string
$hexEncodedString = '0102030a0c0d'

# get back the numbers
$bytes = for ($i = 0; $i -lt $hexEncodedString.Length; $i += 2) {
    [Convert]::ToByte($hexEncodedString.Substring($i, 2), 16)
}
$bytes 

 

SecureStrings – This was our deep dive

    • In our first article, cross-platform encryption risks with .NET's SecureString, we looked at how secure your sensitive data was, not only on Windows, but across platforms.
    • To help you enhance SecureString security, we then presented the best practices on different platforms.
    • In the third article, we discussed: Encoding vs encryption? Understand the difference and choose wisely! 
    • And last but not least, we'll look at AES encryption. We'll tackle AES custom commands and encryption keys.

 

Good2know

Your ultimate PowerShell Cheat Sheet

Unleash the full potential of PowerShell with our handy poster. Whether you're a beginner or a seasoned pro, this cheat sheet is designed to be your go-to resource for the most important and commonly used cmdlets.

The poster is available for download and in paper form.

PowerShell Poster 2023

Get your poster here!

 

 

Related links 

 

Related posts

6 min read

Encoding vs encryption? Understand the difference and choose wisely!

Understanding encoding vs encryption is essential for robust data security. But what is the difference between encoding...

6 min read

Enhancing SecureString security: Best practices on different platforms

How does Windows keep SecureString safe? Dive deeper into encryption methods and uncover cross-platform security gaps...

6 min read

Cross-platform encryption risks with .NET's SecureString

Think your SecureString is safe? Not on all platforms! Discover the risks of cross-platform data encryption with ...

About the author: