How to convert a byte array into a string that preserves lowercase? - c#

im trying to convert a byte array from a hash function into a string, i used a bitconverter.tostring() at first but it just creates a string with all uppercase bytes separated by dashes
This is my basic method
public string Hash(string password)
{
using var hasher = SHA512.Create();
{
var asBytes = Encoding.Default.GetBytes(password);
var hashed = hasher.ComputeHash(asBytes);
string stringhashed = BitConverter.ToString(hashed);
return stringhashed;
}
}
the output hashes correctly, however it gets formated into a string as BYTE-BYTE-BYTE-BYTE-BYTE....
while i needed the output to be a normal string, with lowercase and all.
Is there any way to convert a byte array into a string meeting these requirements?

Either use String.Replace() and String.ToLower() to modify the string output from BitConverter.ToString():
return stringhashed.Replace("-", "").ToLower();
... or implement your own stringification extension method:
public static class BitUtils {
public static string ToHexString(this byte[] bytes)
{
StringBuilder sb = new StringBuilder(bytes.Length * 2);
foreach(byte b in bytes)
{
// use the `x` format string to get lowercase hexadecimal
sb.AppendFormat("{0:x2}", b);
}
return sb.ToString();
}
}
So you can do:
return asBytes.ToHexString();

Related

How to convert json to hexadecimal in c#

