How to transform to C# the PHP pack('H40',$string);? - c#

I am trying to reproduce the result of a PHP pack('H40',$string) function.
So far i got good results but slightly different.
Here is what i tried
PHP Code
<?php
function test(){
$packed = pack('H40',"42d5abcd859afd2cc0f6b6f8cc2a9cd41f66a120");
return $packed;
}
echo test();
?>
C# Code:
private void test(){
string result = PackH40("42d5abcd859afd2cc0f6b6f8cc2a9cd41f66a120");
}
private string PackH40(string input)
{
string result = string.Empty;
input = input.Replace("-", " ");
byte[] hashBytes = new byte[input.Length / 2];
for (int i = 0; i < hashBytes.Length; i++)
{
hashBytes[i] = Convert.ToByte(input.Substring(i * 2, 2), 16);
}
return Encoding.UTF8.GetString(hashBytes);
}
The results look similar in browser but if you write them to a file they are not equal.
So far i tried every Encoding for the C# output and nothing.
What am i doing wrong?
Edit:
I tried the approach in
Trying to reproduce PHP's pack("H*") function in C# the issue is similar and in this case did not help me.
Resolved: Major problem was that i wanted to 'see' the data and compare it. I was terribly wrong! Converted all to byte[] and it worked like a charm !

Related

C# hmac hashing function converting to PHP

I am working on a rest call to an asp.net web service and was provided sample code in C#. I am having trouble converting the following function
public static string ComputeHash(string hashedPassword, string message)
{
var key = Encoding.UTF8.GetBytes(hashedPassword.ToUpper());
string hashString;
using (var hmac = new HMACSHA256(key))
{
var hash = hmac.ComputeHash(Encoding.UTF8.GetBytes(message));
hashString = Convert.ToBase64String(hash);
}
return hashString;
}
So far this is the draft php equivalent, is there anything specific I should be taking into account when converting between the two? Ignore any formatting am just trying to keep variable names the same for now for sanity. I can't seem to get these to come out to be the same.
function ComputeHash($hashedPassword, $message)
{
$key = utf8_encode(strtoupper($hashedPassword));
$hashString=hash_hmac('sha256',utf8_encode($message),$key,True);
$hashString = base64_encode($hashString);
return $hashString;
}
EDIT
Thanks to comments below I am able to get both functions doing the same.
Now the issue I have is around the input message
In C# this comes out like this
"GET\n03 August 2022 14:57:27.569500\n/api/member\nuserName=tom.woodforde#redox-software.co.uk";
If I feed the same into the function below the output is different.
This is how the function is built in C# to generate the message
private const String _newLineChar = "\n";
private static String CreateMessage(String method, String dateUTC, String apiModule, String data)
{
return method + _newLineChar + dateUTC + _newLineChar + apiModule + _newLineChar + data;
}
In PHP this is my equivalent
function CreateMessage($method, $dateUTC, $apiModule, $data){
$newLineChar = "\\n";
$message= $method.$newLineChar.$dateUTC.$newLineChar.$apiModule.$newLineChar.$data;
return $message;
}
I can feed in the exact same string but get a different result from the encryption and I am assuming it must be because of \n

I'm trying to Multi-thread a MD5 Hash string method but getting the error CS0123 C# No overload for matches delegate 'ThreadStart'

