C# String to Byte[] - c#

I want to convert a string to byte and output it as byte array.
example: string: 3074 output: 0C02
private static byte[] ConvertHexToBytes(string input)
{
var result = new byte[(input.Length + 1) / 2];
var offset = 0;
if (input.Length % 2 == 1)
{
result[0] = (byte)Convert.ToUInt32(input[0] + "", 16);
offset = 1;
}
for (int i = 0; i < input.Length / 2; i++)
{
result[i + offset] = (byte)Convert.ToUInt32(input.Substring(i * 2 + offset, 2), 16);
}
return result;
}
private static void SetValue(string input)
{
byte[] port = ConvertHexToBytes(input);
byte[] port = new byte[] { byte.Parse("" + port[0]), byte.Parse("" + port[1]) };
}
I am getting 3074 instead of the 0C02.
Just figured it out, here is my code
private static void SetValue(string input)
{
byte[] port = BitConverter.GetBytes(int.Parse(input));
byte[] res= new byte[] { port[1], port[0] };
}

It seems you're working with int, not string ("I want to convert a string to byte...")
int input = 3074; // 00 00 0C 02
And you want to trim leading zeroes and get "0C02" string; you can do it with a help of Linq:
byte[] result =
(BitConverter.IsLittleEndian
? BitConverter.GetBytes(input).Reverse()
: BitConverter.GetBytes(input))
.SkipWhile(b => b == 0)
.DefaultIfEmpty() // we don't want trim all in case of input == 0
.ToArray();
Test:
// "0C02"
Console.WriteLine(string.Concat(result.Select(b => b.ToString("X2"))));
Combining it all into the proposed method:
private static void SetValue(string input) {
byte[] res =
(BitConverter.IsLittleEndian
? BitConverter.GetBytes(int.Parse(input)).Reverse()
: BitConverter.GetBytes(int.Parse(input)))
.SkipWhile(b => b == 0)
.DefaultIfEmpty() // we don't want trim all in case of input == 0
.ToArray();
// Console.WriteLine(string.Concat(res.Select(b => b.ToString("X2"))));
//TODO: relevant code here
}

A solution which will work independent of the endianess of your system architecture which will make things more portable:
byte[] bytes = BitConverter.GetBytes(input);
if (BitConverter.IsLittleEndian)
Array.Reverse(bytes);
Console.WriteLine("byte array: " +
BitConverter.ToString(bytes).Replace("-", string.Empty));

Related

C# reading a byte array as a string

I am coding in c#.
I need to read the string of bytes without converting.
bytes: 68
string: 44
I want to be able to convert it through code
I figured it out
#region "Grab Bytes Function"
private string grabBytes(byte[] buffer)
{
byte[] bytes = buffer;
string output = string.Empty;
foreach (byte item in bytes)
{
output += Convert.ToString(item, 16).ToUpper().PadLeft(2, '0');
}
return output;
}
#endregion
#region "Grab String Function"
private string grabString(byte[] buffer)
{
byte[] bytes = buffer;
string output = string.Empty;
foreach (byte item in bytes)
{
for (int i = 0; i < 255; i++)
{
if (grabBytes(new byte[] { item }) == grabBytes(new byte[] { byte.Parse(i.ToString()) }))
output += item + ".";
}
}
string output1 = output.Remove(output.Count() - 1, 1);
if (output1 != "0.0.0.0")
return output1;
else
return "";
}
#endregion
Your code is equivalent to this one:
private string grabString(byte[] buffer)
{
var asDecimal = string.Join(".", buffer));
return (asDecimal == "0.0.0.0" ? "" : asDecimal);
}

C# coding: hexadecimal to decimal & character encoding