I have json string as in example below
{"SaleToPOIRequest":{"MessageHeader":{"ProtocolVersion":"2.0","MessageClass":"Service","MessageCategory":"Login","MessageType":"Request","ServiceID":"498","SaleID":"SaleTermA","POIID":"POITerm1"},"LogoutRequest":{}}}
I want to convert json request to hexadecimal. I tried example in this link but i cannot get the exact conversion because of {,:,",} values.
Actually i can get hexadecimal return but when i reconvert to string i got return as below
{"SaleToPOIReque§7B#§²$ÖW76vTVder":{"ProtocolV¦W'6öâ#¢#"ã"Â$ÚessageClass":"Se§'f6R"Â$ÖW76vT:ategory":"Login"¢Â$ÖW76vUGR#¢*Request","Servic¤B#¢#C"Â%6ÆZID":"SaleTermA",¢%ôB#¢%ôFW&Ú1"},"LogoutReque§7B#§·×
that is not usefull for me
Is there any way to convert this?
So basically the problem is not only converting to hex but also converting back.
This is nothing more then combining 2 answers already on SO:
First for converting we use the answer given here: Convert string to hex-string in C#
Then for the converting back you can use this answer:
https://stackoverflow.com/a/724905/10608418
For you it would then look something like this:
class Program
{
static void Main(string[] args)
{
var input = "{\"SaleToPOIRequest\":{\"MessageHeader\":{\"ProtocolVersion\":\"2.0\",\"MessageClass\":\"Service\",\"MessageCategory\":\"Login\",\"MessageType\":\"Request\",\"ServiceID\":\"498\",\"SaleID\":\"SaleTermA\",\"POIID\":\"POITerm1\"},\"LogoutRequest\":{}}}";
var hex = string.Join("",
input.Select(c => String.Format("{0:X2}", Convert.ToInt32(c))));
var output = Encoding.ASCII.GetString(FromHex(hex));
Console.WriteLine($"input: {input}");
Console.WriteLine($"hex: {hex}");
Console.WriteLine($"output: {output}");
Console.ReadKey();
}
public static byte[] FromHex(string hex)
{
byte[] raw = new byte[hex.Length / 2];
for (int i = 0; i < raw.Length; i++)
{
raw[i] = Convert.ToByte(hex.Substring(i * 2, 2), 16);
}
return raw;
}
}
See it in action in a fiddle here:
https://dotnetfiddle.net/axUC5n
Hope this helps and good luck with your project
You should most probably use Encoding.Unicode to convert the string to a byte array: it's quite possible that some characters cannot be represented by ASCII chars.
Encoding.Unicode (UTF-16LE) always uses 2 bytes, so it's predictable: a sequence of 4 chars in the HEX string will always represent an UFT-16 CodePoint.
No matter what characters the input string contains.
Convert string to HEX:
string input = "Yourstring \"Ваша строка\"{あなたのひも},آپ کی تار";;
string hex = string.Concat(Encoding.Unicode.GetBytes(input).Select(b => b.ToString("X2")));
Convert back to string:
var bytes = new List<byte>();
for (int i = 0; i < hex.Length; i += 2) {
bytes.Add(byte.Parse(hex.Substring(i, 2), NumberStyles.HexNumber));
}
string original = Encoding.Unicode.GetString(bytes.ToArray());

How to XOR a MD5 hash and return a 32 character string?

How do I further encrypt a MD5 hash by XOR'ing it with a string of variable size (not bigger than 32 characters) ?
I would like the result of the XOR to be a 32 character string as well.
What i have tried so far is:
convert the md5 string to binary
convert second string to binary
pad second binary with 0's (to the left) until both binaries are of equal length
iterate the binary representations and XOR them
convert the XOR'ed result to a string
The approach may be wrong, im not sure how to do it. My problem is, when converting the result of the XOR, it is not a 32 character long string, as I would like it to be.
Sample code (equal length strings in this case):
class Program
{
static void Main(string[] args)
{
var md51 = ToBinary(ConvertToByteArray(CalculateMD5Hash("Maaa"), Encoding.ASCII));
var md52 = ToBinary(ConvertToByteArray(CalculateMD5Hash("Moo"), Encoding.ASCII));
List<int> xoredResult = new List<int>();
for (int i = 0; i < md51.Length; i++)
{
var string1 = md51[i];
var string2 = md52[i];
var xor = string1 ^ string2;
xoredResult.Add(xor);
}
var resultingString = string.Join("", xoredResult);
Console.WriteLine(resultingString.Length);
var data = GetBytesFromBinaryString(resultingString);
var text = Encoding.ASCII.GetString(data);
}
public static byte[] ConvertToByteArray(string str, Encoding encoding)
{
return encoding.GetBytes(str);
}
public static String ToBinary(Byte[] data)
{
return string.Join("", data.Select(byt => Convert.ToString(byt, 2).PadLeft(8, '0')));
}
public static Byte[] GetBytesFromBinaryString(String binary)
{
var list = new List<Byte>();
for (int i = 0; i < binary.Length; i += 8)
{
String t = binary.Substring(i, 8);
list.Add(Convert.ToByte(t, 2));
}
return list.ToArray();
}
public static string CalculateMD5Hash(string input)
{
// step 1, calculate MD5 hash from input
MD5 md5 = System.Security.Cryptography.MD5.Create();
byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(input);
byte[] hash = md5.ComputeHash(inputBytes);
// step 2, convert byte array to hex string
StringBuilder sb = new StringBuilder();
for (int i = 0; i < hash.Length; i++)
{
sb.Append(hash[i].ToString("X2"));
}
return sb.ToString();
}
}
xoring a string with what is essentially random bytes is not guaranteed to give you a valid string as a output. Your var text = Encoding.ASCII.GetString(data); is likely failing because you are passing it a non valid string in byte form. You must use something like var text = Convert.ToBase64String(data) to be able to represent the random data without loss of information in the process.

Convert character to CP1252 Hex in c#

I wrote a function to convert a string to a hex string. So "abc" would be converted to "616263".
Here is the function:
private string StringToHex(string myString)
{
int ctr, li_max;
string ls_hex = "";
li_max = myString.Length;
for(ctr = 0; ctr < li_max; ctr++)
ls_hex = ls_hex + (Convert.ToInt16(myString[ctr])).ToString("x2");
return ls_hex;
}
However, when I have unicode characters like "‹abc" I get "2039616263". So my first character is converted to 2039 (unicode). I wanted to get "8B616263" (CP1252). See image below:
How can I get the hex value for the correct encoding?
ie: 8B instead of 2039
You need to get use the CP1252 encoding to get the bytes of the string:
private string StringToHex(string myString)
{
byte[] bytes = Encoding.GetEncoding(1252).GetBytes(myString);
return string.Concat(bytes.Select(b => b.ToString("X2")));
}
My output is
8B616263

Convert Binary String to its readable equivalence C#

I have a string array that contains some binary data, and I would like to convert the binary to its equivalent character representative.
Each element inside the array contains 8 bit "1 byte" of data and I need to know how to convert it to its character equivalence
Here is the string array:
IEnumerable<string> resultChunks = Enumerable.Range(0, result.Length / 8)
.Select(x => result.Substring(x * 8, 8));
string[] newRes = resultChunks.ToArray();
string tempRes="";
for (int i = 0; i < newRes.Length; i++)
{
tempRes+=Convert.ToString(newRes[i]);
}
Current "result" is "0010001111000100001010010011101111000111001100110110011100110110"
If your data is in a byte array then you could use this:
string result = Encoding.ASCII.GetString(bytes);
I guess, your string is base64 string.
Then you can use next method:
public static string FromBase64(string base64Str, Encoding encoding = null)
{
if (string.IsNullOrWhiteSpace(base64Str))
{
return string.Empty;
}
byte[] bytes;
try
{
bytes = System.Convert.FromBase64String(base64Str);
}
catch (FormatException)
{
return string.Empty;
}
var stringEncoding = encoding ?? Encoding.UTF8;
return stringEncoding.GetString(bytes);
}

Calculate a MD5 hash from a string

I use the following C# code to calculate a MD5 hash from a string.
It works well and generates a 32-character hex string like this:
900150983cd24fb0d6963f7d28e17f72
string sSourceData;
byte[] tmpSource;
byte[] tmpHash;
sSourceData = "MySourceData";
//Create a byte array from source data.
tmpSource = ASCIIEncoding.ASCII.GetBytes(sSourceData);
tmpHash = new MD5CryptoServiceProvider().ComputeHash(tmpSource);
// and then convert tmpHash to string...
Is there a way to use code like this to generate a 16-character hex string (or 12-character string)? A 32-character hex string is good but I think it'll be boring for the customer to enter the code!
As per MSDN
Create MD5:
public static string CreateMD5(string input)
{
// Use input string to calculate MD5 hash
using (System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create())
{
byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(input);
byte[] hashBytes = md5.ComputeHash(inputBytes);
return Convert.ToHexString(hashBytes); // .NET 5 +
// Convert the byte array to hexadecimal string prior to .NET 5
// StringBuilder sb = new System.Text.StringBuilder();
// for (int i = 0; i < hashBytes.Length; i++)
// {
// sb.Append(hashBytes[i].ToString("X2"));
// }
// return sb.ToString();
}
}
// given, a password in a string
string password = #"1234abcd";
// byte array representation of that string
byte[] encodedPassword = new UTF8Encoding().GetBytes(password);
// need MD5 to calculate the hash
byte[] hash = ((HashAlgorithm) CryptoConfig.CreateFromName("MD5")).ComputeHash(encodedPassword);
// string representation (similar to UNIX format)
string encoded = BitConverter.ToString(hash)
// without dashes
.Replace("-", string.Empty)
// make lowercase
.ToLower();
// encoded contains the hash you want
Was trying to create a string representation of MD5 hash using LINQ, however, none of the answers were LINQ solutions, therefore adding this to the smorgasbord of available solutions.
string result;
using (MD5 hash = MD5.Create())
{
result = String.Join
(
"",
from ba in hash.ComputeHash
(
Encoding.UTF8.GetBytes(observedText)
)
select ba.ToString("x2")
);
}
You can use Convert.ToBase64String to convert 16 byte output of MD5 to a ~24 char string. A little bit better without reducing security. (j9JIbSY8HuT89/pwdC8jlw== for your example)
Depends entirely on what you are trying to achieve. Technically, you could just take the first 12 characters from the result of the MD5 hash, but the specification of MD5 is to generate a 32 char one.
Reducing the size of the hash reduces the security, and increases the chance of collisions and the system being broken.
Perhaps if you let us know more about what you are trying to achieve we may be able to assist more.
I suppose it is better to use UTF-8 encoding in the string MD5.
public static string MD5(this string s)
{
using var provider = System.Security.Cryptography.MD5.Create();
StringBuilder builder = new StringBuilder();
foreach (byte b in provider.ComputeHash(Encoding.UTF8.GetBytes(s)))
builder.Append(b.ToString("x2").ToLower());
return builder.ToString();
}
public static string Md5(string input, bool isLowercase = false)
{
using (var md5 = MD5.Create())
{
var byteHash = md5.ComputeHash(Encoding.UTF8.GetBytes(input));
var hash = BitConverter.ToString(byteHash).Replace("-", "");
return (isLowercase) ? hash.ToLower() : hash;
}
}
Support string and file stream.
examples
string hashString = EasyMD5.Hash("My String");
string hashFile = EasyMD5.Hash(System.IO.File.OpenRead("myFile.txt"));
-
class EasyMD5
{
private static string GetMd5Hash(byte[] data)
{
StringBuilder sBuilder = new StringBuilder();
for (int i = 0; i < data.Length; i++)
sBuilder.Append(data[i].ToString("x2"));
return sBuilder.ToString();
}
private static bool VerifyMd5Hash(byte[] data, string hash)
{
return 0 == StringComparer.OrdinalIgnoreCase.Compare(GetMd5Hash(data), hash);
}
public static string Hash(string data)
{
using (var md5 = MD5.Create())
return GetMd5Hash(md5.ComputeHash(Encoding.UTF8.GetBytes(data)));
}
public static string Hash(FileStream data)
{
using (var md5 = MD5.Create())
return GetMd5Hash(md5.ComputeHash(data));
}
public static bool Verify(string data, string hash)
{
using (var md5 = MD5.Create())
return VerifyMd5Hash(md5.ComputeHash(Encoding.UTF8.GetBytes(data)), hash);
}
public static bool Verify(FileStream data, string hash)
{
using (var md5 = MD5.Create())
return VerifyMd5Hash(md5.ComputeHash(data), hash);
}
}
Idk anything about 16 character hex strings....
using System;
using System.Security.Cryptography;
using System.Text;
But here is mine for creating MD5 hash in one line.
string hash = BitConverter.ToString(MD5.Create().ComputeHash(Encoding.ASCII.GetBytes("THIS STRING TO MD5"))).Replace("-","");
This solution requires c# 8 and takes advantage of Span<T>. Note, you would still need to call .Replace("-", string.Empty).ToLowerInvariant() to format the result if necessary.
public static string CreateMD5(ReadOnlySpan<char> input)
{
var encoding = System.Text.Encoding.UTF8;
var inputByteCount = encoding.GetByteCount(input);
using var md5 = System.Security.Cryptography.MD5.Create();
Span<byte> bytes = inputByteCount < 1024
? stackalloc byte[inputByteCount]
: new byte[inputByteCount];
Span<byte> destination = stackalloc byte[md5.HashSize / 8];
encoding.GetBytes(input, bytes);
// checking the result is not required because this only returns false if "(destination.Length < HashSizeValue/8)", which is never true in this case
md5.TryComputeHash(bytes, destination, out int _bytesWritten);
return BitConverter.ToString(destination.ToArray());
}
Here is my utility function for UTF8, which can be replaced with ASCII if desired:
public static byte[] MD5Hash(string message)
{
return MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(message));
}
A MD5 hash is 128 bits, so you can't represent it in hex with less than 32 characters...
System.Text.StringBuilder hash = new System.Text.StringBuilder();
System.Security.Cryptography.MD5CryptoServiceProvider md5provider = new System.Security.Cryptography.MD5CryptoServiceProvider();
byte[] bytes = md5provider.ComputeHash(new System.Text.UTF8Encoding().GetBytes(YourEntryString));
for (int i = 0; i < bytes.Length; i++)
{
hash.Append(bytes[i].ToString("x2")); //lowerCase; X2 if uppercase desired
}
return hash.ToString();
A faster alternative of existing answer for .NET Core 2.1 and higher:
public static string CreateMD5(string s)
{
using (System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create())
{
var encoding = Encoding.ASCII;
var data = encoding.GetBytes(s);
Span<byte> hashBytes = stackalloc byte[16];
md5.TryComputeHash(data, hashBytes, out int written);
if(written != hashBytes.Length)
throw new OverflowException();
Span<char> stringBuffer = stackalloc char[32];
for (int i = 0; i < hashBytes.Length; i++)
{
hashBytes[i].TryFormat(stringBuffer.Slice(2 * i), out _, "x2");
}
return new string(stringBuffer);
}
}
You can optimize it even more if you are sure that your strings are small enough and replace encoding.GetBytes by unsafe int GetBytes(ReadOnlySpan chars, Span bytes) alternative.
Extending Anant Dabhi's answer
a helper method:
using System.Text;
namespace XYZ.Helpers
{
public static class EncryptionHelper
{
public static string ToMD5(this string input)
{
// Use input string to calculate MD5 hash
using (System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create())
{
byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(input);
byte[] hashBytes = md5.ComputeHash(inputBytes);
// Convert the byte array to hexadecimal string
StringBuilder sb = new StringBuilder();
for (int i = 0; i < hashBytes.Length; i++)
{
sb.Append(hashBytes[i].ToString("X2"));
}
return sb.ToString();
}
}
}
}
I'd like to offer an alternative that appears to perform at least 10% faster than craigdfrench's answer in my tests (.NET 4.7.2):
public static string GetMD5Hash(string text)
{
using ( var md5 = MD5.Create() )
{
byte[] computedHash = md5.ComputeHash( Encoding.UTF8.GetBytes(text) );
return new System.Runtime.Remoting.Metadata.W3cXsd2001.SoapHexBinary(computedHash).ToString();
}
}
If you prefer to have using System.Runtime.Remoting.Metadata.W3cXsd2001; at the top, the method body can be made an easier to read one-liner:
using ( var md5 = MD5.Create() )
{
return new SoapHexBinary( md5.ComputeHash( Encoding.UTF8.GetBytes(text) ) ).ToString();
}
Obvious enough, but for completeness, in OP's context it would be used as:
sSourceData = "MySourceData";
tmpHash = GetMD5Hash(sSourceData);
https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.md5?view=netframework-4.7.2
using System;
using System.Security.Cryptography;
using System.Text;
static string GetMd5Hash(string input)
{
using (MD5 md5Hash = MD5.Create())
{
// Convert the input string to a byte array and compute the hash.
byte[] data = md5Hash.ComputeHash(Encoding.UTF8.GetBytes(input));
// Create a new Stringbuilder to collect the bytes
// and create a string.
StringBuilder 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.
static bool VerifyMd5Hash(string input, string hash)
{
// Hash the input.
string hashOfInput = GetMd5Hash(input);
// Create a StringComparer an compare the hashes.
StringComparer comparer = StringComparer.OrdinalIgnoreCase;
return 0 == comparer.Compare(hashOfInput, hash);
}
StringBuilder sb= new StringBuilder();
for (int i = 0; i < tmpHash.Length; i++)
{
sb.Append(tmpHash[i].ToString("x2"));
}
public static string GetMD5(string encryptString)
{
var passByteCrypt = new MD5CryptoServiceProvider().ComputeHash(Encoding.UTF8.GetBytes(encryptString));
return ByteArrayToString(passByteCrypt);
}
public static string ByteArrayToString(byte[] bytes)
{
var output = new StringBuilder(bytes.Length);
foreach (var t in bytes)
{
output.Append(t.ToString("X2"));
}
return output.ToString().ToLower();
}
this is simple md5 ByteCrypt
If you are using a version lower than .NET5 this is a neat way to write it
string.Concat(yourHashBytes.Select(x => x.ToString("X2")))
Here is a condensed version.
private string CreateMD5(string myText)
{
var hash = System.Security.Cryptography.MD5.Create()
.ComputeHash(System.Text.Encoding.ASCII.GetBytes(myText ?? ""));
return string.Join("", Enumerable.Range(0, hash.Length).Select(i => hash[i].ToString("x2")));
}

Categories