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...
Unlocking the Power of PowerShell: Tips for Success
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.
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.
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:
When you run this, PowerShell executes the original encoded script block and begins dumping all PowerShell scripts it can find in your Windows folder.
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.
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 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
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
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.
Nov 27, 2024 by Aleksandar Nikolić and Dr. Tobias Weltner
Understanding encoding vs encryption is essential for robust data security. But what is the difference between encoding...
Nov 20, 2024 by Aleksandar Nikolić and Dr. Tobias Weltner
How does Windows keep SecureString safe? Dive deeper into encryption methods and uncover cross-platform security gaps...
Nov 18, 2024 by Aleksandar Nikolić and Dr. Tobias Weltner
Think your SecureString is safe? Not on all platforms! Discover the risks of cross-platform data encryption with ...
Tobias Weltner and Aleksandar Nikolić joinly wrote the blog post series 'Tobias&Aleksandar's PowerShell tips'. So we introduce both of them here:
----------------------------
Aleksandar Nikolić is a Microsoft Azure MVP and co-founder of PowerShellMagazine.com, the ultimate online source for PowerShell enthusiasts. With over 18 years of experience in system administration, he is a respected trainer and speaker who travels the globe to share his knowledge and skills on Azure, Entra, and PowerShell. He has spoken at IT events such as Microsoft Ignite, ESPC, NIC, CloudBrew, NTK, and PowerShell Conference Europe.
----------------------------
Tobias is a long-time Microsoft MVP and has been involved with the development of PowerShell since its early days. He invented the PowerShell IDE "ISESteroids", has written numerous books on PowerShell for Microsoft Press and O'Reilly, founded the PowerShell Conference EU (psconf.eu), and is currently contributing to the advancement of PowerShell as member in the "Microsoft Cmdlet Working Group". Tobias shares his expertise as a consultant in projects and as a trainer in in-house trainings for numerous companies and agencies across Europe.