I have done some research and found solutions that apply to a void method, however I have been unable to replicate my code to that of a void as there is no overload for my method 'MD5' that matches the delegate 'ThreadStart', and I have been unable to convert a void to string, this programs intent is to show how multi-threading can allow for more than one process can be done at once. I intend to add additional processes on different threads, however, it is important that this works.
using System.Security.Cryptography;//Added to allow for UTF8 encoding
using System.Threading;//Added to allow for multi-threading
namespace MTSTask5
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
//MD5 Hash method
public void MD5(string input)
{
MD5 md5 = new MD5CryptoServiceProvider();
//Convert the input string to a byte array and computer the hash, return the hexadecimal
byte[] bytes = md5.ComputeHash(Encoding.UTF8.GetBytes(input));
string result = BitConverter.ToString(bytes).Replace("-", string.Empty);
return result.ToLower();
}
private void btnStartHash_Click(object sender, EventArgs e)
{
int loopQty = Int32.Parse(txtboxLoopQty.Text);
int i = 0;
//Create a while loop for the MD5 method below
while (i < loopQty)
{
//loop output
string HashOutput = MD5(MD5(txtboxHashOne.Text + txtboxHashTwo.Text));
txtboxHashOutput.Text = HashOutput + " " + i;
Thread HashThread = new Thread(new ThreadStart(MD5));
HashThread.Start();
i++;
}
}
Some suggestions that may help you troubleshoot and solve your problem:
First, I believe you may be trying to return result.ToLower(), a data type of string from your method named MD5, I'm guessing you were trying to use this instead of returning void, (i.e. nothing):
//MD5 Hash method
public string MD5(string input)
{
MD5 md5 = new MD5CryptoServiceProvider();
//Convert the input string to a byte array and computer the hash, return the hexadecimal
byte[] bytes = md5.ComputeHash(Encoding.UTF8.GetBytes(input));
string result = BitConverter.ToString(bytes).Replace("-", string.Empty);
return result.ToLower();
}
That may not the entire problem, so let's check to make sure your method is working by copying the code you have in your btnStartHash_Click method into a safe place, and then replacing it with a simple message to yourself.
private void btnStartHash_Click(object sender, EventArgs e)
{
//Convert the input string to a byte array and computer the hash, return the hexadecimal and display it in a message box
MessageBox.Show(MD5("abcdefg"));//parse whatever known value test
}
If you are still unsure of the hash result from your MD5 method, then start taking parts out one by one.
Build the button click up again once you're certain of desired MD5 method's output:
private void btnStartHash_Click_(object sender, EventArgs e)
{
txtboxHashOne.Text = MD5(txtboxHashInput.Text);
string hashOfHash = MD5(txtboxHashOne.Text);
txtboxHashTwo.Text = hashOfHash;
}
In the above situation I'm using the MD5 method to hash the input textbox, txtboxHashInput.Text and then change the txtboxHashOne text box to reflect the change on the form. The txboxHashOne's entire string is then hashed to make sure to make the hashOfHash string.
Instead of having each instance txtboxHashOne , txtboxHashTwo, one may think it could do better by just creating the text box programmatically on the form:
//lets say the loopqty input is the number of times I wanted to hash this
int numberOfTimesToHash = Int32.Parse(txtboxLoopQty.Text);
//x and y represent where you want them to start appearing on your form..
int x = 10;
int y = 100;
int howeverManyThreadsIWant = numberOfTimesToHash;
for (int i = 0; i < howeverManyThreadsIWant; i++)
{
TextBox textBox = new TextBox();
textBox.Location = new Point(x, y);
//Could go into a recursive function such as` MD5(Input,recursionDepth)
//But instead going to reprint same hash for demonstration purposes
textBox.Text = MD5(txtboxHashInput.Text);
//MessageBox.Show(textBox.Text);
this.Controls.Add(textBox);
y += 30;
}
Then, the programmer may want to try to embrace a multithreaded approach to reduce complexity we have to do a lot more.
For example, unfortunately it's not so simple to do this:
//##!!Don't do this!!
var thread = new Thread(() =>
{
int x = 10;
int y = 100;
int howeverManyThreadsIWant = numberOfTimesToHash;
for (int i = 0; i < howeverManyThreadsIWant; i++)
{
TextBox textBox = new TextBox();
textBox.Tag = i;
textBox.Location = new Point(x, y);
//Could go into a recursive function such as MD5(Input,recursionDepth)
//But instead going to simply reprint same hash
textBox.Text = MD5(txtboxHashInput.Text);
//MessageBox.Show(textBox.Text);
this.Controls.Add(textBox);//<--invalid operations error
y += 30;
}
});
thread.Start();
would result in:
System.InvalidOperationException: 'Cross-thread operation not valid: Control 'Form1' accessed from a thread other than the thread it was created on.'<<
Strongly consider if you really need multithreading to solve this task.
Microsoft suggests:
When to Use Multiple Threads
Multithreading can be used in many common situations to significantly improve the responsiveness and usability of your application.
You should strongly consider using multiple threads to:
#Communicate over a network, for example to a Web server, database, or remote object.
#Perform time-consuming local operations that would cause the UI to freeze.
#Distinguish tasks of varying priority.
#Improve the performance of application startup and initialization.
It is useful to examine these uses in more detail.
Communicating Over a Network
#Smart-clients may communicate over a network in a number of ways, including:
#Remote object calls, such as DCOM, RPC or .NET remoting
#Message-based communications, such as Web service calls and HTTP requests
#Distributed transactions
With that in mind, if you really need to do these things, now that you have bug free code that is hashing the way you want it, visit the Using Multiple Threads by Microsoft.
Also you may want to check out Threading in Windows Forms, this has an example that you can run with most of what you need to know.
Hopefully some of this was what you were looking for.

