Try to generate sha1 base64 hash of an empty string in powershell
$enc = [system.Text.Encoding]::UTF8
$string = ""
$data=$enc.GetBytes($string)
$sha1 = New-Object System.Security.Cryptography.SHA1CryptoServiceProvider
$ResultHash = $sha1.ComputeHash($data)
$str_out = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes($ResultHash))
write-host $str_out
result is
MjE4IDU3IDE2MyAyMzggOTQgMTA3IDc1IDEzIDUwIDg1IDE5MSAyMzkgMTQ5IDk2IDI0IDE0NCAxNzUgMjE2IDcgOQ==
and I should have received
2jmj7l5rSw0yVb/vlWAYkK/YBwk=
Please could someone advice?
The output from ComputeHash is already a byte array, not a string - [Text.Encoding]::UTF8.GetBytes($ResultHash) makes no sense here.
Remove that part and it'll work as expected:
$enc = [system.Text.Encoding]::UTF8
$string = ""
$data=$enc.GetBytes($string)
$sha1 = New-Object System.Security.Cryptography.SHA1CryptoServiceProvider
$ResultHash = $sha1.ComputeHash($data)
$str_out = [Convert]::ToBase64String($ResultHash)
write-host $str_out
Your expected encoded base64 string is not UTF-8 encoded.
If you want to get 2jmj7l5rSw0yVb/vlWAYkK/YBwk= you have to replace :
$str_out = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes($ResultHash))
by
$str_out = [Convert]::ToBase64String($ResultHash)
Related
How can I decode the body of a jdownloader *.DLC container file with Powershell?
I have managed to write a small Powershell snippet to decrypt a DLC container file based on the PyLoad code reference.
It prompts for a given file, decrypts the content and puts the URLs into the clipboard.
For the archives here the working sample code:
# script for decoding a DLC-file:
Remove-Variable * -ea 0
$ErrorActionPreference = 'stop'
$utf8 = [System.Text.Encoding]::UTF8
# file selector:
Add-Type -AssemblyName 'System.Windows.Forms'
$browser = [System.Windows.Forms.OpenFileDialog]::new()
$browser.Filter = 'DLC files (*.dlc)|*.dlc'
$browser.InitialDirectory = "$env:USERPROFILE\Downloads"
$null = $browser.ShowDialog()
$fileName = $browser.FileName
if (![System.IO.File]::Exists($fileName)) {break}
$dlc = [System.IO.File]::ReadAllText($fileName)
$len = $dlc.Length
$key = $dlc.Substring($len-88)
$data = $dlc.Substring(0,$len-88)
$bytes = [System.Convert]::FromBase64String($data)
$aesKey = 'cb99b5cbc24db398'
$aesIV = '9bc24cb995cb8db3'
$url = "http://service.jdownloader.org/dlcrypt/service.php?srcType=dlc&destType=pylo&data=$key"
$result = Invoke-WebRequest $url
$rc64 = ([xml]$result.Content).rc
$rc = [System.Convert]::FromBase64String($rc64)
$aes = [System.Security.Cryptography.Aes]::Create()
$aes.Key = $utf8.GetBytes($aeskey)
$aes.IV = $utf8.GetBytes($aesIV)
$aes.Padding = [System.Security.Cryptography.PaddingMode]::None
$dec = $aes.CreateDecryptor()
$result = $dec.TransformFinalBlock($rc, 0, $rc.Length)
$dec.Dispose()
$aes.key = $result
$aes.IV = $result
$dec = $aes.CreateDecryptor()
$enc = $dec.TransformFinalBlock($bytes, 0, $bytes.Length)
$dec.Dispose()
$b64 = $utf8.GetString($enc).Trim([char]0)
$byte = [System.Convert]::FromBase64String($b64)
$xml = [xml]$utf8.GetString($byte)
$urlList = foreach($url64 in $xml.dlc.content.package.file.url) {
$urlb = [System.Convert]::FromBase64String($url64)
$utf8.GetString($urlb)
}
cls
$urlList | Set-Clipboard
$urlList
Here is also a short demo how to encode any text into a DLC-format:
# DLC-encryption:
# get a random encryption key (RCP):
$bytes = [System.Security.Cryptography.Rfc2898DeriveBytes]::new($null,8)
$hexbin = [System.Runtime.Remoting.Metadata.W3cXsd2001.SoapHexBinary]::new($bytes.Salt)
$rcp = $hexbin.ToString().ToLower()
# let jdownloader generate an RC-value for this key:
$url = "http://service.jdownloader.org/dlcrypt/service.php?jd=1&srcType=plain&data=$rcp"
$result = Invoke-WebRequest $url
$rc = ([xml]"<xml>$($result.Content)</xml>").xml.rc
# if we store the rcp/rc-pair, then we could decode a DLC in offline mode
# encode any information with our initial key:
$data = 'something to encode'
$bytes = $utf8.GetBytes($data)
$aes = [System.Security.Cryptography.Aes]::Create()
$rcb = $utf8.GetBytes($rcp)
$aes.Padding = [System.Security.Cryptography.PaddingMode]::Zeros
$enc = $aes.CreateEncryptor($rcb, $rcb)
$out = $enc.TransformFinalBlock($bytes, 0, $bytes.Length)
$enc.Dispose()
# the DLC-content is a concatenation of the base64-string of the encrypted data
# plus the base64-string of the RC which corresponds to our initial RCP-key.
$data = [System.Convert]::ToBase64String($out)
write-host "$data$rc"
And here a correct XML-format of a decrypted DLC container. All(!) shown values here (strings/numbers/dates) must be in base64-format. I just decoded them all to make it a bit easier to understand them. Some elements or values might be optional, some may be subject of change. I have not tested that in details. It is just a readable format of a single DLC-file I created with JDownloader:
<dlc>
<header>
<generator>
<app>JDownloader</app>
<version>43307</version>
<url>http://jdownloader.org</url>
</generator>
<tribute/>
<dlcxmlversion>20_02_2008</dlcxmlversion>
</header>
<content>
<package category="various" comment="" name="Packagename">
<file>
<url>http://appwork.org/projects/DLCAPI/dlcapi_v1.0.rar</url>
<filename>dlcapi_v1.0.rar</filename>
<size>5838</size>
</file>
</package>
</content>
</dlc>
I am having a problem with the formatting of an e-mail. I have special characters in the body and they are not being displayed correctly, I have tried several solutions but the e-mail keeps arriving with a format that does not interpret special characters. The body of the e-mail has to be sent in plain text, so I cannot use [-BodyAsHtml]. Here is my function. I hope someone can help me. Best regards
function SendMail {
$PDFName = $settings.pdf.Name
$WebResponseObj = Invoke-WebRequest -Uri $PDFUrl
$getLastModified = $WebResponseObj.Headers.'Last-Modified'
$PDFdate = [DateTime]$getLastModified
$dateTimePDF = $PDFdate.DateTime
$plainTextBody = "
Meldung über das aktualisierte Dokument `r`n
File Name: $PDFName `r`n
File Url: $PDFUrl `r`n
Letzte Aktualisierung: $dateTimePDF `r`n
Letzte Aktualisierungsprüfung: $getDateTime
"
$param = #{
SmtpServer = $settings.mail.SmtpServer
Port = $settings.mail.Port
UseSsl = $true
Credential = $userCredential
From = $settings.mail.FromUser
To = $settings.mail.ToUser
Subject = $settings.mail.Subject
Body = $plainTextBody
Priority = 'High'
DeliveryNotificationOption = 'OnFailure'
ErrorAction = 'Stop'
Encoding = ([System.Text.Encoding]::UTF8)
}
Send-MailMessage #param
}
I have found the problem, the .ps1 file was in UTF-8 format and to be interpreted correctly it has to be UTF-8 with BOM, that's it!
I have database with tables in WIN1251 encoding. When I read data from tables then all the text that is in Cyrillic are shown as unknown symbols. This is the code I use:
function Get-ODBC-Data {
param([string]$query = $(throw 'query is required.'))
$conn = New-Object System.Data.Odbc.OdbcConnection
$connStr = "Driver=Firebird/Interbase(r) driver;Server=localhost;Port=3050;Database=C:\Users\user\Desktop\B52.GDB;Uid=SYSDBA;Pwd=masterkey;CHARSET=WIN1251"
$conn.ConnectionString = $connStr
$conn.open
$cmd = new-object System.Data.Odbc.OdbcCommand($query, $conn)
$cmd.CommandTimeout = 15
$ds = New-Object system.Data.DataSet
$da = New-Object system.Data.odbc.odbcDataAdapter($cmd)
[void]$da.fill($ds)
$ds.Tables[0]
$conn.close()
}
$query = #"
SELECT name FROM contact;
"#
$result = Get-ODBC-Data -query $query
$customers = #();
foreach ($row in $result) {
if (-not($null -eq $row.name)) {
$customers += $row.name;
}
}
$customers
You can try specifying the connection character set as UTF8 instead of WIN1251.
This will only work if your database really contains data in WIN1251 and those columns have WIN1251 as their explicit character set, if those columns have character set NONE (or NULL), then this will only work if the data is actually in UTF8.
The problem is either that your data didn't match your expectation (ie it wasn't WIN1251), or the combination of Powershell and the Firebird ODBC driver doesn't handle strings in a different character set than the console character set properly (if I'm not mistaken, the Powershell character set is utf-8).
Why does the following powershell script:
$privateKey = "843c1f887b"
$requestData = "1543448572|d.lastname#firm.com|Firstname Lastname"
function signRequest {
$hmacsha = New-Object System.Security.Cryptography.HMACSHA256
$hmacsha.key = [Text.Encoding]::ASCII.GetBytes($privateKey)
$signature = $hmacsha.ComputeHash([Text.Encoding]::ASCII.GetBytes($requestData))
$signature = [Convert]::ToBase64String($signature)
$outi = $signature
return $signature
}
convert to hash:
FipK51tOtzb2m2yFQAf5IK6BNthClnqE24luMzYMPuo=
and other online hmac sha256 generators with the same input to:
162a4ae75b4eb736f69b6c854007f920ae8136d842967a84db896e33360c3eea
any suggestions what I'm doing wrong in the script?
Thanks!
Your code produces the correct HMAC, you're just base64-encoding it instead of output a hex string like all the other tools.
Change this line
$signature = [Convert]::ToBase64String($signature)
to
$signature = [System.BitConverter]::ToString($signature).Replace('-','').ToLower()
Explanation:
[BitConverter]::ToString($signature) produces a hexadecimal string (16-2A-4A-E7...)
String.Replace('-','') removes the - (162A4AE7...)
String.ToLower() lowercases the final string (162a4ae7...)
I have a PowerShell script, whose objective is to convert an incoming JSON object into a different sort of JSON object. (The "why" falls outside of the scope of this question.) The script (so far) is below (URL is obfuscated and will not work):
function Map-TempStudents {
param($uffStudent) # JObject containing UFF-formatted student
[String]$districtCode = $uffStudent.Item("DistrictCode").ToString()
Write-Host "districtCode = " $districtCode
$tempStudent = New-Object -TypeName Newtonsoft.Json.Linq.JObject
$tempStudent.Add("DistrictNum", $uffStudent.Item("DistrictCode").ToString())
Write-Host "tempStudent(DistrictNum) = " $tempStudent.Item("DistrictNum").ToString()
}
$currentPath = Split-Path -parent $MyInvocation.MyCommand.Definition
$jsonNetPath = $currentPath + '\Newtonsoft.Json.dll'
Add-Type -Path $jsonNetPath
$wc = New-Object system.Net.WebClient;
$studentPersonal = $wc.downloadString("http://test.foo.org/StudentPersonal")
$json = [Newtonsoft.Json.Linq.JObject]::Parse($studentPersonal)
$studentPersonal | Out-File "test.txt" # DEBUG
$studentBases = $json.Item("Data").Item("AssignTeacher")
Map-TempStudents -uffStudent $studentBases[0]
Running this script gives the following output:
districtCode = 0745
tempStudent(DistrictNum) = 485
To be clear, "0745" is the correct value, and "485" is the unexpected value.
I would expect tempStudent(DistrictNum) to be "0745" as well.
Why would this value change like this?
I was able to reproduce your issue with the following script (assuming Newtonsoft.Json.dll is already loaded into PowerShell):
$jo = New-Object -TypeName Newtonsoft.Json.Linq.JObject
$jo.Add("foo", "0745")
Write-Host $jo.Item("foo").ToString()
The Add method on JObject accepts an object as its second argument. If you pass a numeric string with a leading zero (and all the digits are less than 8), it is interpreted as an octal number. Hence "0745" gets converted into "485". This must be a PowerShell thing, because the equivalent code in C# works correctly:
JObject jo = new JObject();
jo.Add("foo", "0745");
Console.WriteLine(jo["foo"].ToString());
To prevent the unwanted conversion in PowerShell, wrap your string in a JValue before passing it to JObject.Add(), e.g.:
$jval = New-Object -TypeName Newtonsoft.Json.Linq.JValue -ArgumentList "0745"
$jo.Add("foo", $jval)
Here is the corrected Map-TempStudents function:
function Map-TempStudents {
param($uffStudent) # JObject containing UFF-formatted student
$districtCode = New-Object -TypeName Newtonsoft.Json.Linq.JValue -ArgumentList $uffStudent.Item("DistrictCode").ToString()
Write-Host "districtCode = " $districtCode.ToString()
$tempStudent = New-Object -TypeName Newtonsoft.Json.Linq.JObject
$tempStudent.Add("DistrictNum", $districtCode)
Write-Host "tempStudent(DistrictNum) = " $tempStudent.Item("DistrictNum").ToString()
}