C# private function, IncrementArray - c#

Can someone please explain in layman's terms the workings of this C# code?
for (int pos = 0; pos < EncryptedData.Length; pos += AesKey.Length);
{
Array.Copy(incPKGFileKey, 0, PKGFileKeyConsec, pos, PKGFileKey.Length);
IncrementArray(ref incPKGFileKey, PKGFileKey.Length - 1);
}
private Boolean IncrementArray(ref byte[] sourceArray, int position)
{
if (sourceArray[position] == 0xFF)
{
if (position != 0)
{
if (IncrementArray(ref sourceArray, position - 1))
{
sourceArray[position] = 0x00;
return true;
}
else return false;
}
else return false;
}
else
{
sourceArray[position] += 1;
return true;
}
}
I'm trying to port an app to Ruby but I'm having trouble understanding how the IncrementArray function works.

IncrementArray increments all entries of a byte array, with any overflow being added to the previous index, unless it's index 0 already.
The entire thing looks like some kind of encryption or decryption code. You might want to look for additional hints on which algorithm is used, as this kind of code is usually not self-explaining.

It looks to me like a big-endian addition algorithm:
Let's say you've got a long (64 bit, 8 byte) number:
var bigNumber = 0x123456FFFFFFFF;
But for some reason, we've got it coming to us as a byte array in Big-endian format:
// Get the little endian byte array representation of the number:
// [0xff 0xff 0xff 0xff 0xff 0x56 0x34 0x12]
byte[] source = BitConverter.GetBytes(bigNumber);
// BigEndian-ify it by reversing the byte array
source = source.Reverse().ToArray();
So now you want to add one to this "number" in it's current form, while maintaining any carrys/overflows like you would in normal arithmetic:
// increment the least significant byte by one, respecting carry
// (as it's bigendian, the least significant byte will be the last one)
IncrementArray(ref source, source.Length-1);
// we'll re-little-endian-ify it so we can convert it back
source = source.Reverse().ToArray();
// now we convert the array back into a long
var bigNumberIncremented = BitConverter.ToInt64(source, 0);
// Outputs: "Before +1:123456FFFFFFFF"
Console.WriteLine("Before +1:" + bigNumber);
// Outputs: "After +1:12345700000000"
Console.WriteLine("After +1:" + bigNumberIncremented);

Related

How to do mass Bit shift calculation in C#

