Увеличение байта []

У меня есть byte[] testKey = new byte[8];

Это, очевидно, начинается со всех байтов как 0. Я хочу пройти через все байты и увеличивать на 1 на каждой итерации цикла, поэтому в итоге я просматриваю все возможности байтового массива. Я также хочу сделать это как можно быстрее. Да, я пытаюсь написать грубый forcer.

Обновление. У меня работает небезопасный метод, и он самый быстрый. Тем не менее, по моим расчетам, для каждого цикла с использованием .Net DESCryptoServiceProvider потребуется 76 000 000 лет, чтобы выполнить шифрование DES. 10 000 шифров занимают 1,3 секунды. Спасибо за все потрясающие ответы на самый бесполезный вопрос!

Ответ 1

кстати; требуется большая обработка для проверки 2 ^ 64 опций...

Ну, самый быстрый способ - просто использовать Int64 (aka long) или UInt64 (ulong) и использовать ++? Вам действительно нужен byte[]?

Как хакерская альтернатива, как насчет:

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;
}

Единственный другой подход, о котором я могу думать, - это использовать небезопасный код для разговора с массивом, как будто это 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);
    }
}

Ответ 2

Вот как вы увеличиваете значение в массиве:

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

Когда index равно -1 после этого кода, вы выполнили итерацию всех комбинаций.

Это будет немного быстрее, чем использование BitConverter, поскольку он не создает новый массив для каждой итерации.

Edit:
Небольшой тест производительности показал, что это примерно в 1400 раз быстрее, чем использование BitConverter...

Ответ 3

Какой замечательный вопрос! Здесь можно сделать это без небезопасного кода:

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);

Каждый из членов Byte0... Byte7 перекрывает ulong и делится своими членами. Это не массив - я попытался с этим справиться и имел неудовлетворительные результаты. Бьюсь об заклад, кто-то знает волшебную декларацию, чтобы это произошло. Я могу сделать это для P/Invoke, но не для использования в .NET, поскольку массив является объектом.

Ответ 4

byte [8] - это, по существу, улунг, но если вам действительно нужно быть байтом [8], вы можете использовать

byte[] bytes = new byte[8];
ulong i = 0;
bytes = BitConverter.GetBytes(i);

Ответ 5

Вы можете извлечь байты с помощью битовых операторов:

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

Это менее "хакерский", поскольку он сначала работает с неподписанным 64-битным целым, а затем извлекает байты. Однако будьте осторожны с окончанием процессора.

Ответ 6

for (UInt64 i = 0; i < UInt64.MaxValue; i++)
{
    byte[] data = BitConverter.GetBytes(i)
}

Ответ 7

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
}

Ответ 8

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

Должен быть таким же быстрым, как и небезопасный метод, и допускать массивы любого размера.

Ответ 9

Простая итерация:

static IEnumerable<byte[]> Iterate(int arrayLength) {
    var arr = new byte[arrayLength];
    var i = 0;
    yield return arr;
    while (i < arrayLength)
    {
        if (++arr[i] != 0)
        {
            i = 0;
            yield return arr;
        }
        else i++;
    }
}

static void Main(string[] args)
{
    foreach (var arr in Iterate(2))
    {
        Console.Write(String.Join(",", arr.Select(x => $"{x:D3}")));
        Console.WriteLine();
    }
}

Ответ 10

Извините за позднюю публикацию, но мне тоже была нужна описанная функция, и я реализовал ее довольно простым способом, на мой взгляд. Возможно, это полезно и для кого-то еще:

private byte[] incrementBytes(byte[] bytes)
{
    for (var i = bytes.Length - 1; i >= 0; i--)
    {
        if (bytes[i] < byte.MaxValue)
        {
            bytes[i]++;
            break;
        }
        bytes[i] = 0;
    }
    return bytes;
}

Ответ 11

BitConverter.ToInt64/BitConverter.GetBytes - преобразует 8 байтов в точно длинные и увеличивает его. Когда почти закончите преобразовать обратно в байты. Это самый быстрый способ в системе