Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Increment a byte[]

Tags:

c#

.net

I have a byte[] testKey = new byte[8];

This obviously starts with all bytes as 0. I want to go through all the bytes and increment by 1 on each iteration of the loop so eventually I go through all possibilities of the byte array. I also want to do this as FAST as possible. Yes I am trying to write a brute forcer.

Update I got the unsafe method working, and it is the quickest. However, by my calculations, it is going to take 76,000,000 years to loop through doing DES encryption on each key using the .Net DESCryptoServiceProvider. 10,000 encryptions takes 1.3 seconds. Thanks for all the awesome answers to the most useless question ever!

like image 207
John Oxley Avatar asked Sep 18 '09 11:09

John Oxley


People also ask

What does system byte [] mean?

System. Byte[*] is an array that has a non-zero lower bound. For example, an array that starts at 1.

Can we increment byte?

The byte data type can be incremented by using the pre-increment operator.


8 Answers

btw; it takes a lot of processing to check 2^64 options...

Well, the fastest way may be to just use an Int64 (aka long) or UInt64 (ulong), and use ++? Do you really need the byte[]?

As a hacky alternative, how about:

Array.Clear(data, 0, data.Length);
while (true)
{
  // use data here
  if (++data[7] == 0) if (++data[6] == 0)
    if (++data[5] == 0) if (++data[4] == 0)
      if (++data[3] == 0) if (++data[2] == 0)
        if (++data[1] == 0) if (++data[0] == 0) break;
}

The only other approach I can think of would be to use unsafe code to talk to an array as though it is an int64... messy.

unsafe static void Test() {
    byte[] data = new byte[8];
    fixed (byte* first = data) {
        ulong* value = (ulong*)first;
        do {
            // use data here
            *value = *value + 1;
        } while (*value != 0);
    }
}
like image 177
Marc Gravell Avatar answered Oct 12 '22 23:10

Marc Gravell


This is how you increase the value in the array:

int index = testKey.Length - 1;
while (index >= 0) {
   if (testKey[index] < 255) {
      testKey[index]++;
      break;
   } else {
      testKey[index--] = 0;
   }
}

When index is -1 after this code, you have iterated all combinations.

This will be slightly faster than using BitConverter, as it doesn't create a new array for each iteration.

Edit:
A small performance test showed that this is about 1400 times faster than using BitConverter...

like image 24
Guffa Avatar answered Oct 13 '22 01:10

Guffa


What a great question! Here's a way to do it without unsafe code:

public struct LongAndBytes
{
    [FieldOffset(0)]
    public ulong UlongValue;
    [FieldOffset(0)]
    public byte Byte0;
    [FieldOffset(1)]
    public byte Byte1;
    [FieldOffset(2)]
    public byte Byte2;
    [FieldOffset(3)]
    public byte Byte3;
    [FieldOffset(4)]
    public byte Byte4;
    [FieldOffset(5)]
    public byte Byte5;
    [FieldOffset(6)]
    public byte Byte6;
    [FieldOffset(7)]
    public byte Byte7;

    public byte[] ToArray()
    {
        return new byte[8] {Byte0, Byte1, Byte2, Byte3, Byte4, Byte5, Byte6, Byte7};
    }
}


// ...

    LongAndBytes lab = new LongAndBytes();

    lab.UlongValue = 0;
    do {
        // stuff
        lab.UlongValue++;
    } while (lab.ULongValue != 0);

Each of the members Byte0...Byte7 overlap the ulong and share its members. It's not an array - I tried dinking around with that and had unsatisfactory results. I bet someone knows the magic declaration to make that happen. I can do that for a P/Invoke, but not for use in .NET as an array is an object.

like image 44
plinth Avatar answered Oct 13 '22 00:10

plinth


byte[8] is essentially an ulong but if you really need it to be byte[8] you can use

byte[] bytes = new byte[8];
ulong i = 0;
bytes = BitConverter.GetBytes(i);
like image 27
Jonas Elfström Avatar answered Oct 13 '22 00:10

Jonas Elfström


You can extract the bytes using bit operators:

byte[] bytes = new byte[8];
for (ulong u = 0; u < ulong.MaxValue; u++)
{
    bytes[0] = (byte)(u & 0xff);
    bytes[1] = (byte)((u >> 8) & 0xff);
    bytes[2] = (byte)((u >> 16) & 0xff);
    bytes[3] = (byte)((u >> 24) & 0xff);
    bytes[4] = (byte)((u >> 32) & 0xff);
    bytes[5] = (byte)((u >> 40) & 0xff);
    bytes[6] = (byte)((u >> 48) & 0xff);
    bytes[7] = (byte)((u >> 56) & 0xff);
    // do your stuff...
}

This is less 'hackish', since it operates on an unsigned 64-bit integer first and then extract the bytes. However beware CPU endianess.

like image 40
Cecil Has a Name Avatar answered Oct 12 '22 23:10

Cecil Has a Name


for (UInt64 i = 0; i < UInt64.MaxValue; i++)
{
    byte[] data = BitConverter.GetBytes(i)
}
like image 37
Stu Mackellar Avatar answered Oct 13 '22 00:10

Stu Mackellar


byte[] array = new byte[8];
int[] shifts = new int[] { 0, 8, 16, 24, 32, 40, 48, 56 };    
for (long index = long.MinValue; index <= long.MaxValue; index++)
{
    for (int i = 0; i < 8; i++)
    {
        array[i] = (byte)((index >> shifts[i]) & 0xff);
    }
    // test array
}
like image 31
MusiGenesis Avatar answered Oct 12 '22 23:10

MusiGenesis


for (int i = 0; i < bytes.Length & 0 == ++bytes[i]; i++);

Should be as fast as the unsafe method and allows arrays of any size.

like image 30
cassam Avatar answered Oct 13 '22 00:10

cassam