SHA256 adds \n into value - c#

I have a couple of methods to do a little encryption and it always adds a \n in the value I am comparing.
Would this be due to some new line character thingy?
public static class Security
{
public static string CreateHash(this string unHashed)
{
SHA256CryptoServiceProvider x = new SHA256CryptoServiceProvider();
byte[] data = Encoding.UTF8.GetBytes(unHashed);
data = x.ComputeHash(data);
return Encoding.UTF8.GetString(data);
}
public static bool MatchHash(this string hashData, string hashUser)
{
if (hashUser == hashData)
{
return true;
}
else
{
return false;
}
}
}
I am entering the value into one text box and running the CreateHash() to enter the value into another textbox (all for testing). I then run my comparison check from another text box.
protected void btn_dehash_Click(object sender, EventArgs e)
{
// get value entered and hash it
var matchPass = txt_password.Text.CreateHash();
// populate lbl with true or false
lbl_Name.Text = txt_hashed.Text.MatchHash(matchPass) ? "true" : "false";
}
The results I get from MD5 are ok and work as this is much shorter. I want to use a more secure method so I have used SHA256 and this is the results I get from the comparison.
Does anybody know why this is happening?

Don't turn the hash into a string! Keep it as a byte array.
The hash represents a sequence of bytes that may or may not be valid as UTF-8.
If you want a readable hash then do something similar to:
byte[] hash = x.ComputeHash(bytes);
string hashString = string.Empty;
foreach (byte x in hash)
{
// Turn each byte into it's hex equivalent (00 to FF).
hashString += String.Format("{0:x2}", x);
}
return hashString;
Or, as the comments suggest, use base 64 encoding.

Related

c# Generate Random number passing long as seed instead of int32

