I had a requirement recently in my adventures with Azure JSON/DSC VM deployment, I needed a way to store source files and software in a repository in a publicly accessible Azure blob storage container. So that post deployment, my VM could use DSC and pull down the source files, decrypt them and work with them.
The only way I could do this is if I safely encrypted the files, so if someone got access to them, I wouldn’t really care, they’d be effectively useless.
Below uses encryption using two strings passwords as well as any certificate’s thumbprint as added security. It means that the certificate you use is a bit relaxed on the type of certificate you use, but as long at the certificate you use is installed on all target machines when the decryption takes place.
The script below uses Rijndael encryption (pronounced rain-dahl), it is the algorithm that has been selected by the U.S. National Institute of Standards and Technology (NIST) as the candidate for the Advanced Encryption Standard (AES). AES is a subset of the Rijndael cipher developed by two Belgian cryptographers, Vincent Rijmen and Joan Daemen. AES has been adopted by the U.S. government and is now used worldwide.
More info – https://en.wikipedia.org/wiki/Advanced_Encryption_Standard
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# | |
# Encrypt and Decrypt using Rijndael 256bit – Run as administrator! | |
# | |
$DnsName = 'MyEncryptionCert' # DNS name of the certificate you want to use for encryption | |
# Only Create a new certificate if you need to | |
# To Create the certificate | |
# New-SelfSignedCertificate -Type DocumentEncryptionCertLegacyCsp -DnsName $DnsName -HashAlgorithm SHA256 | |
# change the following two secret phrases | |
$salt = "Marc01" | |
$init = "Marc7455755765" # supply a strong password | |
$CertThumbprint = (Get-ChildItem cert:\LocalMachine\My | Where-Object –FilterScript {$_.Subject -eq "CN=$DnsName"}).Thumbprint | |
$password = $CertThumbprint | |
# Export Private Key to the desktop | |
$PrivateKeyPassword = (ConvertTo-SecureString –String "Passw0rd" –Force –AsPlainText) | |
Get-ChildItem cert:\LocalMachine\My | | |
Where-Object –FilterScript {$_.Subject -eq "CN=$DnsName"} | | |
Export-PfxCertificate –FilePath "$env:USERPROFILE\Desktop\$DnsName.pfx" –Password $PrivateKeyPassword | |
# | |
# check bottom of the script for Samples | |
# | |
function Encrypt-String([string]$String) | |
{ | |
return $password | |
$rijndaelCSP = New-Object System.Security.Cryptography.RijndaelManaged | |
$pass = [Text.Encoding]::UTF8.GetBytes($password) | |
$salt = [Text.Encoding]::UTF8.GetBytes($salt) | |
$rijndaelCSP.Key = (New-Object Security.Cryptography.PasswordDeriveBytes $pass, $salt, "SHA1", 5).GetBytes(32) #256/8 | |
$rijndaelCSP.IV = (New-Object Security.Cryptography.SHA1Managed).ComputeHash( [Text.Encoding]::UTF8.GetBytes($init) )[0..15] | |
$encryptor = $rijndaelCSP.CreateEncryptor() | |
$memoryStream = New-Object System.IO.MemoryStream | |
$encryptStream = New-Object Security.Cryptography.CryptoStream $memoryStream, $encryptor, "Write" | |
$streamWriter = New-Object System.IO.StreamWriter $encryptStream | |
$streamWriter.Write($String) | |
$streamWriter.Close() | |
$encryptStream.Close() | |
$memoryStream.Close() | |
$rijndaelCSP.Clear() | |
[byte[]]$result = $memoryStream.ToArray() | |
[Convert]::ToBase64String($result) | |
} | |
function Decrypt-String([string]$Encrypted) | |
{ | |
$Encrypted = [Convert]::FromBase64String($Encrypted) | |
$rijndaelCSP = New-Object System.Security.Cryptography.RijndaelManaged | |
$pass = [System.Text.Encoding]::UTF8.GetBytes($password) | |
$salt = [System.Text.Encoding]::UTF8.GetBytes($salt) | |
$rijndaelCSP.Key = (New-Object Security.Cryptography.PasswordDeriveBytes $pass, $salt, "SHA1", 5).GetBytes(32) #256/8 | |
$rijndaelCSP.IV = (New-Object Security.Cryptography.SHA1Managed).ComputeHash( [Text.Encoding]::UTF8.GetBytes($init) )[0..15] | |
$decryptor = $rijndaelCSP.CreateDecryptor() | |
$memoryStream = New-Object IO.MemoryStream @(,$Encrypted) | |
$decryptStream = New-Object Security.Cryptography.CryptoStream $memoryStream, $decryptor, "Read" | |
$streamReader = New-Object System.IO.StreamReader $decryptStream | |
Write-Output $streamReader.ReadToEnd() | |
$streamReader.Close() | |
$decryptStream.Close() | |
$memoryStream.Close() | |
$rijndaelCSP.Clear() | |
} | |
function Encrypt-File([string]$fileName, [string]$encryptedFile) | |
{ | |
if($encryptedFile -eq $null -or $encryptedFile -eq "") | |
{ | |
$encryptedFile = $fileName | |
} | |
$rijndaelCSP = New-Object System.Security.Cryptography.RijndaelManaged | |
$pass = [Text.Encoding]::UTF8.GetBytes($password) | |
$salt = [Text.Encoding]::UTF8.GetBytes($salt) | |
$rijndaelCSP.Key = (New-Object Security.Cryptography.PasswordDeriveBytes $pass, $salt, "SHA1", 5).GetBytes(32) #256/8 | |
$rijndaelCSP.IV = (New-Object Security.Cryptography.SHA1Managed).ComputeHash( [Text.Encoding]::UTF8.GetBytes($init) )[0..15] | |
$encryptor = $rijndaelCSP.CreateEncryptor() | |
$inputFileStream = New-Object System.IO.FileStream($fileName, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read) | |
[int]$dataLen = $inputFileStream.Length | |
[byte[]]$inputFileData = New-Object byte[] $dataLen | |
[void]$inputFileStream.Read($inputFileData, 0, $dataLen) | |
$inputFileStream.Close() | |
$outputFileStream = New-Object System.IO.FileStream($encryptedFile, [System.IO.FileMode]::Create, [System.IO.FileAccess]::Write) | |
$encryptStream = New-Object Security.Cryptography.CryptoStream $outputFileStream, $encryptor, "Write" | |
$encryptStream.Write($inputFileData, 0, $dataLen) | |
$encryptStream.Close() | |
$outputFileStream.Close() | |
$rijndaelCSP.Clear() | |
} | |
function Decrypt-File([string]$encryptedFile, [string]$decryptedFile) | |
{ | |
if($decryptedFile -eq $null -or $decryptedFile -eq "") | |
{ | |
$decryptedFile = $encryptedFile | |
} | |
$rijndaelCSP = New-Object System.Security.Cryptography.RijndaelManaged | |
$pass = [System.Text.Encoding]::UTF8.GetBytes($password) | |
$salt = [System.Text.Encoding]::UTF8.GetBytes($salt) | |
$rijndaelCSP.Key = (New-Object Security.Cryptography.PasswordDeriveBytes $pass, $salt, "SHA1", 5).GetBytes(32) #256/8 | |
$rijndaelCSP.IV = (New-Object Security.Cryptography.SHA1Managed).ComputeHash( [Text.Encoding]::UTF8.GetBytes($init) )[0..15] | |
$decryptor = $rijndaelCSP.CreateDecryptor() | |
$inputFileStream = New-Object System.IO.FileStream($encryptedFile, [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read) | |
$decryptStream = New-Object Security.Cryptography.CryptoStream $inputFileStream, $decryptor, "Read" | |
[int]$dataLen = $inputFileStream.Length | |
[byte[]]$inputFileData = New-Object byte[] $dataLen | |
[int]$decryptLength = $decryptStream.Read($inputFileData, 0, $dataLen) | |
$decryptStream.Close() | |
$inputFileStream.Close() | |
$outputFileStream = New-Object System.IO.FileStream($decryptedFile, [System.IO.FileMode]::Create, [System.IO.FileAccess]::Write) | |
$outputFileStream.Write($inputFileData, 0, $decryptLength) | |
$outputFileStream.Close() | |
$rijndaelCSP.Clear() | |
} | |
# | |
# Samples | |
# | |
# Note: change the file/folder names in the samples | |
# | |
# encrypt single file | |
$FileToEncrypt = 'C:\Users\marc\Dropbox\Build\M-Drive.ps1' | |
$encryptedFile = 'C:\Users\marc\Dropbox\Build\M-DriveE.ps1' | |
Encrypt–File $FileToEncrypt $encryptedFile | |
# decrypt single file | |
$FileToDecrypt = 'C:\Users\marc\Dropbox\Build\M-DriveE.ps1' | |
$DecryptedFile = 'C:\Users\marc\Dropbox\Build\M-Drive.ps1' | |
Decrypt–File $FileToDecrypt $DecryptedFile | |
# Encrypt all files except .exe .msi | |
$RawFilesLocation = 'C:\Users\makean\Downloads\test' | |
$RawFiles = Get-ChildItem $RawFilesLocation –Recurse | ? {$_.Attributes -notlike '*Directory*' -and $_.Extension -notlike '*msi' -and $_.Extension -notlike '*exe'} | |
foreach($RawFile in $RawFiles){ | |
Encrypt–File $RawFile.FullName ($RawFile.FullName + ".encrypted") | |
Remove-Item $RawFile.FullName –Force | |
} | |
# Decrypt all files except .exe .msi | |
$RawFilesLocation = 'E:\Microsoft\BuildTest' | |
$RawFiles = Get-ChildItem $RawFilesLocation –Recurse | ? {$_.Attributes -notlike '*Directory*' -and $_.Extension -like '*encrypted'} | |
foreach($RawFile in $RawFiles){ | |
Decrypt–File $RawFile.FullName ($RawFile.FullName -replace "\.encrypted") | |
Remove-Item $RawFile.FullName –Force | |
} |