The following is an illustration of a practical usage of decrypting an ASCII encoded value from a CRM database. This is also a solution for the issue of “Recovering ‘lost’ CRM encryption key.” May the power of Google helps someone who is facing such problems.
# getCrmEncryptionPassword.ps1
$orgName='TESTORG'
$sqlServer='SQLSERVER'
$saUsername='sa'
$saPassword='password'
$saCredential=New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $saUsername,$(ConvertTo-securestring $saPassword -AsPlainText -Force)
function getSymmetricKey($orgName){
$moduleName='sqlps'
if(!(Get-Module -ListAvailable -Name $moduleName -ea SilentlyContinue)){
if(!('NuGet' -in (get-packageprovider).Name)){
try{
Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force -ErrorAction SilentlyContinue;
}
catch{
#Set-ItemProperty -Path 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\.NetFramework\v4.0.30319' -Name 'SchUseStrongCrypto' -Value '1' -Type DWord
#Set-ItemProperty -Path 'HKLM:\SOFTWARE\Microsoft\.NetFramework\v4.0.30319' -Name 'SchUseStrongCrypto' -Value '1' -Type DWord
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force -ErrorAction SilentlyContinue;
}
}
Install-Module -Name $moduleName -Force -Confirm:$false
}
import-module $moduleName
$querySymmetricKey=@"
USE MSCRM_CONFIG
SELECT VarBinaryColumn FROM OrganizationProperties
WHERE (ColumnName = 'SymmetricKeySource')
AND Id IN (SELECT Id FROM Organization WHERE UniqueName = '$orgName')
"@
$symmetricKey=invoke-sqlcmd $querySymmetricKey
return $symmetricKey.VarBinaryColumn
}
$encodedBytes=Invoke-Command -ComputerName $sqlServer -Credential $saCredential -ScriptBlock{
param($getSymmetricKey,$orgName)
write-host "Executing function on $env:computername"
Write-Host "$getSymmetricKey"
pause
[ScriptBlock]::Create($getSymmetricKey).invoke($orgName)
} -Args ${function:getSymmetricKey},$orgName
function convertEncodedBytesToString($bytesArray,$encoding='default'){
# Convert encoded bytes => decimal string => decimal bytes array => string
#source: https://learn.microsoft.com/en-us/dotnet/api/system.bitconverter.tochar?view=netcore-3.1
$ErrorActionPreference='stop'
try{
$decimalString=[System.Text.Encoding]::default.GetChars($bytesArray) -join ''
$decimalBytes=$decimalString.Split(':')
$result=$(for ($i=0;$i -lt $decimalBytes.count;$i+=2){[System.BitConverter]::ToChar($decimalBytes,$i)}) -join ''
return $result
}catch{
Write-Error $_
return $false
}
}
convertEncodedBytesToString $encodedBytes
# Other Miscellaneous conversions
function convertHexToAscii($hexValue){
try{
$initChars=$hexValue.ToString().Substring(0,2)
$startIndex=if($initChars -eq '0x'){2}else{0}
$keys=$hexValue -split '-'
$decimalBytes = $(for($i=$startIndex; $i -lt $keys.length; $i+=2){[char][int]::Parse($keys.substring($i,2),'HexNumber')}) -join ''
$decimalArray=$decimalBytes.Split(':')
$ascii=$(for ($i=0;$i -lt $decimalArray.count;$i+=2){[CHAR][BYTE]$decimalArray[$i]}) -join ''
return $ascii
}catch{
Write-Warning "Please validate the input by checking this error:`r`n$($Error[0].Exception.Message)"
}
}
function convertBytesArrayToAscii($bytesArray){
function convertDecimalBytesToAscii($decimalBytes){
$decimalArray=$decimalBytes.Split(':')
$ascii=$(for ($i=0;$i -lt $decimalArray.count;$i+=2){[CHAR][BYTE]$decimalArray[$i]}) -join ''
return $ascii
}
function convertBytesArrayToDecimalBytes($bytesArray){
return [System.Text.Encoding]::ASCII.GetString($bytesArray)
}
try{
$decimalBytes=convertBytesArrayToDecimalBytes $bytesArray
$ascii=convertDecimalBytesToAscii $decimalBytes
return $ascii
}
catch{
write-warning $error[0].Exception.Message
}
}
# How to convert Bytes Array => Hex
$hexValue=[System.BitConverter]::ToString($bytesArray)
# How to convert decimalBytes => ASCII
$decimalBytes=($hexValue.split('-') | % {[char][byte]"0x$_"}) -join ''
# How to convert bytes => binary
[system.Text.Encoding]::Default.GetBytes($bytesArray) | %{[System.Convert]::ToString($_,2).PadLeft(8,'0') }
# Enable UTF8 encoding in PShell session
$OutputEncoding=[console]::InputEncoding=[console]::OutputEncoding=New-Object System.Text.UTF8Encoding
# Convert text => bytes
$text='hello world!'
$bytes = [System.Text.Encoding]::UTF8.GetBytes($text)
# How to convert bytes => text
[System.Text.Encoding]::UTF8.GetChars($bytes) -join ''
Categories: