How to convert a String to a Hex Byte Array? [duplicate] - c#

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
How do you convert Byte Array to Hexadecimal String, and vice versa, in C#?
For testing my encryption algorithm I have being provided keys, plain text and their resulting cipher text.
The keys and plaintext are in strings
How do i convert it to a hex byte array??
Something like this : E8E9EAEBEDEEEFF0F2F3F4F5F7F8F9FA
To something like this :
byte[] key = new byte[16] { 0xE8, 0xE9, 0xEA, 0xEB, 0xED, 0xEE, 0xEF, 0xF0, 0xF2, 0xF3, 0xF4, 0xF5, 0xF7, 0xF8, 0xF9, 0xFA} ;
Thanx in advance :)

Do you need this?
static class HexStringConverter
{
public static byte[] ToByteArray(String HexString)
{
int NumberChars = HexString.Length;
byte[] bytes = new byte[NumberChars / 2];
for (int i = 0; i < NumberChars; i += 2)
{
bytes[i / 2] = Convert.ToByte(HexString.Substring(i, 2), 16);
}
return bytes;
}
}
Hope it helps.

Sample code from MSDN:
string hexValues = "48 65 6C 6C 6F 20 57 6F 72 6C 64 21";
string[] hexValuesSplit = hexValues.Split(' ');
foreach (String hex in hexValuesSplit)
{
// Convert the number expressed in base-16 to an integer.
int value = Convert.ToInt32(hex, 16);
// Get the character corresponding to the integral value.
string stringValue = Char.ConvertFromUtf32(value);
char charValue = (char)value;
Console.WriteLine("hexadecimal value = {0}, int value = {1}, char value = {2} or {3}", hex, value, stringValue, charValue);
}
You only have to change it to split the string on every 2 chars instead of on spaces.

did u mean this
StringBuilder Result = new StringBuilder();
string HexAlphabet = "0123456789ABCDEF";
foreach (byte B in Bytes)
{
Result.Append(HexAlphabet[(int)(B >> 4)]);
Result.Append(HexAlphabet[(int)(B & 0xF)]);
}
return Result.ToString();

Related

Convert byte array to collection of enums in C#