c# Generate Random number passing long as a seed instead of int32, but l need to pass phone numbers or accounts number
https://learn.microsoft.com/en-us/dotnet/api/system.random.-ctor?view=netframework-4.8#System_Random__ctor_System_Int32_
Please suggest any reliable NuGet package which does this or any implementation who has already done something like this.
I need to pass the complete PhoneNumber as the seed which I'm able to do in python but not with C# and my code stack is all in C#
using System;
public class Program
{
public static void Main()
{
int seed = 0123456789;
Random random = new Random(seed);
double result = random.NextDouble();
Console.WriteLine(result);
}
}
Some insights on my requirements and what I'm trying to achieve:
1)We're doing this for A/B testing and todo data analysis on the
experience of two services.
2)When a request comes with
phoneNumber based on random.NextDouble() there is a preset percentage
which we use to determine whether to send a request to service A or
service B
3)For example, let's says the request comes and falls
under >0.5 then we direct the request to service A and the next time
the request with the same phone number comes in it will be >0.5 and
goes service A since the seed is a unique hash of phoneNumber.
The method GetHashCode() belongs to Object class, it has nothing to do with random number generation. Please read here (https://learn.microsoft.com/en-us/dotnet/api/system.object.gethashcode?view=netframework-4.8). The documentation clearly states that it is possible to get collisions specially if input is consistent.
The method HashAlgorithm.ComputeHash (documented here - https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.hashalgorithm.computehash?view=netframework-4.8) calculates the hash for a given value, but it is consistent in nature, i.e. if input is same, generated output is also same. Obviously this is not the desired output (I assume). I have attached the sample code I tried to generate this.
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
while (true)
{
Console.WriteLine("Enter a 9 digit+ number to calculate hash");
var val = Console.ReadLine();
long target = 0;
bool result = long.TryParse(val,out target);
if (result)
{
var calculatedHash = OutputHash(target);
Console.WriteLine("Calculated hash is : " + calculatedHash);
}
else
{
Console.WriteLine("Incorrect input. Please try again.");
}
}
}
public static string OutputHash(long number)
{
string source = Convert.ToString(number);
string hash;
using (SHA256 sha256Hash = SHA256.Create())
{
hash = GetHash(sha256Hash, source);
Console.WriteLine($"The SHA256 hash of {source} is: {hash}.");
Console.WriteLine("Verifying the hash...");
if (VerifyHash(sha256Hash, source, hash))
{
Console.WriteLine("The hashes are the same.");
}
else
{
Console.WriteLine("The hashes are not same.");
}
}
return hash;
}
private static string GetHash(HashAlgorithm hashAlgorithm, string input)
{
// Convert the input string to a byte array and compute the hash.
byte[] data = hashAlgorithm.ComputeHash(Encoding.UTF8.GetBytes(input));
// Create a new Stringbuilder to collect the bytes
// and create a string.
var sBuilder = new StringBuilder();
// Loop through each byte of the hashed data
// and format each one as a hexadecimal string.
for (int i = 0; i < data.Length; i++)
{
sBuilder.Append(data[i].ToString("x2"));
}
// Return the hexadecimal string.
return sBuilder.ToString();
}
// Verify a hash against a string.
private static bool VerifyHash(HashAlgorithm hashAlgorithm, string input, string hash)
{
// Hash the input.
var hashOfInput = GetHash(hashAlgorithm, input);
// Create a StringComparer an compare the hashes.
StringComparer comparer = StringComparer.OrdinalIgnoreCase;
return comparer.Compare(hashOfInput, hash) == 0;
}
I agree with #Knoop 's comment above that you might end up with same integer mapping to multiple long number input values.
If you are looking for a 'pure' random number generator with long value as seed, you don't have a choice but to go for third party libraries (or implementing your own custom algorithm). However, rather than getting into such complexities, simple
Guid g = Guid.NewGuid();
should do the trick (https://learn.microsoft.com/en-us/dotnet/api/system.guid.newguid?view=netframework-4.8).
Documentation (https://learn.microsoft.com/en-gb/windows/win32/api/combaseapi/nf-combaseapi-cocreateguid?redirectedfrom=MSDN )says that even this can end up having collisions but chances are very minimal.
Finally, this sounds like potential duplicate of .NET unique object identifier
take the hash of the phone number, eg:
var phoneNumber = 123456789L;
var seed = phoneNumber.GetHashCode();
This means that for the same phoneNumber you will get the same sequence. It also means that for some phone numbers you will get identical sequences, but that is going to be slim. And it might be different on different .net runtimes as commented, but you might not care.
Not sure why you want to, but I there are reasons, e.g. test code

Convert string to ASCII without exceptions (like TryParse)

I am implementing a TryParse() method for an ASCII string class. The method takes a string and converts it to a C-style string (i.e. a null-terminated ASCII string).
I had been using only a Parse(), doing the conversion to ASCII using::
public static bool Parse(string s, out byte[] result)
{
result = null;
if (s == null || s.Length < 1)
return false;
byte[]d = new byte[s.Length + 1]; // Add space for null-terminator
System.Text.Encoding.ASCII.GetBytes(s).CopyTo(d, 0);
// GetBytes can throw exceptions
// (so can CopyTo() but I can replace that with a loop)
result = d;
return true;
}
However, as part of the idea of a TryParse is to remove the overhead of exceptions, and GetBytes() throws exceptions, I'm looking for a different method that does not do so.
Maybe there is a TryGetbytes()-like method?
Or maybe we can reason about the expected format of a standard .Net string and perform the change mathematically (I'm not overly familiar with UTF encodings)?
EDIT: I guess for non-ASCII chars in the string, the TryParse() method should return false
EDIT: I expect when I get around to implementing the ToString() method for this class I may need to do the reverse there.
Two options:
You could just ignore Encoding entirely, and write the loop yourself:
public static bool TryParse(string s, out byte[] result)
{
result = null;
// TODO: It's not clear why you don't want to be able to convert an empty string
if (s == null || s.Length < 1)
{
return false;
}
byte buffer = new byte[s.Length + 1]; // Add space for null-terminator
for (int i = 0; i < s.Length; i++)
{
char c = s[i];
if (c > 127)
{
return false;
}
buffer[i] = (byte) c;
}
result = buffer;
return true;
}
That's simple, but may be slightly slower than using Encoding.GetBytes.
The second option would be to use a custom EncoderFallback:
public static bool TryParse(string s, out byte[] result)
{
result = null;
// TODO: It's not clear why you don't want to be able to convert an empty string
if (s == null || s.Length < 1)
{
return false;
}
var fallback = new CustomFallback();
var encoding = new ASCIIEncoding { EncoderFallback = fallback };
byte buffer = new byte[s.Length + 1]; // Add space for null-terminator
// Use overload of Encoding.GetBytes that writes straight into the buffer
encoding.GetBytes(s, 0, s.Length, buffer, 0);
if (fallback.HadErrors)
{
return false;
}
result = buffer;
return true;
}
That would require writing CustomFallback though - it would need to basically keep track of whether it had ever been asked to handle invalid input.
If you didn't mind an encoding processing the data twice, you could call Encoding.GetByteCount with a UTF-8-based encoding with a replacement fallback (with a non-ASCII replacement character), and check whether that returns the same number of bytes as the number of chars in the string. If it does, call Encoding.ASCII.GetBytes.
Personally I'd go for the first option unless you have reason to believe it's too slow.
There are two possible exceptions that Encoding.GetBytes might throw according to the documentation.
ArgumentNullException is easily avoided. Do a null check on your input and you can ensure this is never thrown.
EncoderFallbackException needs a bit more investigation... Reading the documentation:
A fallback strategy determines how an encoder handles invalid characters or how a decoder handles invalid bytes.
And if we looking in the documentation for ASCII encoding we see this:
It uses replacement fallback to replace each string that it cannot encode and each byte that it cannot decode with a question mark ("?") character.
That means it doesn't use the Exception Fallback and thus will never throw an EncoderFallbackException.
So in summary if you are using ASCII encoding and ensure you don't pass in a null string then you will never have an exception thrown by the call to GetBytes.
The GetBytes method is throwing an exception because your Encoding.EncoderFallback specifies that it should throw an exception.
Create an encoding object with EncoderReplacementFallback to avoid exceptions on unencodable characters.
Encoding encodingWithFallback = new ASCIIEncoding() { DecoderFallback = DecoderFallback.ReplacementFallback };
encodingWithFallback.GetBytes("Hɘ££o wor£d!");
This way imitates the TryParse methods of the primitive .NET value types:
bool TryEncodingToASCII(string s, out byte[] result)
{
if (s == null || Regex.IsMatch(s, "[^\x00-\x7F]")) // If a single ASCII character is found, return false.
{
result = null;
return false;
}
result = Encoding.ASCII.GetBytes(s); // Convert the string to ASCII bytes.
return true;
}

Create a hash from an id and sign it

Our user recieve emails with a prepared hyperlink.
This hyperlink has a parameter.
When the user clicks the hyperlink I need to make sure that the user did not tamper with the parameter.
The parameter is a simple integer.
I would like to create a hash from the integer.
I would like to sign the hash.
What are the current .NET classes I should use for this task?
The easiest way to do this is use a HMAC ("keyed-hash message authentication code").
public static string CreateHMAC(int data, byte[] key)
{
using(var hmac = new HMACSHA1(key))
{
var dataArray = BitConverter.GetBytes(data);
var resultArray = hmac.ComputeHash(dataArray);
return Convert.ToBase64String(resultArray);
}
}
You keep key secret on your server, and pass data and the result of CreateHMAC to the user in the URL. When the user clicks the link you verify that the data was not modified.
public static bool VerifyHMAC(int data, byte[] key, string verification)
{
using(var hmac = new HMACSHA1(key))
{
var dataArray = BitConverter.GetBytes(data);
var computedHash = hmac.ComputeHash(dataArray);
var verificationHash = Convert.FromBase64String(verification);
for (int i = 0; i < verificationHash.Length; i++)
{
if (computedHash[i] != verificationHash[i])
{
return false;
}
}
return true;
}
}
You can see here how to calculate the hash.
Since HASH functions accepts only ARRAYS, I advice you to create an array of ONE single item, with your integer there.
You may "sign" the input calculating the HASH of the calculated HASH above PLUS a constant of your application (or date and hour, for instance)

byte.Parse (c#) : FormatException on Hexadecimal string

I'm actually trying to implement a very simple login mecanism for an app I'm developping in Visual C# .NET 2.0 on an embedded device. After some researches, I've found on the msdn a code sample performing password hashing :
How to store passwords
Unfortunately, when I try to use it, that code sample is raising a FormatException on the call to byte.Parse on the substrings of the hexadecimal string SaltValue. I really have trouble to understand why, since I haven't done any change to the code.
Here is the code :
using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography;
using System.Globalization;
private const int SaltValueSize = 4;
private static string GenerateSaltValue()
{
UnicodeEncoding utf16 = new UnicodeEncoding();
if (utf16 != null)
{
// Create a random number object seeded from the value
// of the last random seed value. This is done
// interlocked because it is a static value and we want
// it to roll forward safely.
Random random = new Random(unchecked((int)DateTime.Now.Ticks));
if (random != null)
{
// Create an array of random values.
byte[] saltValue = new byte[SaltValueSize];
random.NextBytes(saltValue);
// Convert the salt value to a string. Note that the resulting string
// will still be an array of binary values and not a printable string.
// Also it does not convert each byte to a double byte.
//Original line :
//string saltValueString = utf16.GetString(saltValue);
//Replaced by :
string saltValueString = utf16.GetString(saltValue, 0, SaltValueSize);
// Return the salt value as a string.
return saltValueString;
}
}
return null;
}
private static string HashPassword(string clearData, string saltValue, HashAlgorithm hash)
{
UnicodeEncoding encoding = new UnicodeEncoding();
if (clearData != null && hash != null && encoding != null)
{
// If the salt string is null or the length is invalid then
// create a new valid salt value.
if (saltValue == null)
{
// Generate a salt string.
saltValue = GenerateSaltValue();
}
// Convert the salt string and the password string to a single
// array of bytes. Note that the password string is Unicode and
// therefore may or may not have a zero in every other byte.
byte[] binarySaltValue = new byte[SaltValueSize];
//FormatException raised here
binarySaltValue[0] = byte.Parse(saltValue.Substring(0, 2), System.Globalization.NumberStyles.HexNumber, CultureInfo.InvariantCulture.NumberFormat);
binarySaltValue[1] = byte.Parse(saltValue.Substring(2, 2), System.Globalization.NumberStyles.HexNumber, CultureInfo.InvariantCulture.NumberFormat);
binarySaltValue[2] = byte.Parse(saltValue.Substring(4, 2), System.Globalization.NumberStyles.HexNumber, CultureInfo.InvariantCulture.NumberFormat);
binarySaltValue[3] = byte.Parse(saltValue.Substring(6, 2), System.Globalization.NumberStyles.HexNumber, CultureInfo.InvariantCulture.NumberFormat);
//...
//Some more code
//...
}
}
I only have changed one line :
string saltValueString = utf16.GetString(saltValue);
to
string saltValueString = utf16.GetString(saltValue, 0, SaltValueSize);
because the first version of the method doesn't seem to be available for embedded C#. But anyway I've tested without changing this line (on a non-embedded environment), and it still was raising a FormatException.
I've copied the SaltValueSize value from that other msdn code sample (which is related) :
How to validate passwords
The test that raises the exception :
HashPassword("youpi", null, new SHA1CryptoServiceProvider());
The problem lies in the fact that your GenerateSaltValue method does not return string of hexademical numbers.
It returns string of some random symbols, that may or usually may not be valid hexademical symbols - for me it created string of mostly Chinese hieroglyphs that for sure aren't parseable by Byte.Parse method.
Also, your example pertains to Microsoft Commerce Server - I have no idea whatsoever it is.
"SOLUTION:"
I am not sure what all this examples wants to accomplish with this string-tohex-tobinary conversions, but for it to successfully execute the GenerateSaltValue should be something like:
public static string ByteArrayToString(byte[] byteArray)
{
StringBuilder hex = new StringBuilder(byteArray.Length * 2);
foreach (byte b in byteArray)
hex.AppendFormat("{0:x2}", b);
return hex.ToString();
}
// Renamed GenerateSaltValue method
private static string GenerateHexSaltString()
{
Random random = new Random();
// Create an array of random values.
byte[] saltValue = new byte[SaltValueSize];
random.NextBytes(saltValue);
string saltValueString = ByteArrayToString(saltValue);
// Return the salt value as a string.
return saltValueString;
}
And your program will "work", thanks to How do you convert Byte Array to Hexadecimal String, and vice versa?
BUT:
Using Random for Salt creation is a bad idea.
string-tohex-tobinary conversion looks even worser.
And other problems...
SO:
Read some articles that really pertains to C# password hashing and encryption, like:
Hash and salt passwords in C#
And be very attentive while searching for code examples - they could use another version, platform or even language. Good luck.

How to display text being held in a int variable?

My variable holds some text but is currently being stored as an int (the class used reads the bytes at a memory address and converts to int. Variable.ToString just displays the decimal representation, but doesn't encode it to readable text, or in other words, I would now like to convert the data from int to string with ascii encoding or something.
Here is a demo (based on our Q+A above).
Note: Settings a string with the null terminator as a test, then encoding it into ASCII bytes, then using unsafe (you will need to allow that in Build Option in project properties), itearte through each byte and convert it until 0x0 is reached.
private void button1_Click(object sender, EventArgs e)
{
var ok = "OK" + (char)0;
var ascii = Encoding.ASCII;
var bin = ascii.GetBytes( ok );
var sb = new StringBuilder();
unsafe
{
fixed (byte* p = bin)
{
byte b = 1;
var i = 0;
while (b != 0)
{
b = p[i];
if (b != 0) sb.Append( ascii.GetString( new[] {b} ) );
i++;
}
}
}
Console.WriteLine(sb);
}
Note the FIXED statement, this is required managed strings/arrayts etc are not guaranteed to be statically placed in memory - this ensures it during that section.
assuming an int variable
int x=10;
you can convert this into string as
string strX = x.ToString();
Try this
string s = "9quali52ty3";
byte[] ASCIIValues = Encoding.ASCII.GetBytes(s);
foreach(byte b in ASCIIValues) {
Console.WriteLine(b);
}
Int32.ToString() has an overload that takes a format string. Take a look at the available format strings and use one of those.
Judging by your previous question, the int you have is (probably) a pointer to the string. Depending on whether the data at the pointer is chars or bytes, do one of these to get your string:
var s = new string((char*)myInt);
var s = new string((sbyte*)myInt);
OK. If you variable is a pointer, then Tim is pointing you in the right direction (assuming it is an address and not an offset from an address - in which case you will need the start address to offset from).
If, on the other hand, your variable contains four encoded ascii characters (of a byte each), then you need to split to bytes and convert each byte to a character. Something like this Console.WriteLine(TypeDescriptor.GetConverter(myUint).ConvertTo(myUint, typeof(string))); from Here - MSDN ByteConverter

Categories