tags:

views:

290

answers:

8

Hi all,

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!

+10  A: 

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);
    }
}
Marc Gravell
+1 : Yep. Eight bytes is an Int64. :-)
Workshop Alex
I think that the overhead of fixing the array in memory to use it in unsafe code would outweigh the benefit of being able to treat it as an int64...
Guffa
You should use ulong* in the unsafe code, not uint*. Eventhough you loop inside the fixed statement, it's surprisingly slow. My managed code to increase the array is about 200 times faster...
Guffa
A: 

BitConverter.ToInt64 / BitConverter.GetBytes - convert 8 byte to exactly long, and increment it. When almost done convert back to bytes. It is the fastest way in system

Dewfy
When *almost* done?
Fredrik Mörk
`BitConverter`? fastest? Creating a new `byte[]` **per call** is **not** the fastest by any stretch.
Marc Gravell
Idea was to make some logical brackets - start you convert (ONCE!) bytes to long. Multiple times increase as many as you can, at the end (WHEN ALMOST DONE and ONCE!) convert back to bytes
Dewfy
+1  A: 
for (UInt64 i = 0; i < UInt64.MaxValue; i++)
{
    byte[] data = BitConverter.GetBytes(i)
}
Stu Mackellar
This creates a new `byte[]` per call, making lots of work for allocation and garbage collection; there are faster ways using a fixed array
Marc Gravell
This loop will either be done in no time or in the spring of year 7854.
Jonas Elfström
Just looping through the combinations will take about seven years using the faster method in my answer. Using BitConverter it will take about 10000 years...
Guffa
To be finished in 7 years you need to process 2^64/(7*365.25*24*3600*1000) = 83506006 per millisecond. Really?
Jonas Elfström
+3  A: 

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);
Jonas Elfström
A: 

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...

Guffa
Why the downvote? If you don't explain why, it's relly pointless...
Guffa
+3  A: 

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.

plinth
`byte[] b = new byte[8] {Byte0, Byte1, Byte2, Byte3, Byte4, Byte5, Byte6, Byte7};`
Chris
thanks! Added the change in
plinth
+1 for awesomeness.. I love this answer, simple yet powerful.
Scott Lance
The for loop will miss the last combination. You need a different loop where you check after incrementing the value if it has reached zero again.
Guffa
Changed loop to a do/while
plinth
+1  A: 

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.

Cecil Has a Name
A: 
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
}
MusiGenesis