Below is the code(conversion of hexadecimal to decimal) I'm trying to work out ..
I found error which appears in place I've commented in the code..
Please provide a solution to rectify ..
static void Main(string[] args)
{
byte[] byteData;
int n;
byteData = GetBytesFromHexString("001C0014500C0A5B06A4FFFFFFFFFFFFFFFFFFFFFFFFFFFF");
n = byteData.Length;
Console.WriteLine(n);
string s = System.Text.Encoding.UTF8.GetString(byteData, 0, n); //error
Console.WriteLine(s);
Console.ReadLine();
}
public static byte[] GetBytesFromHexString(string hexString)
{
//MessageBox.Show("getbytes ");
if (hexString == null)
return null;
if (hexString.Length % 2 == 1)
hexString = '0' + hexString; // Up to you whether to pad the first or last byte
byte[] data = new byte[hexString.Length / 2];
for (int i = 0; i < data.Length; i++)
{
data[i] = Convert.ToByte(hexString.Substring(i * 2, 2), 16);
Console.WriteLine(data[i]);
}
What I'm getting as output is:
"\0\0P\f\n[���������������"
The converted decimal value is not been encoded.
UPDATE:
Expected output is "0 28 0 20 80 12 10 91 6 164 255 255 255 255 255 255 255 255 255 255 255 255 255 255"
Instead of
string s = System.Text.Encoding.UTF8.GetString(byteData, 0, n);
write
string s = String.Join(" ", byteData);
You can use this and try to play with the radix ( in this case 2 ). This snippet, which I once wrote, helped me all the time.
private void ConvHexStringToBitString(ref string strErrorBitMask)
{
try
{
string strTempStr = strErrorBitMask;
if (strTempStr != string.Empty)
{
strTempStr = Convert.ToString(Convert.ToInt32(strTempStr.Replace(" ", "0"), 16), 2);
}
strErrorBitMask = strTempStr.PadLeft(32, '0');
}
catch (Exception ex)
{
LogWithMsg(ex);
}
}

Trying to reproduce PHP's pack("H*") function in C#

this is my code in C# :
public static String MD5Encrypt(String str, Boolean raw_output=false)
{
// Use input string to calculate MD5 hash
String output;
MD5 md5 = System.Security.Cryptography.MD5.Create();
byte[] inputBytes = System.Text.Encoding.ASCII.GetBytes(str);
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"));
}
output = sb.ToString();
if (raw_output)
{
output = pack(output);
}
return output;
}
public static String pack(String S)
{
string MultiByte = "";
for (int i = 0; i <= S.Length - 1; i += 2)
{
MultiByte += Convert.ToChar(HexToDec(S.Substring(i, 2)));
}
return MultiByte;
}
private static int HexToDec(String hex)
{
//Int32.Parse(hexString, System.Globalization.NumberStyles.HexNumber);
return Convert.ToInt32(hex, 16);
}
To reproduce what is done in php by this way :
md5($str, true);
OR
pack('H*', md5( $str ));
I tried many things but can't get the same on the two sides in some cases of word.
For example, Trying this test on the string "8tv7er5j"
PHP Side :
9c36ad446f83ca38619e12d9e1b3c39e <= md5("8tv7er5j");
œ6­DoƒÊ8ažÙá³Ãž <= md5("8tv7er5j", true) or pack("H*", md5("8tv7er5j"))
C# Side :
9c36ad446f83ca38619e12d9e1b3c39e <= MD5Encrypt("8tv7er5j")
6­DoÊ8aÙá³Ã <= MD5Encrypt("8tv7er5j", true) or pack( MD5Encrypt("8tv7er5j") )
Why ? Encoding problem ?
EDIT 1 :
I have the good result, but bad encoded with this this function for pack() :
if ((hex.Length % 2) == 1) hex += '0';
byte[] bytes = new byte[hex.Length / 2];
for (int i = 0; i < hex.Length; i += 2)
{
bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
}
return bytes;
So, System.Text.Encoding.UTF8.GetString(bytes) give me :
�6�Do��8a���Þ
And System.Text.Encoding.ASCII.GetString(bytes)
?6?Do??8a??????
...
I encountered same scenario where I am in need of php's pack-unpack-md5 functions in C#. Most important was that I need to match out of all these 3 functions with php.
I created my own functions and then validated(verified) my output with functions at onlinephpfunctions.com. The output was same when I parsed with DefaultEncoding. FYI, I checked my application's encoding(Encoding.Default.ToString()) and it was System.Text.SBCSCodePageEncoding
Pack
private static string pack(string input)
{
//only for H32 & H*
return Encoding.Default.GetString(FromHex(input));
}
public static byte[] FromHex(string hex)
{
hex = hex.Replace("-", "");
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;
}
MD5
private static string md5(string input)
{
byte[] asciiBytes = Encoding.Default.GetBytes(input);
byte[] hashedBytes = MD5CryptoServiceProvider.Create().ComputeHash(asciiBytes);
string hashedString = BitConverter.ToString(hashedBytes).Replace("-", "").ToLower();
return hashedString;
}
Unpack
private static string unpack(string p1, string input)
{
StringBuilder output = new StringBuilder();
for (int i = 0; i < input.Length; i++)
{
string a = Convert.ToInt32(input[i]).ToString("X");
output.Append(a);
}
return output.ToString();
}
PS: User can enhance these functions with other formats
I guess that PHP defaults to Latin1 so the code should look like :
public static String PhpMd5Raw(string str)
{
var md5 = System.Security.Cryptography.MD5.Create();
var inputBytes = System.Text.Encoding.ASCII.GetBytes(str);
var hashBytes = md5.ComputeHash(inputBytes);
var latin1Encoding = System.Text.Encoding.GetEncoding("ISO-8859-1");
return latin1Encoding.GetString(hashBytes);
}
If you are going to feed the result as a key for HMAC-SHA1 hashing keep it as bytes[] and initialize the HMACSHA1 with the return value of this function: DO NOT convert it to a string and back to bytes, I have spent hours because of this mistake.
public static byte[] PackH(string hex)
{
if ((hex.Length % 2) == 1) hex += '0';
byte[] bytes = new byte[hex.Length / 2];
for (int i = 0; i < hex.Length; i += 2)
{
bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
}
return bytes;
}
I know this is an old question. I am posting my answer for anyone who might reach this page searching for it.
The following code is the full conversion of the pearl function pack("H*") to c#.
public static String Pack(String input)
{
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.UTF7.GetString(hashBytes); // for perl/php
}
I'm sorry. I didn't go with the questions completely. But if php code is as below,
$testpack = pack("H*" , "you value");
and if can't read the $testpack values(due to some non support format), then first do base64_encode as below and echo it.
echo base64_encode($testpack);
Then use Risky Pathak answer. For complete this answer I'll post his answer with some small modification like base 64 encoding etc.
var hex = "you value";
hex = hex.Replace("-", "");
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);
}
var res = Convert.ToBase64String(raw);
Console.WriteLine(res);
Now if you compare both of values, those should be similar.
And all credit should go to the Risky Pathak answer.
The same in c# can be reached with Hex.Decode() method.
And bin2hex() in php is Hex.Encode().