I have a byte array that recevies enums in little endianess byte order from a function GetData() and I want to convert the array into a collection of enums.
How would I copy and cast the bytes in LE order to the enum values in C#? I have a C++ background and not too familiar with the language.
This is a sample code snippet:
public enum BarID
{
TAG0 = 0x0B01,
TAG1 = 0x0B02,
}
public class TestClass
{
List<BarID> ids;
internal TestClass()
{
ids = new List<BarID>();
byte[] foo = GetData(); // returns 01 0b 00 00 02 0b 00 00
// cast byte array so that ids contains the enums 'TAG0' and 'TAG1'
}
}
The interesting step here is reading the bytes reliably in a little-endian way (where "reliable" here means "works on any CPU, not just one that happens to be little-endian itself"); fortunately, BinaryPrimitives makes this obvious, giving you an int from a Span<byte> (the byte[] from GetData() is implicitly castable to Span<byte>). Then from the int you can just cast to BarID:
Span<byte> foo = GetData();
var result = new BarID[foo.Length / 4];
for (int i = 0; i < result.Length; i++)
{
result[i] = (BarID)BinaryPrimitives.ReadInt32LittleEndian(foo.Slice(4 * i));
}
The Slice step here just offsets where we should start reading in the span.
Though Marc's answer is both good and fast, that works only on .NET Core, or if you use additional nugets. If that could be a problem (or you target older Framework versions) you can use a solution like this:
var bytes = new byte[] { 0x01, 0x0b, 0x00, 0x00, 0x02, 0x0b, 0x00, 0x00 };
return BitConverter.IsLittleEndian
? ConvertLittleEndian(bytes)
: ConvertBigEndian(bytes);
Where the conversion methods:
private static unsafe BarID[] ConvertLittleEndian(byte[] bytes)
{
var barIds = new BarID[bytes.Length / 4];
fixed (byte* pBytes = bytes)
{
BarID* asIds = (BarID*)pBytes;
for (int i = 0; i < barIds.Length; i++)
barIds[i] = asIds[i];
}
return barIds;
}
If you know that your code will be used on little endian CPUs (eg. it is meant to be a Windows app), then you don't even need the big endian version:
private static BarID[] ConvertBigEndian(byte[] bytes)
{
var barIds = new BarID[bytes.Length / 4];
for (int i = 0; i < barIds.Length; i++)
{
int offset = i * 4;
barIds[i] = (BarID)((bytes[offset] << 3) | (bytes[offset + 1] << 2)
| (bytes[offset + 2] << 1) | bytes[offset + 3]);
}
return barIds;
}
Try this:
var foo = new byte[] {0x01, 0x0b, 0x00, 0x00, 0x02, 0x0b, 0x00, 0x00}.ToList();
IEnumerable<byte> bytes;
var result = new List<BarID>();
while ((bytes = foo.Take(4)).Any())
{
var number = BitConverter.IsLittleEndian
? BitConverter.ToInt32(bytes.ToArray(), 0)
: BitConverter.ToInt32(bytes.Reverse().ToArray(), 0);
var enumValue = (BarID) number;
result.Add(enumValue);
foo = foo.Skip(4).ToList();
}
It is not clear if the array values are grouped by two or four, however the pattern is basically the same:
public enum BarID
{
TAG0 = 0x0B01,
TAG1 = 0x0B02,
}
public class TestClass
{
List<BarID> ids;
internal TestClass()
{
ids = new List<BarID>();
byte[] foo = GetData(); // returns 01 0b 00 00 02 0b 00 00
// cast byte array so that ids contains the enums 'TAG0' and 'TAG1'
//create a hash-set with all the enum-valid values
var set = new HashSet<int>(
Enum.GetValues(typeof(BarID)).OfType<int>()
);
//scan the array by 2-bytes
for (int i = 0; i < foo.Length; i += 2)
{
int value = foo[i] + foo[i + 1] << 8;
if (set.Contains(value))
{
ids.Add((BarID)value);
}
}
}
}
The set is not mandatory, but it should prevent invalid values to be casted to a tag. For instance, if the values are word-based, the 00 00 value is invalid.
As final consideration, I wouldn't do similar tasks in a class constructor: better to create the instance, then call a dedicated method to the conversion.

C# Convert Active Directory Hexadecimal to GUID

We are pushing AD objects to a 3rd party vendor where the objectGUID attribute is outputted as hexadecimal, as seen in the Attribute Editor window. We need to be able to convert the hexadecimal back to GUID format so that we can perform lookups against the database.
Is it possible to convert hexadecimal back to GUID format? In all likelihood, the hexadecimal will come back in string format.
Example:
Hexadecimal: EC 14 70 17 FD FF 0D 40 BC 03 71 A8 C5 D9 E3 02
or
Hexadecimal (string): ec147017fdff0d40bc0371a8c5d9e302
GUID: 177014EC-FFFD-400D-BC03-71A8C5D9E302
Update
After accepting the answer, I can validate it using some code from Microsoft See here: Guid.ToByteArray Method
using System;
namespace ConsoleApp3
{
class Program
{
static void Main()
{
// https://stackoverflow.com/questions/56638890/c-sharp-convert-active-directory-hexadecimal-to-guid
byte[] bytearray = StringToByteArray("ec147017fdff0d40bc0371a8c5d9e302");
// https://learn.microsoft.com/en-us/dotnet/api/system.guid.tobytearray?view=netframework-4.8
Guid guid = new Guid(bytearray);
Console.WriteLine("Guid: {0}", guid);
Byte[] bytes = guid.ToByteArray();
foreach (var byt in bytes)
Console.Write("{0:X2} ", byt);
Console.WriteLine();
Guid guid2 = new Guid(bytes);
Console.WriteLine("Guid: {0} (Same as First Guid: {1})", guid2, guid2.Equals(guid));
Console.ReadLine();
}
public static byte[] StringToByteArray(String hex)
{
int NumberChars = hex.Length;
byte[] bytes = new byte[NumberChars / 2];
for (int i = 0; i < NumberChars; i += 2)
bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
return bytes;
}
}
}
Guid has a constructor which takes a byte array
You can convert the hexadecimal string into a byte array and use that to construct a new Guid.
If you need to know how to convert the hexadecimal string to a byte array, Stack Overflow already has a few answers to that question.
From the accepted answer of that question:
public static byte[] StringToByteArray(String hex)
{
int NumberChars = hex.Length;
byte[] bytes = new byte[NumberChars / 2];
for (int i = 0; i < NumberChars; i += 2)
bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
return bytes;
}

