Увеличение байта []
У меня есть 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 байтов в точно длинные и увеличивает его.
Когда почти закончите преобразовать обратно в байты.
Это самый быстрый способ в системе