Hash SHA1 large files (over 2gb) in C#

I`m looking for solution for hashing large file content (files may be over 2gb in 32bit os). It there any easy solution for that? Or just reading by part and loading to buffer?
Driis's solution sounds more flexible, but HashAlgorithm.ComputeHash will also accept Streams as parameters.
Use TransformBlock and TransformFinalBlock to calculate the hash block by block, so you won't need to read the entire file into memory. (There is a nice example in the first link - and another one in this previous question).
If you choose to use TransformBlock, then you can safely ignore the last parameter and set the outputBuffer to null. TransformBlock will copy from the input to the output array - but why would you want to simply copy bits for no good reason?
Furthermore, all mscorlib HashAlgorithms work as you might expect, i.e. the block size doesn't seem to affect the hash output; and whether you pass the data in one array and then hash in chunks by changing the inputOffset or you hash by passing smaller, separate arrays doesn't matter. I verified this using the following code:
(this is slightly long, just here so people can verify for themselves that HashAlgorithm implementations are sane).
public static void Main() {
RandomNumberGenerator rnd = RandomNumberGenerator.Create();
byte[] input = new byte[20];
rnd.GetBytes(input);
Console.WriteLine("Input Data: " + BytesToStr(input));
var hashAlgoTypes = Assembly.GetAssembly(typeof(HashAlgorithm)).GetTypes()
.Where(t => typeof(HashAlgorithm).IsAssignableFrom(t) && !t.IsAbstract);
foreach (var hashType in hashAlgoTypes)
new AlgoTester(hashType).AssertOkFor(input.ToArray());
}
public static string BytesToStr(byte[] bytes) {
StringBuilder str = new StringBuilder();
for (int i = 0; i < bytes.Length; i++)
str.AppendFormat("{0:X2}", bytes[i]);
return str.ToString();
}
public class AlgoTester {
readonly byte[] key;
readonly Type type;
public AlgoTester(Type type) {
this.type=type;
if (typeof(KeyedHashAlgorithm).IsAssignableFrom(type))
using(var algo = (KeyedHashAlgorithm)Activator.CreateInstance(type))
key = algo.Key.ToArray();
}
public HashAlgorithm MakeAlgo() {
HashAlgorithm algo = (HashAlgorithm)Activator.CreateInstance(type);
if (key != null)
((KeyedHashAlgorithm)algo).Key = key;
return algo;
}
public byte[] GetHash(byte[] input) {
using(HashAlgorithm sha = MakeAlgo())
return sha.ComputeHash(input);
}
public byte[] GetHashOneBlock(byte[] input) {
using(HashAlgorithm sha = MakeAlgo()) {
sha.TransformFinalBlock(input, 0, input.Length);
return sha.Hash;
}
}
public byte[] GetHashMultiBlock(byte[] input, int size) {
using(HashAlgorithm sha = MakeAlgo()) {
int offset = 0;
while (input.Length - offset >= size)
offset += sha.TransformBlock(input, offset, size, input, offset);
sha.TransformFinalBlock(input, offset, input.Length - offset);
return sha.Hash;
}
}
public byte[] GetHashMultiBlockInChunks(byte[] input, int size) {
using(HashAlgorithm sha = MakeAlgo()) {
int offset = 0;
while (input.Length - offset >= size)
offset += sha.TransformBlock(input.Skip(offset).Take(size).ToArray()
, 0, size, null, -24124512);
sha.TransformFinalBlock(input.Skip(offset).ToArray(), 0
, input.Length - offset);
return sha.Hash;
}
}
public void AssertOkFor(byte[] data) {
var direct = GetHash(data);
var indirect = GetHashOneBlock(data);
var outcomes =
new[] { 1, 2, 3, 5, 10, 11, 19, 20, 21 }.SelectMany(i =>
new[]{
new{ Hash=GetHashMultiBlock(data,i), Name="ByMSDN"+i},
new{ Hash=GetHashMultiBlockInChunks(data,i), Name="InChunks"+i}
}).Concat(new[] { new { Hash = indirect, Name = "OneBlock" } })
.Where(result => !result.Hash.SequenceEqual(direct)).ToArray();
Console.Write("Testing: " + type);
if (outcomes.Any()) {
Console.WriteLine("not OK.");
Console.WriteLine(type.Name + " direct was: " + BytesToStr(direct));
} else Console.WriteLine(" OK.");
foreach (var outcome in outcomes)
Console.WriteLine(type.Name + " differs with: " + outcome.Name + " "
+ BytesToStr(outcome.Hash));
}
}

How to convert a string of bits to byte array

I have a string representing bits, such as:
"0000101000010000"
I want to convert it to get an array of bytes such as:
{0x0A, 0x10}
The number of bytes is variable but there will always be padding to form 8 bits per byte (so 1010 becomes 000010101).
Use the builtin Convert.ToByte() and read in chunks of 8 chars without reinventing the thing..
Unless this is something that should teach you about bitwise operations.
Update:
Stealing from Adam (and overusing LINQ, probably. This might be too concise and a normal loop might be better, depending on your own (and your coworker's!) preferences):
public static byte[] GetBytes(string bitString) {
return Enumerable.Range(0, bitString.Length/8).
Select(pos => Convert.ToByte(
bitString.Substring(pos*8, 8),
2)
).ToArray();
}
public static byte[] GetBytes(string bitString)
{
byte[] output = new byte[bitString.Length / 8];
for (int i = 0; i < output.Length; i++)
{
for (int b = 0; b <= 7; b++)
{
output[i] |= (byte)((bitString[i * 8 + b] == '1' ? 1 : 0) << (7 - b));
}
}
return output;
}
Here's a quick and straightforward solution (and I think it will meet all your requirements): http://vbktech.wordpress.com/2011/07/08/c-net-converting-a-string-of-bits-to-a-byte-array/
This should get you to your answer: How can I convert bits to bytes?
You could just convert your string into an array like that article has, and from there use the same logic to perform the conversion.
Get the characers in groups of eight, and parse to a byte:
string bits = "0000101000010000";
byte[] data =
Regex.Matches(bits, ".{8}").Cast<Match>()
.Select(m => Convert.ToByte(m.Groups[0].Value, 2))
.ToArray();
private static byte[] GetBytes(string bitString)
{
byte[] result = Enumerable.Range(0, bitString.Length / 8).
Select(pos => Convert.ToByte(
bitString.Substring(pos * 8, 8),
2)
).ToArray();
List<byte> mahByteArray = new List<byte>();
for (int i = result.Length - 1; i >= 0; i--)
{
mahByteArray.Add(result[i]);
}
return mahByteArray.ToArray();
}
private static String ToBitString(BitArray bits)
{
var sb = new StringBuilder();
for (int i = bits.Count - 1; i >= 0; i--)
{
char c = bits[i] ? '1' : '0';
sb.Append(c);
}
return sb.ToString();
}
You can go any of below,
byte []bytes = System.Text.Encoding.UTF8.GetBytes("Hi");
string str = System.Text.Encoding.UTF8.GetString(bytes);
byte []bytesNew = System.Convert.FromBase64String ("Hello!");
string strNew = System.Convert.ToBase64String(bytesNew);

Categories