I have 2 eight Byte of Data, received as the RX CAN message,
so in total 128 bit, but not all the bit carries message. Each byte gives boolean value in specified bit like in the picture.
NOTE: This is the structure of first 8 byte, and bit Var Names are not as clean as in the picture.
At the moment I receive 85 bit of message excluding the Reserved bit.
Reserved are for the future usage if a message is need to be added.
I have to check the boolean value of the specified bit, and store the boolean value in an Array.
I am having difficulty in checking each of 85 bit and storing them in array, is there any more efficient way like using a function to check the bool status, and store the value in array using iteration? or any other,
You could just create a class to store your 8 bytes, and create read only properties to get the different flags, through left shift and bitwise AND. Each flag can return something like this (for example, this is W1_A, bit 0 of first byte):
return (bytes[0] & (1 << 0)) != 0;
So something like this:
public class CanMessage
{
private byte[] _bytes = new byte[8];
public CanMessage(byte[] bytes)
{
if (bytes == null || bytes.Length != 8)
{
throw new ArgumentException(nameof(bytes));
}
_bytes = bytes;
}
public bool W1_A => (_bytes[0] & (1 << 0)) != 0;
// ...
}
Which you can then use like this:
var msg = new CanMessage(new byte[] { 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA, 0x55, 0xAA });
var w1a = msg.W1_A;
Have a look at BitArray, I think it does exactly what you need.
BitArray bitArray = new(inputBytes);
bool set = bitArray.Get(bitIndex);
This is what I'm talking about. It's a struct, so it should be immutable. If you need mutability, you probably want a class, but with a way to work with a [StructLayout(LayoutKind.Sequential)] struct to do interop with your CAN driver (and initialize instances of your class.
I'm doing this with two uints because you only show 64 bits, not 128. To access 128 bits, I'd use two ulongs and adjust my magic numbers.
Here's the basic struct. We'll be adding members to this:
[StructLayout(LayoutKind.Sequential)]
public struct CanBuffer
{
private uint First;
private uint Second;
}
We need a way to read a bit from that struct. I'm using two bytes here to index into the struct. The first one will tell you which byte you are interested in, the second which bit. So, to get the value of W3_C, it would be whichByte == 2, bitNum == 3:
private bool ReadBit(byte whichByte, byte bitNum)
{
uint whichItem = whichByte switch
{
(>= 0 and <= 3) => First,
(>= 4 and <= 8) => Second,
_ => throw new ArgumentOutOfRangeException(nameof(whichByte), "WhichByte is out of range")
};
if (bitNum > 31)
{
throw new ArgumentOutOfRangeException(nameof(bitNum), "BitNum is out of range");
}
var shiftBy = whichByte * 8 + bitNum;
return ((whichItem & (1 << shiftBy)) != 0);
}
With that in place, I can write a ton of properties that look like this:
public bool W1A => ReadBit(0, 0);
//skip a bunch
public bool W3D => ReadBit(2, 4);
//etc.
Now what I need is a way to map an array index to a (byte whichByte, byte bitNum) tuple that I can use with ReadBit:
private static Dictionary<int, (byte whichByte, byte bitNum)> addresses = new()
{
{1, (0, 0) },
{2, (0, 1) },
{3, (0, 3) }, //notice that (0, 2) is skipped
{4, (0, 5) },
{5, (1, 0) },
{6, (1, 1) },
//and so on
};
Note that the syntax (byte whichByte, byte bitNum) indicates a two-byte tuple.
With that in place, writing an indexer is easy:
public bool this[int index]
{
get
{
if (index < 0 || index > 84)
{
throw new IndexOutOfRangeException("Index is out of range");
}
var (whichByte, bitNum) = addresses[index];
return ReadBit(whichByte, bitNum);
}
}
With that all in place, you can populated a CanBuffer from a call to your CAN driver (treating it as a 64 or 128 bit buffer).
CanBuffer myBuffer;
InteropCallToCanDriverToPopulateBuffer(myBuffer); // this is up to you
Then to get the bit corresponding to W3_B (which, skipping the holes, is index 10), you'd do something like this:
bool w3_B = myBuffer[10];
Note that you are not creating an array, copying into an array, or doing anything else with an array. What you are doing is pretending to be an array by implementing an int-based indexer.
Also note, I haven't really tested this code (testing would be a lot of work - I figure you can figure it out)

Need help writing a binary reader extension method for a specific value format: 6 bit then 7 bits structure

Alright so here goes.
I currently need to write an extension method for the System.IO.BinaryReader class that is capable of reading a specific format.
I have no idea what this format is called but I do know exactly how it works so i will describe it below.
Each byte that makes up the value is flagged to indicate how the reader will need to behave next.
The first byte has 2 flags, and any subsequent bytes for the value have only 1 flag.
First byte:
01000111
^^^^^^^^
|||____|_ 6 bit value
||_______ flag: next byte required
|________ flag: signed value
Next bytes:
00000011
^^^^^^^^
||_____|_ 7 bit value
|________ flag: next byte required
The first byte in the value has 2 flags, the first bit is if the value is positive or negative.
The second bit is if another byte needs to be read.
The 6 remaining bits is the value so far which will need to be kept for later.
If no more bytes need to be read then you just return the 6 bit value with the right sign as dictated by the first bit flag.
If another byte needs to be read then you read the first bit of that byte, and that will indicate if another byte needs to be read.
The remaining 7 bits are the value here.
That value will need to be joined with the 6 bit value from the first byte.
So in the case of the example above:
The first value was this: 01000111.
Which means it is positive, another byte needs to be read, and the value so far is 000111.
Another byte is read and it is this: 00000011
Therefore no new bytes need to be read and value here is this: 0000011
That is joined onto the front of the value so far like so: 0000011000111
That is therefore the final value: 0000011000111 or 199
0100011100000011 turns into this: 0000011000111
Here is another example:
011001111000110100000001
^^^^^^^^^^^^^^^^^^^^^^^^
| || ||______|_____ Third Byte (1 flag)
| ||______|_____________ Second Byte (1 flag)
|______|_____________________ First Byte (2 flags)
First Byte:
0 - Positive
1 - Next Needed
100111 - Value
Second Byte:
1 - Next Needed
0001101 - Value
Third Byte:
0 - Next Not Needed
0000001 - Value
Value:
00000010001101100111 = 9063
Hopefully my explanation was clear :)
Now i need to be able to write a clear, simple and, and most importantly fast extension method for System.IO.BinaryReader to read such a value from a stream.
My attempts so far are kind of bad and unnecessarily complicated involving boolean arrays and bitarrays.
Therefore I could really do with somebody helping me out with this in writing such a method, that would be really appreciated!
Thanks for reading.
Based on the description in the comments I came up with this, unusually reading in signed bytes since it makes the continue flag slightly easier to check: (not tested)
static int ReadVLQInt32(this BinaryReader r)
{
sbyte b0 = r.ReadSByte();
// the first byte has 6 bits of the raw value
int shift = 6;
int raw = b0 & 0x3F;
// first continue flag is the second bit from the top, shift it into the sign
sbyte cont = (sbyte)(b0 << 1);
while (cont < 0)
{
sbyte b = r.ReadSByte();
// these bytes have 7 bits of the raw value
raw |= (b & 0x7F) << shift;
shift += 7;
// continue flag is already in the sign
cont = b;
}
return b0 < 0 ? -raw : raw;
}
It can easily be extended to read a long too, just make sure to use b & 0x7FL otherwise that value is shifted as an int and bits would get dropped.
Version that checks for illegal values (an overlong sequence of 0xFF, 0xFF... for example, plus works with checked math of C# (there is an option in the C# compiler to use cheched math to check for overflows)
public static int ReadVlqInt32(this BinaryReader r)
{
byte b = r.ReadByte();
// the first byte has 6 bits of the raw value
uint raw = (uint)(b & 0x3F);
bool negative = (b & 0x80) != 0;
// first continue flag is the second bit from the top, shift it into the sign
bool cont = (b & 0x40) != 0;
if (cont)
{
int shift = 6;
while (true)
{
b = r.ReadByte();
cont = (b & 0x80) != 0;
b &= 0x7F;
if (shift == 27)
{
if (negative)
{
// minumum value abs(int.MinValue)
if (b > 0x10 || (b == 0x10 && raw != 0))
{
throw new Exception();
}
}
else
{
// maximum value int.MaxValue
if (b > 0xF)
{
throw new Exception();
}
}
}
// these bytes have 7 bits of the raw value
raw |= ((uint)b) << shift;
if (!cont)
{
break;
}
if (shift == 27)
{
throw new Exception();
}
shift += 7;
}
}
// We use unchecked here to handle int.MinValue
return negative ? unchecked(-(int)raw) : (int)raw;
}

Limit UTF-8 encoded bytes length from string

I need to limit the output byte[] length encoded with UTF-8 encoding. Eg. byte[] length must be less than or equals 1000 First I wrote the following code
int maxValue = 1000;
if (text.Length > maxValue)
text = text.Substring(0, maxValue);
var textInBytes = Encoding.UTF8.GetBytes(text);
works good if string is just using ASCII characters, because 1 byte per character. But if characters goes beyond that it could be 2 or 3 or even 6 bytes per character. That would be a problem with the above code. So to fix that problem I wrote this.
List<byte> textInBytesList = new List<byte>();
char[] textInChars = text.ToCharArray();
for (int a = 0; a < textInChars.Length; a++)
{
byte[] valueInBytes = Encoding.UTF8.GetBytes(textInChars, a, 1);
if ((textInBytesList.Count + valueInBytes.Length) > maxValue)
break;
textInBytesList.AddRange(valueInBytes);
}
I haven't tested code, but Im sure it will work as I want. However, I dont like the way it is done, is there any better way to do this ? Something I'm missing ? or not aware of ?
Thank you.
My first posting on Stack Overflow, so be gentle! This method should take care of things pretty quickly for you..
public static byte[] GetBytes(string text, int maxArraySize, Encoding encoding) {
if (string.IsNullOrEmpty(text)) return null;
int tail = Math.Min(text.Length, maxArraySize);
int size = encoding.GetByteCount(text.Substring(0, tail));
while (tail >= 0 && size > maxArraySize) {
size -= encoding.GetByteCount(text.Substring(tail - 1, 1));
--tail;
}
return encoding.GetBytes(text.Substring(0, tail));
}
It's similar to what you're doing, but without the added overhead of the List or having to count from the beginning of the string every time. I start from the other end of the string, and the assumption is, of course, that all characters must be at least one byte. So there's no sense in starting to iterate down through the string any farther in than maxArraySize (or the total length of the string).
Then you can call the method like so..
byte[] bytes = GetBytes(text, 1000, Encoding.UTF8);

Reversing a hash function

I have the following hash function, and I'm trying to get my way to reverse it, so that I can find the key from a hashed value.
uint Hash(string s)
{
uint result = 0;
for (int i = 0; i < s.Length; i++)
{
result = ((result << 5) + result) + s[i];
}
return result;
}
The code is in C# but I assume it is clear.
I am aware that for one hashed value, there can be more than one key, but my intent is not to find them all, just one that satisfies the hash function suffices.
EDIT :
The string that the function accepts is formed only from digits 0 to 9 and the chars '*' and '#' hence the Unhash function must respect this criteria too.
Any ideas? Thank you.
This should reverse the operations:
string Unhash(uint hash)
{
List<char> s = new List<char>();
while (hash != 0)
{
s.Add((char)(hash % 33));
hash /= 33;
}
s.Reverse();
return new string(s.ToArray());
}
This should return a string that gives the same hash as the original string, but it is very unlikely to be the exact same string.
Characters 0-9,*,# have ASCII values 48-57,42,35, or binary: 00110000 ... 00111001, 00101010, 00100011
First 5 bits of those values are different, and 6th bit is always 1. This means that you can deduce your last character in a loop by taking current hash:
uint lastChar = hash & 0x1F - ((hash >> 5) - 1) & 0x1F + 0x20;
(if this doesn't work, I don't know who wrote it)
Now roll back hash,
hash = (hash - lastChar) / 33;
and repeat the loop until hash becomes zero. I don't have C# on me, but I'm 70% confident that this should work with only minor changes.
Brute force should work if uint is 32 bits. Try at least 2^32 strings and one of them is likely to hash to the same value. Should only take a few minutes on a modern pc.
You have 12 possible characters, and 12^9 is about 2^32, so if you try 9 character strings you're likely to find your target hash. I'll do 10 character strings just to be safe.
(simple recursive implementation in C++, don't know C# that well)
#define NUM_VALID_CHARS 12
#define STRING_LENGTH 10
const char valid_chars[NUM_VALID_CHARS] = {'0', ..., '#' ,'*'};
void unhash(uint hash_value, char *string, int nchars) {
if (nchars == STRING_LENGTH) {
string[STRING_LENGTH] = 0;
if (Hash(string) == hash_value) { printf("%s\n", string); }
} else {
for (int i = 0; i < NUM_VALID_CHARS; i++) {
string[nchars] = valid_chars[i];
unhash(hash_value, string, nchars + 1);
}
}
}
Then call it with:
char string[STRING_LENGTH + 1];
unhash(hash_value, string, 0);
Hash functions are designed to be difficult or impossible to reverse, hence the name (visualize meat + potatoes being ground up)
I would start out by writing each step that result = ((result << 5) + result) + s[i]; does on a separate line. This will make solving a lot easier. Then all you have to do is the opposite of each line (in the opposite order too).

Convert into to byte array and insert into other array

I work in a c# wpf application in which I want to do several things. I'm working with byte arrays to compose MIDI Show Control messages (specified in the MSC Specification 1.0).
The structure of this message is that a 0x00 byte is like a comma between all the parts of the message. I compose a message like this:
byte[] data =
{(byte)0xF0, // SysEx
(byte)0x7F, // Realtime
(byte)0x7F, // Device id
(byte)0x02, // Constant
(byte)0x01, // Lighting format
(commandbyte), // GO
(qnumber), // qnumber
(byte)0x00, // comma
(qlist), // qlist
(byte)0x00, // comma
(byte)0xF7, // End of SysEx
};
I want the user to fill in unsigned integers (like 215.5) and I want to convert these numbers to bytes (without 0x00 bytes because then the message is interpreted wrong).
What is the best way to convert the numbers and place the byte array in the places mentioned above?
You might want to take a look at the BitConverter class, which is designed to convert base types into byte arrays.
http://msdn.microsoft.com/en-us/library/system.bitconverter.aspx
But I'm not sure what guidance you are seeking for placing the items into your array. Array.Copy can work to simply copy the bytes in, but maybe I am misunderstanding.
Found it out like this:
Used someone else's converter code like this:
static byte[] VlqEncode(int value)
{
uint uvalue = (uint)value;
if (uvalue < 128)
return new byte[] { (byte)uvalue };
// simplest case
// calculate length of buffer required
int len = 0;
do
{
uvalue >>= 7;
} while (uvalue != 0);
// encode
uvalue = (uint)value;
byte[] buffer = new byte[len];
int offset = 0;
do { buffer[offset] = (byte)(uvalue & 127);
// only the last 7 bits
uvalue >>= 7; if(uvalue != 0) buffer[offset++] |= 128;
// continuation bit
} while (uvalue != 0);
return buffer;
}
Then I use this to convert the integer:
byte[] mybytearray = VlqEncode(integer);
I then make a new arraylist in which I add each item in sequence:
ArrayList mymessage = new ArrayList();
foreach(byte uvalue in mymessage)
{
mymessage.Add((byte)uvalue);
}
mymessage.Add((byte)0x00);
`
and so on until I have the correct message. I then only have to convert this a byte array like this:
byte[] data = new byte[mymessage.count];
data = (byte[])mymessage.ToArray(typeof(byte));`

Categories

Resources