I am a newbie with a question regarding reading specific bytes out of an array in C#. I received an array response that is 128 bytes long and I am looking to read and store the first 4 bytes of the array. How do I do so?
I've read a number of posts about shifting bytes but was a bit confused and I am looking to get going in the right direction.
Use one of the Array.Copy overloads:
byte[] bytes = new byte[4];
Array.Copy(originalArray, bytes, bytes.Length);
Use Array.Copy method:
// your original array
var sourceArray = new byte[128];
// create a new one with the size you need
var firstBytes = new byte[4];
// copy the required number of bytes.
Array.Copy(sourceArray, 0, firstBytes, 0, firstBytes.Length);
If you do not need the rest of the data in the original array, you can also resize it, truncating everything after the first 4 bytes:
Array.Resize(ref sourceArray, 4);
Read the first 4 bytes in 4 different variables:
byte first = array[0],
second = array[1],
third = array[2],
forth = array[4];
Read them as one 32-bit long integer:
int result =
first << 24 ||
second << 16 ||
third << 8 ||
forth;
The x << n operator shifts the bits of number x, n times to the left. You are effectively moving the bytes of first 24 positions to the left, thus first will be stored in bits with indices 24 to 31 like that:
first 00000000 00000000 00000000
Next, move second 16 positions to the left, thus storing it in bits 16 to 23 and so on:
first second 00000000 00000000
Wikipedia provides a good summary of bitwise operations if you need more details.
Example from a network stream.
byte[] bytesRead = 0;
using (NetworkStream stream = client.GetStream())
{
byte[] length = new byte[4];
bytesRead = stream.Read(length, 0, 4);
}
bytesRead contains the first 4 bytes stored in the networkstream.
You could use the Take method. Although, this is only available if you are using .NET 3.5 or later. You will need to have using System.Linq; at the top of the .cs file.
var bytes = originalArray.Take(4).ToArray();
Related
I have a test code like below. I am reading from stream, offsetting by 2 positions, and then taking next 2 bytes. I would hope that result would be an array with 2 elements. This does not work though - offset is completely ignored, and full sized array is always returned, with only offset blocks having values. But this means my result table is still very large, it just has a lot of unwanted zeroes
How can I rework below code, so that file.Read() returns only an array of 2 bytes instead of 10 when length = 2 and offset = 2? In real world scenario I am dealing with large files (>2gigs) so filtering out the result array is not an option.
Edit: As the issue is unclear - below code requires me to always define output array that is the same size as the stream. Instead I would like to have an output that is of size of length (in below example I would like to have var buffer = new byte[2], but that will throw an exception because file.Read ignores offset and length and always returns 10 elements (with only 2 of them being read, rest is dummy zeroes).
private byte[] GetFilePart(int length, int offset)
{
//build some dummy content
var content = new byte[10];
for (int i = 0; i<10; i++)
{
content[i] = 1;
}
//read the data from content
var buffer = new byte[10];
using (Stream file = new MemoryStream(content))
{
file.Read(buffer, offset, length);
}
return buffer;
}
Looks like it's working properly to me; maybe your confusion would clear a bit if you inited your content array with something like:
for (int i = 1; i<=10; i++)
{
content[i-1] = i;
}
then each byte would have a different number and the image would look like:
offset relates to where into buffer the Stream will write the bytes to (it reads from the start of content). It does not relate to what bytes are read out of content.
Imagine Read as being called WriteBytesInto(byte[] whatBuffer, int whereToStartWriting, int howManyBytesToWrite) - you provide the buffer it will write into and tell it where to start and how many to do
If you did this, having inited content to be incrementing numbers:
file.Read(buffer, 2, 3); //read 3 bytes from stream and write to buffer # index 2
file.Read(buffer, 0, 2); //read 2 bytes from stream and write to buffer # index 0
Your buffer would end up looking like:
4,5,1,2,3,0,0,0,0,0
The 1,2,3 having been written first, then the 4,5 written next
If you want to skip two bytes from the stream (i.e. read the 3rd and 4th byte from content, Seek() the stream or set its Position (or as canton7 advises in the commments, if the stream is not seekable, read and discard some bytes)
How can I rework below code, so that file.Read() returns only an array of 2 bytes instead of 10 when length = 2 and offset = 2?
Well, file.Read doesn't return an array at all; it modifies an array you give it. If you want a 2 byte array, give it a 2 byte array:
byte buf = new byte[2];
file.Read(buf, 0, buf.Length);
If you want to open a file, skip the first 7 bytes and then read bytes 8th and 9th into your length-of-2 byte array then:
byte buf = new byte[2];
file.Position = 7; //absolute skip to 8th byte
file.Read(buf, 0, buf.Length);
For more on seeking in streams see Stream.Seek(0, SeekOrigin.Begin) or Position = 0
I have two byte arrays, they have variable length but always add up to 8 bytes. These need to be combined into a long. I can do this with creating a byte array and copying the required data. But I was thinking that this should also be possible through bit-shifting. I've been trying this (simplified with just one length):
var bytes1 = new byte[] { 1, 2, 3, 4, 5, 6, 7 };
var bytes2 = new byte[] { 8 };
unsafe
{
fixed (byte* b1 = bytes1)
{
fixed (byte* b2 = bytes2)
{
ulong* bl1 = (ulong*)b1;
ulong v = (*bl1<< 8) | (*b2);
var bytes = bytes1.Concat(bytes2).ToArray();
// These two are different:
Console.WriteLine(v);
Console.WriteLine(BitConverter.ToUInt64(bytes, 0));
}
}
}
I'm aware that Concat works, but I'd like to this to work too.
First of all, (ulong*)b1 is an out of bounds read because the array has length 7 and sizeof(ulong) == 8. The next read is also broken in that way. Alignment is also a problem. I don't see a way to rescue that approach. You could read 4 bytes, then 2 bytes, then 1 byte if you really are looking for performance.
I'd loop over the arrays and shift in each byte:
ulong result = 0;
void MergeArray(byte[] bytes) {
foreach (var b in bytes) {
result = result << 8 | (ulong)b;
}
}
MergeArray(bytes1);
MergeArray(bytes2);
Using a local function for code sharing.
You can improve performance by taking 4 bytes as the first chunk if the array length supports a read of that size. Then, fetch 2, then fetch 1. That way there is not even a loop and the number of operations is minimized.
Whether this is good or not depends on your need for performance which must be traded off with code legibility.
I have application that play Pcap files and i try to add function that wrap my packet with PPPOE layer.
so almost all done except large packets that i didn't understand yet how to set the new langth after add PPPOE layer.
For example this packet:
As you can see this packet length is 972 bytes (03 cc), and all i want is to convert it to decimal, after see this packet byte[] in my code i can see that this value converted into 3 and 204 in my packet byte[], so my question is how this calculation works ?
Those two bytes represents a short (System.Int16) in bigendian notation (most significant byte first).
You can follow two approaches to get the decimal value of those two bytes. One is with the BitConverter class, the other is by doing the calculation your self.
BitConverter
// the bytes
var bytes = new byte[] {3, 204};
// are the bytes little endian?
var littleEndian = false; // no
// What architecure is the BitConverter running on?
if (BitConverter.IsLittleEndian != littleEndian)
{
// reverse the bytes if endianess mismatch
bytes = bytes.Reverse().ToArray();
}
// convert
var value = BitConverter.ToInt16( bytes , 0);
value.Dump(); // or Console.WriteLine(value); --> 972
Calculate your self
base 256 of two bytes:
// the bytes
var bytes2 = new byte[] {3, 204};
// [0] * 256 + [1]
var value2 = bytes2[0] * 256 + bytes2[1]; // 3 * 256 + 204
value2.Dump(); // 972
i have exponent whats 3 bytes long. Now i need it to be 4 bytes. I found somewhere that i could pad at the leading octets.. but i have no idea to do that.. So can anybody help me out?
Example Input: exponent what i have right now is 65537, int bytes its then 01 00 01.
Assuming you just want to pad it with zeroes, create a new four byte array and copy the existing one into it:
byte[] newArray = new byte[4];
// Copy bytes 0, 1, 2 of oldArray into 1, 2, 3 of newArray.
Array.Copy(oldArray, 0, newArray, 1, 3);
(You can do this manually with three assignments as well; that's potentially simpler for this situation, but doesn't scale well (in terms of code) to larger sizes.)
Change the "1" to "0" if you find you need the padding at the end instead of the start... or use Array.Resize in that case.
Not entirely sure of the meaning, but it sounds like you just want:
byte[] first = /* 3 bytes */
byte[] second = new byte[4];
// since 3 bytes, we'll do this manually; note second[0] is 0 already
second[1] = first[0];
second[2] = first[1];
second[3] = first[2];
Of course, if you are actually dealing with an int it is already padded on the left with 0, to 4 bytes.
I've 4 bytes of data and need an 8 bytes array for a security operation. I should produce these 8 bytes form the 4 bytes byte array and this should be reproducible.
I was thinking of using exact byte array and adding 4 extra bytes and fill them with AND, OR, XOR... of the initial array in a known sequence. I'm not sure if it's a good idea. I just need an 8 byte array from this 4 bytes and the operation should be reproducible (same 8 bytes with same given 4 bytes). Please give an example in C#
Why not just pad the existing 4 bytes with another 4 bytes of zeroes? Or repeat the original 4 bytes. For example:
static byte[] Pad(byte[] input)
{
// Alternatively use Array.Resize
byte[] output = new byte[input.Length + 4];
Buffer.BlockCopy(input, 0, output, 0, input.Length);
return output;
}
static byte[] Repeat(byte[] input)
{
byte[] output = new byte[input.Length * 2];
Buffer.BlockCopy(input, 0, output, 0, input.Length);
Buffer.BlockCopy(input, 0, output, input.Length, input.Length);
return output;
}
Both of these fulfil your original criteria, I believe... but I suspect you're looking for something else. If that's the case, you need to be explicit about what you need.
EDIT: As I've said in the comments, you're basically not adding any real security here - padding will make that clearer, IMO. On the other hand, if you do want some security-through-obscurity, you could find a random number generator that allows seeding, and use that as a starting point. For example:
// Don't use this - see below. Just the concept...
int seed = BitConverter.ToInt32(input, 0); // TODO: Cope with endianness
Random rng = new Random(seed);
byte[] output = new byte[8];
Buffer.BlockCopy(input, 0, output, 0, 4);
for (int i = 4; i < 8; i++) {
output[i] = (byte) rng.Next(256);
}
Now, the reason I've got the comment above is that you probably need an algorithm which is guaranteed not to change between versions of .NET. Find code to something like the Mersenne Twister, for exmaple.
There are multiple methods of doing padding for block ciphers.
This Wikipedia article covers some of the more accepted solutions: http://en.wikipedia.org/wiki/Padding_(cryptography)#Padding_methods
Barring any other considerations, I would use PKCS#7 padding.
How about
bytes.Concat(bytes)
I would be very careful. If a security operation requires 64 bits worth of data it is probably because it requires that much data. If you create your 64 bits from 32 bits with a known reproducible formula you will still only have 32 bits worth of data.
If the security is not affected by the data you have you can just fill the the remaining four bytes with ones or zeros. But you should really try to get 8 bytes of "real" data.