How to create same MD5 token in different platforms?

I am using MD5 hashing first time, I am trying to create a token to secure my web-services. I have found three different md5 hashing method for Android, IOS and C#. Before I call any webservice, I create a token and send it as a parameter. Then, when I get the token in service side, I create a token with the same algorithm in C# too and compare those two tokens. If the tokens are the same, I permit to the process. If not, I throw an exeption. My problem is, tokens are always different. I suppose that the difference of md5 creation methods causes this problem.
MD5 method in the C# code:
public static string MD5(string stringToEncrypted)
{
// step 1, calculate MD5 hash from input
var md5 = System.Security.Cryptography.MD5.Create();
byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(stringToEncrypted);
byte[] hash = md5.ComputeHash(inputBytes);
// step 2, convert byte array to hex string
var sb = new StringBuilder();
for (int i = 0; i < hash.Length; i++)
{
sb.Append(hash[i].ToString("X2"));
}
return sb.ToString();
}
In Swift Code:
extension String
{
var md5: String!
{
let str = self.cStringUsingEncoding(NSUTF8StringEncoding)
let strLen = CC_LONG(self.lengthOfBytesUsingEncoding(NSUTF8StringEncoding))
let digestLen = Int(CC_MD5_DIGEST_LENGTH)
let result = UnsafeMutablePointer<CUnsignedChar>.alloc(digestLen)
CC_MD5(str!, strLen, result)
var hash = NSMutableString()
for i in 0..<digestLen
{
hash.appendFormat("%02x", result[i])
}
result.destroy()
return String(format: hash)
}
}
In Android Code:
public static final String md5(final String stringToEncrypted)
{
final String MD5 = "MD5";
try
{
// Create MD5 Hash
MessageDigest digest = java.security.MessageDigest.getInstance(MD5);
digest.update(stringToEncrypted.getBytes());
byte messageDigest[] = digest.digest();
// Create Hex String
StringBuilder hexString = new StringBuilder();
for (byte aMessageDigest : messageDigest)
{
String h = Integer.toHexString(0xFF & aMessageDigest);
while (h.length() < 2)
h = "0" + h;
hexString.append(h);
}
return hexString.toString();
}
catch (NoSuchAlgorithmException e)
{
e.printStackTrace();
}
return "";
}
In Android using: h = "0" + h;
In IOS using: hash.appendFormat("%02x", result[i])
In C# using: sb.Append(hash[i].ToString("X2"));
Do these differences cause this problem ?
Thank you for your answers,
Best regards
Code example from SO Answer
func doSha256(#dataIn:NSData) -> NSData {
var shaOut: NSMutableData! = NSMutableData(length: Int(CC_SHA256_DIGEST_LENGTH));
CC_SHA256(dataIn.bytes, CC_LONG(dataIn.length), UnsafeMutablePointer<UInt8>(shaOut.mutableBytes));
return shaOut;
}
Obviously just change the constants for other hash methods.
If you want another format, say Base64 or hex put those conversions in a wrapper method that calls this method. It is better not to co-mingle methods, allow each to do a single thing. (Single Responsibility Principle) It also allows for easier testing and debugging.