Decrypt string using Bouncy Castle RC4 algorithm in C#

I am trying to use library Bouncy Castle for decrypting. But the decrypted string is not correct. I am getting value Aa1ŽYY445Ló, but correct value should be Aa11YY445LL. What I am doing wrong? When I try to decrypt string on http://rc4.online-domain-tools.com/ I am getting correct result.
Code sample:
string textToDecrypt = HexDumper.FromHex("E5497380DC724B28284D80");
var key = Encoding.UTF8.GetBytes("heslo");
var cipher = new RC4Engine();
cipher.Init(true, new KeyParameter(key));
byte[] inBytes = UTF8Encoding.GetEncoding(1252).GetBytes(textToDecrypt);
byte[] outBuffer = new byte[1024 * 4];
cipher.ProcessBytes(inBytes, 0, inBytes.Length, outBuffer, 0);
// Output must be 41 61 31 31 59 59 34 34 35 4c 4c -> Aa11YY445LL
var textDecrypted = ASCIIEncoding.GetEncoding(1252).GetString(outBuffer);
int indexOf0 = textDecrypted.IndexOf("\0");
if (indexOf0 > 0)
{
textDecrypted = textDecrypted.Substring(0, indexOf0);
MessageBox.Show(textDecrypted);
}
public static string FromHex(string hexString)
{
string StrValue = "";
while (hexString.Length > 0)
{
StrValue += System.Convert.ToChar(System.Convert.ToUInt32(hexString.Substring(0, 2), 16)).ToString();
hexString = hexString.Substring(2, hexString.Length - 2);
}
return StrValue;
}
The problem is your FromHex function.
Swapped it with the top answer from How can I convert a hex string to a byte array? and got the correct result.
Not sure specifically what's wrong (in terms of functionality) with your FromHex, though -- you should probably figure that out.

How to convert decimal string value to hex byte array in C#?

I have an input string which is in decimal format:
var decString = "12345678"; // in hex this is 0xBC614E
and I want to convert this to a fixed length hex byte array:
byte hexBytes[] // = { 0x00, 0x00, 0xBC, 0x61, 0x4E }
I've come up with a few rather convoluted ways to do this but I suspect there is a neat two-liner! Any thoughts? Thanks
UPDATE:
OK I think I may have inadvertently added a level of complexity by having the example showing 5 bytes. Maximum is in fact 4 bytes (FF FF FF FF) = 4294967295. Int64 is fine.
If you have no particular limit to the size of your integer, you could use BigInteger to do this conversion:
var b = BigInteger.Parse("12345678");
var bb = b.ToByteArray();
foreach (var s in bb) {
Console.Write("{0:x} ", s);
}
This prints
4e 61 bc 0
If the order of bytes matters, you may need to reverse the array of bytes.
Maximum is in fact 4 bytes (FF FF FF FF) = 4294967295
You can use uint for that - like this:
uint data = uint.Parse("12345678");
byte[] bytes = new[] {
(byte)((data>>24) & 0xFF)
, (byte)((data>>16) & 0xFF)
, (byte)((data>>8) & 0xFF)
, (byte)((data>>0) & 0xFF)
};
Demo.
To convert the string to bytes you can use BitConverter.GetBytes:
var byteArray = BitConverter.GetBytes(Int32.Parse(decString)).Reverse().ToArray();
Use the appropriate type instead of Int32 if the string is not allways an 32 bit integer.
Then you could check the lenght and add padding bytes if needed:
if (byteArray.Length < 5)
{
var newArray = new byte[5];
Array.Copy(byteArray, 0, newArray, 5 - byteArray.Length, byteArray.Length);
byteArray = newArray;
}
You can use Linq:
String source = "12345678";
// "BC614E"
String result = String.Join("", BigInteger
.Parse(source)
.ToByteArray()
.Reverse()
.SkipWhile(item => item == 0)
.Select(item => item.ToString("X2")));
In case you want Byte[] it'll be
// [0xBC, 0x61, 0x4E]
Byte[] result = BigInteger
.Parse(source)
.ToByteArray()
.Reverse()
.SkipWhile(item => item == 0)
.ToArray();

