Trying to replicate a Hash example in C# - c#

I'm trying to consume an API and for that purpose I have to create a signature using SHA384. The docs describe doing:
signature = hex(HMAC_SHA384(base64(payload), key=api_secret))
They give an example:
~$ base64 << EOF
> {
> "request": "/v1/order/status",
> "nonce": 123456,
>
> "order_id": 18834
> }
> EOF
ewogICAgInJlcXVlc3QiOiAiL3YxL29yZGVyL3N0YXR1cyIsCiAgICAibm9uY2UiOiAxMjM0NTYs
CgogICAgIm9yZGVyX2lkIjogMTg4MzQKfQo=
In this example, the api_secret is 1234abcd
echo -n 'ewogICAgInJlcXVlc3QiOiAiL3YxL29yZGVyL3N0YXR1cyIsCiAgICAibm9uY2UiOiAxMjM0NTYsCgogICAgIm9yZGVyX2lkIjogMTg4MzQKfQo=' | openssl sha384 -hmac "1234abcd"
(stdin)= 337cc8b4ea692cfe65b4a85fcc9f042b2e3f702ac956fd098d600ab15705775017beae402be773ceee10719ff70d710f
It took a little while, but I realized that in order to replicate the base64 of the original string I had to replace "\r\n" with "\n".
Here's what I've got (ignoring the formatting that I wasted 20 minutes trying to make good):
var raw = #"{
""request"": ""/v1/order/status"",
""nonce"": 123456,
""order_id"": 18834
}
";
var data = raw.Replace("\r\n", "\n");
Console.WriteLine(data);
var data64 = Convert.ToBase64String(Encoding.UTF8.GetBytes(data.ToCharArray()));
if (data64 != "ewogICAgInJlcXVlc3QiOiAiL3YxL29yZGVyL3N0YXR1cyIsCiAgICAibm9uY2UiOiAxMjM0NTYsCgogICAgIm9yZGVyX2lkIjogMTg4MzQKfQo=")
{
Console.WriteLine("base64's don't match");
}
Console.WriteLine("ewogICAgInJlcXVlc3QiOiAiL3YxL29yZGVyL3N0YXR1cyIsCiAgICAibm9uY2UiOiAxMjM0NTYsCgogICAgIm9yZGVyX2lkIjogMTg4MzQKfQo=");
Console.WriteLine(data64);
var key = Encoding.UTF8.GetBytes("1234abcd");
using (var hash = new HMACSHA384(key))
{
var hash64 = Convert.ToBase64String(hash.ComputeHash(Encoding.UTF8.GetBytes(data64)));
StringBuilder sb = new StringBuilder();
foreach (char c in hash64)
{
sb.Append(Convert.ToInt32(c).ToString("x"));
}
Console.WriteLine(sb.ToString());
// yields:
// 4d337a49744f70704c50356c744b68667a4a38454b79342f6343724a5676304a6a57414b7356634664314158767135414b2b647a7a753451635a2f3344584550
// should be:
// 337cc8b4ea692cfe65b4a85fcc9f042b2e3f702ac956fd098d600ab15705775017beae402be773ceee10719ff70d710f
}
My code's output doesn't match the documentation's expected output. Can someone see what I'm doing wrong?

For some reason you are converting hash to base-64 string, then you convert each character of that string to int and that you convert to hex. All that is not needed and not described in "documentation". Instead, do like this:
var hashBin = hash.ComputeHash(Encoding.UTF8.GetBytes(data64));
var hashHex = BitConverter.ToString(hashBin).Replace("-", "").ToLowerInvariant();
Console.WriteLine(hashHex);

Related

Convert String to Byte Array replacing characters between specific character