Input string error when posting for next set of data

The other day I had my scraper working very well, when I realized that I wasn't getting enough records, I decided to search by postal code and had to change some of my code. The first POST and RESPONSE goes off without a hitch, but when I post to get the next page of results it fails on the Response.
the starting code is...
public void StartScrape()
{
List<string> a = lstPostalCodes();
for (int i = 0; i <= lstPostalCodes().Count; i++)
{
b = a[i];
FirstRequestResponse(b);
if (GoBackToStartSearch == "CONTINUEON")
StartNextRequest(GetViewState(ResponseData));
else
{
WriteDataToFile(ResponseData);
FinalClean();
}
}
}
The method that I am calling is StartNextRequest. In the StartNextRequest method is
private void GetResults(HttpWebRequest wr)
{
using (StreamReader responseReader = new StreamReader(wr.GetResponse().GetResponseStream()))
{
// Add response/results to string
ResponseData = responseReader.ReadToEnd();
}
string strFind = "<li id='nextdisabled'>";
if (ResponseData.Contains(strFind)) GoBackToStartSearch = "BACKTOSTART";
else
GoBackToStartSearch = "CONTINUEON";
}
The error that its throwing is saying that the
Input string was not in correct format
and pointing at the using (StreamReader...)
I have gotten other errors that I seem to fix, but then it creates another error which has to do with waiting for bytes to be written. I'm using Fiddler2 to give me more info on the errors, the headers are pretty much the same, I'm not seeing much of a difference, other than 1 being a request and the other a response.
I have no idea on why its saying that, I have stepped through the working code that I wrote to scrape all the data results, and compared the two. Everything looks the same. The values are all the same.
Any ideas on where I should look to fix this?

converting IP to byte/convert back to string

I'm storing an IPV4 address on a SQLSERVER 2008 database as Binary(4). So, I'm converting the values before data input (and due to company restrictions I CANNOT create functions inside the db, well thats not up for discussion).
public static byte[] IpToBin(string ip)
{
return IPAddress.Parse(ip).GetAddressBytes();
}
public static string HexToIp(string ip)
{
return new IPAddress(long.Parse(ip, NumberStyles.HexNumber)).ToString();
}
After IpToBin is called, the data generated is (for example 0x59FC09F3). When I call HexToIp the ip came reversed probably due little/big endian conversion.
Could anyone please come up with a decent solution without 50 billion lines of code?
I think the real issue here is that you are treating the raw form as a string; especially since it is binary(4), you should never have to do that: just fetch it back from the db as a byte[]. IpToBin is fine, but HexToIp should probably be:
public static IPAddress BinToIp(byte[] bin)
{
return new IPAddress(bin);
}
then: job done. But with your existing HexToIp code, you want:
return new IPAddress(new byte[] {
Convert.ToByte(ip.Substring(0,2), 16), Convert.ToByte(ip.Substring(2,2), 16),
Convert.ToByte(ip.Substring(4,2), 16), Convert.ToByte(ip.Substring(6,2), 16)}
).ToString();
public List<IPAddress> SubtractTwoIpAddresses(IPAddress a, IPAddress b, bool includeLeft = true, bool includeRight = true)
{
List<IPAddress> rv = new List<IPAddress>();
int ipA = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(IPAddress.Parse(a.ToString()).GetAddressBytes(), 0)),
ipB = IPAddress.NetworkToHostOrder(BitConverter.ToInt32(IPAddress.Parse(b.ToString()).GetAddressBytes(), 0));
if (includeLeft)
rv.Add(new IPAddress(BitConverter.GetBytes(Math.Min(ipA, ipB)).Reverse().ToArray()));
for (int i = 1; i < Math.Max(ipA, ipB) - Math.Min(ipA, ipB); i++)
rv.Add(new IPAddress(BitConverter.GetBytes(Math.Min(ipA, ipB) + i).Reverse().ToArray()));
if (includeRight)
rv.Add(new IPAddress(BitConverter.GetBytes(Math.Max(ipA, ipB)).Reverse().ToArray()));
return rv;
}

Categories

Resources