Migrating BCD conversion code from Java to .Net

I am converting a Java class that converts BCD data to ASCII
I am converting it to .Net BCD Convertor
Following is the converted from java but it is giving wrong converted value e.g. for 123456789 it is giving 123456153153
public static string GetStringFromBcd(int[] b)
{
StringBuilder buffer = new StringBuilder();
foreach (var t in b)
{
if ((t & 0x0000000F) == 0x0000000F && ((t >> 4) & 0x0000000F) == 0x0000000F)
{
break;
}
buffer.Append((t & 0x0000000F) + "");
if ((t & 0x000000F0) != 0x000000F0)
{
buffer.Append(((t >> 4) & 0x0000000F) + "");
}
}
}
What could be the problem?
EDIT: ANSWER:
I got the source program where the data has been BCD encoded.
I found that nothing was wrong in that logic, then I discovered the source of the function where the data was converting from network stream to string and later converted to byte/int array.
following is the code
int bytesRead = tcpClient.Receive(message);//, 0, bytetoReadSize);
if (bytesRead == 0)
{
break;
//the client has disconnected from the server
}
//message has successfully been received
data += new ASCIIEncoding().GetString(message, 0, bytesRead);
here is the problem ASCIIEncoding does not convert many encoded character and gives '?'63 instead of those character , when putting 63 in BCD conversion logic it gives 153.
To resolve this error, I Modified the last line and instead of decoding , I am simply casting the received byte to char.
foreach (byte b in message)
{
data += ((char) b);
}
Here's a Similar Question that comes about it a few different ways.
Here's a Site that has an excellent detailed description of what your facing.
It shouldn't be that hard, but processing them as int's is going to be much harder.
Zoned Decimal (BCD) is pretty straight forward to convert, but you have to be careful if your taking files from a mainframe that have been converted via an ASCII transfer. It can still be converted, but the byte values change due to the ebcdic to ascii conversion during the FTP.
If your processing binary files, it's much easier to deal with.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace TestZoned
{
class Program
{
public static String zoneToString(byte[] zoneBytes)
{
Encoding ascii = Encoding.ASCII;
Encoding ebcdic = Encoding.GetEncoding("IBM037");
byte[] asciiBytes = null;
String str = null;
int zoneLen = zoneBytes.Length;
int i = zoneLen - 1;
int b1 = zoneBytes[i];
b1 = (b1 & 0xf0) >> 4;
switch (b1)
{
case 13:
case 11:
zoneBytes[i] = (byte)(zoneBytes[i] | 0xf0);
asciiBytes = Encoding.Convert(ebcdic, ascii, zoneBytes);
str = "-" + ASCIIEncoding.ASCII.GetString(asciiBytes);
break;
default:
zoneBytes[i] = (byte)(zoneBytes[i] | 0xf0);
asciiBytes = Encoding.Convert(ebcdic, ascii, zoneBytes);
str = ASCIIEncoding.ASCII.GetString(asciiBytes);
break;
}
return (str);
}
static void Main(string[] args)
{
byte[] array = { 0xf0, 0xf0, 0xf1 }; // 001
byte[] pos = { 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9 }; // 123456789
byte[] neg = { 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xd9 }; // -123456789
Console.WriteLine("Converted: {0}", zoneToString(array));
Console.WriteLine("Converted: {0}", zoneToString(pos));
Console.WriteLine("Converted: {0}", zoneToString(neg));
}
}
}
If you wanted to stick to something similar
public static String GetStringFromBcd(byte[] zoneBytes)
{
StringBuilder buffer = new StringBuilder();
int b1 = (zoneBytes[zoneBytes.Length - 1] & 0xf0) >> 4;
if ( (b1 == 13) || (b1 == 11) ) buffer.Append("-");
for (int i = 0; i < zoneBytes.Length; i++)
{
buffer.Append((zoneBytes[i] & 0x0f));
}
return buffer.ToString();
}

Categories