I am trying to find a way to convert a string (entered into a TextBox) and convert it to a byte array to send out a serial port / socket.
I am fine with the converting string to byte[] part but am struggling a bit with the replacement
Essentially the GUI allows the user to specific the format of the response to send and I was looking at something like the following :-
User Enters : [2] Test {1} {2} [3]
{1} and {2} are variable fields which can be pulled from the incoming message so they are currently being replaced without issue.
What I am trying to achieve is replace the [2] with an STX character and the [3] with an ETX character with the 2 and 3 being their ASCII equivalents. www.asciitable.com
The user can enter any valid ascii character in this format so [13] for CR etc
Would the best way to loop through the string remembering the index of [ and then the index of ] and grab all characters between these two indexes? Or is there a more efficient way?
Thanks,
Daniel.
A regular expression can find digits between brackets and replace them with a calculated value.
Your replacement scheme looks like it might be similar to String.Format but you'll have to compare that and decide on the order of operations and meaning of special characters.
The encoding will throw an exception if the bracketed number is outside of 0-127. You could have some other behavior if you want.
var encoding = Encoding.GetEncoding(Encoding.ASCII.CodePage,
EncoderFallback.ExceptionFallback,
DecoderFallback.ExceptionFallback);
var bracketRegex = new Regex(#"\[(?<digits>\d+)\]", RegexOptions.Compiled);
MatchEvaluator convertToCodepoint = (match) =>
Char.ConvertFromUtf32(Int32.Parse(match.Groups["digits"].Value));
var values = new[] {"a", "b", "c" };
var input = "[2] Test {1} {2} [3]";
encoding.GetBytes(String.Format(bracketRegex.Replace(input, convertToCodepoint), values))
.Dump();
I think you should write a code similar to this:
string input = TextBox.text; "User name (sales)";
//Use those lines if you don't know how many times do you have to iterate.
var totalOfBraces = input.Where(x => x == '{').Count();
var totalOfBrackets = input.Where(x => x == '[').Count();
var totalOfElements = totalOfBraces + totalOfBrackets;
string output = input.Split('[', ']')[1];
string output = input.Split('{', '}')[1];
And you you can get the elements between Braces and Brackets and do a replace of them.
Then, why I added totalOfElements, to have the possibility to do a for bucle
For example:
var counterOfBraces = 0;
var counterOfBrackets = 0;
for(var i=0; i<totalOfElements.Count(); i++){
if(i < totalOfBrackets){
counterOfBrackets+=1;
var textToFind = "[" + index + "]";
input = input.Replace(textToFind, "some new text");
} else {
//Do the same for braces
}
}
//NOW HERE, YOU HAVE YOUR TEXT FORMATED AND READY TO CONVERT IT TO BYTE[]

Extract number from a string followed by "I-"

In C#, I assigned this last line from a log file to string "str"
I want to extract the numbers following "I-" and store it in a data type for use it later in the program. In the example below I need to get 667466.
Please help how to do this?
string str = "2017-01-16 11:10:37.151 +11:00 [Information] OutboundMessageFile:MessageFields: [KeyValuePair`2 { Key: \"ConfirmationCode\", Value: \"I-667466\" }], MessageAttachments: \"\", MessageConfig: \"\", MachineName: \"MARYDEV234\" }"
You can use regex to find this data.
var regex = new Regex("Value: \"I-(\\d+)\"");
var match = regex.Match(str);
if (match.Success)
{
var data = match.Groups[1].Value;
// Store data for next use
}
Personally I like Uladzimir's regex solution, but here's an alternative:
string str = "2017-01-16 11:10:37.151 +11:00 [Information] OutboundMessageFile:MessageFields: [KeyValuePair`2 { Key: \"ConfirmationCode\", Value: \"I-667466\" }], MessageAttachments: \"\", MessageConfig: \"\", MachineName: \"MARYDEV234\" }";
int index = str.IndexOf("I-");
index += 2; //Skip the "I-"
string output = "";
for(int i = index; true; i++)
{
if(str[i] == '"')
break;
output += str[i];
}
Console.WriteLine(output);
This only works on strings specifically formatted like you have though, the regex solution is more generalizable. You can upgrade this version to make output a StringBuilder instead of a string too.

Converting C# code to php encoding issue

I try to replicate this C# code in php to get the same output(I cannot change c# code only php).And here I'm stuck
public static string HashData(string textToBeEncripted)
{
//Convert the string to a byte array
Byte[] byteDataToHash = System.Text.Encoding.Unicode.GetBytes(textToBeEncripted);
//Compute the MD5 hash algorithm
Byte[] byteHashValue = new System.Security.Cryptography.MD5CryptoServiceProvider().ComputeHash(byteDataToHash);
return System.Text.Encoding.Unicode.GetString(byteHashValue);
}
The php code that I have made till now looks like this
$a = "test";
$a = mb_convert_encoding($a, "UTF-16LE");
$a = md5($a,true);
$a = unpack('C*', $a);
var_dump($a);
//with the output
array(16) { [1]=> int(200) [2]=> int(5) [3]=> int(158) [4]=> int(46) [5]=> int(199) [6]=> int(65) [7]=> int(159) [8]=> int(89) [9]=> int(14) [10]=> int(121) [11]=> int(215) [12]=> int(241) [13]=> int(183) [14]=> int(116) [15]=> int(191) [16]=> int(230) }
As you can see the output is the same as in the C# code
But I'm stuck at the function System.Text.Encoding.Unicode.GetString().How to replicate this in php?Or there is a easier way to get the same output?(I cannot change the C# code sorry)
Edit: Based on Vasiliy Zverev answers since the php hash is different a little bit.I end up making aproximating the hash value of php with the C# hash
function validare_parola($parola,$dbHash){
$parola = mb_convert_encoding($parola, "UTF-16LE");
$parola = md5($parola, true);
$parola = mb_convert_encoding($parola, "UCS-2BE", "UCS-2LE");
$parola = bin2hex($parola);
$procent;
similar_text($dbHash,$parola,$procent);
if($procent>=90){
return true;
}else{
return false;
}
}
$parola = "testa";
$dbHash = "10095018710be2bcbbf9bba3f9d91ce8";
if(validare_parola($parola,$dbHash)){
echo 'PASSWORD CORRECT.You can log in.';
}else{
echo 'INCORRECT PASSWORD.Try again.';
}
As a side note don't use md5 for passwords use php password hashing api
Edit2: I ended up using Vasiliy Zverev solution.
Edit3: For the value "111111" there is different output in php...
Edit4: Vasily Zverev updated his solution and now is working as expected
The solution, updated:
$a = "SF0D9G9SGGF0gdsfg976590";
$a = mb_convert_encoding($a, "UTF-16LE");
$a = md5($a, true);
$res = '';
for($i=0; $i<16; $i+=2) {
// System.Text.Encoding.Unicode.GetString(byteHashValue) replaces invalid characters to 0xfffd ('я')
// while PHP to 0x003d ('?') or empty string. So replace them like C# does
$a2 = mb_convert_encoding($a[$i].$a[$i+1], "UTF-16LE","UTF-16LE"); // check if this is invalid UTF-16 character
if(strlen($a2)==0 || $a[$i]!=$a2[0]) {
// replace invalid UTF-16 character with C# like
$v = 0xfffd;
}
else {
// prepare a word (UTF-16 character)
$v = ord($a[$i+1])<<8 | ord($a[$i]);
}
// print each word without leading zeros as C# code does
$res .= sprintf("%x",$v);
}
echo($res);
Removed this variant because it was wrong. See correct code above.

When using indexof and substring how do i parse the right start and end indexs ? And how do i encode hebrew chars?

I have this code:
string firstTag = "Forums2008/forumPage.aspx?forumId=";
string endTag = "</a>";
index = forums.IndexOf(firstTag, index1);
if (index == -1)
continue;
var secondIndex = forums.IndexOf(endTag, index);
result = forums.Substring(index + firstTag.Length + 12, secondIndex - (index + firstTag.Length - 50));
The string i want to extract from is for example:
הנקה
What i want to get is the word after the title only this: הנקה
And the second problem is that when i'm extracting it i see instead hebrew some gibrish like this: ������
One powerful way to do this is to use Regular Expressions instead of trying to find a starting position and use a substring. Try out this code, and you'll see that it extracts the anchor tag's title:
var input = "הנקה";
var expression = new System.Text.RegularExpressions.Regex(#"title=\""([^\""]+)\""");
var match = expression.Match(input);
if (match.Success) {
Console.WriteLine(match.Groups[1]);
}
else {
Console.WriteLine("not found");
}
And for the curious, here is a version in JavaScript:
var input = 'הנקה';
var expression = new RegExp('title=\"([^\"]+)\"');
var results = expression.exec(input);
if (results) {
document.write(results[1]);
}
else {
document.write("not found");
}
Okay here is the solution using String.Substring() String.Split() and String.IndexOf()
String str = "הנקה"; // <== Assume this is passing string. Yes unusual scape sequence are added
int splitStart = str.IndexOf("title="); // < Where to start splitting
int splitEnd = str.LastIndexOf("</a>"); // < = Where to end
/* What we try to extract is this : title="הנקה">הנקה
* (Given without escape sequence)
*/
String extracted = str.Substring(splitStart, splitEnd - splitStart); // <=Extracting required portion
String[] splitted = extracted.Split('"'); // < = Now split with "
Console.WriteLine(splitted[1]); // <= Try to Out but yes will produce ???? But put a breakpoint here and check the values in split array
Now the problem, here you can see that i have to use escape sequence in an unusual way. You may ignore that since you are simply passing the scanning string.
And this actually works, but you cannot visualize it with the provided Console.WriteLine(splitted[1]);
But if you put a break point and check the extracted split array you can see that text are extracted. you can confirm it with following screenshot

reading certain digits from binary data

I have one python script which i am trying to convert and stuck in one place and unable to proceed. Please check where ever i have mentioned "Stuck here" in below code. any help would be appreciated
Original Python script:
import hashlib
meid = raw_input("Enter an MEID: ").upper()
s = hashlib.sha1(meid.decode('hex'))
#decode the hex MEID (convert it to binary!)
pesn = "80" + s.hexdigest()[-6:].upper()
#put the last 6 digits of the hash after 80
print "pESN: " + pesn
My C# conversion:
UInt64 EsnDec = 2161133276;
string EsnHex=string.Format("{0:x}", EsnDec);
string m = Convert.ToString(Convert.ToUInt32(EsnHex, 16), 2);
/*---------------------------------------------
Stuck here. Now m got complete binary data
and i need to take last 6 digits as per python
script and prefix "80".
---------------------------------------------*/
Console.WriteLine(m);
Console.Read();
Use String.Substring:
// last 6 characters
string lastsix = m.Substring(m.Length - 6);
Console.WriteLine("80{0}", lastsix);
How about something like this:
static void Main(string[] args)
{
UInt64 EsnDec = 2161133276;
Console.WriteLine(EsnDec);
//Convert to String
string Esn = EsnDec.ToString();
Esn = "80" + Esn.Substring(Esn.Length - 6);
//Convert back to UInt64
EsnDec = Convert.ToUInt64(Esn);
Console.WriteLine(EsnDec);
Console.ReadKey();
}

Categories