2015-06-13 4 views
3

По моему вопросу n = 16, но и общий ответ был бы оценен.Как поэтапно перебирать все возможные значения байтового массива размера n?

Поэтому у меня есть массив байтов:

byte[] key; 

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

Так например .:

Первая итерация:

//Math.Pow(2,128) is the max no. of iterations right? 
byte[] key; 
for(int i = 0; i < Math.Pow(2,128); i++) 
{ 
    key = new byte[16] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 
} 

Вторая итерация:

//Math.Pow(2,128) is the max no. of iterations right? 
byte[] key; 
for(int i = 0; i < Math.Pow(2,128); i++) 
{ 
    key = new byte[16] {1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 
} 

Третья итерация:

//Math.Pow(2,128) is the max no. of iterations right? 
byte[] key; 
for(int i = 0; i < Math.Pow(2,128); i++) 
{ 
    key = new byte[16] {2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 
} 

Final итерация:

//Math.Pow(2,128) is the max no. of iterations right? 
byte[] key; 
for(int i = 0; i < Math.Pow(2,128); i++) 
{ 
    key = new byte[16] {255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}; 
} 

Очевидно, я просто жёстко массив выше. Мне нужен способ сделать это правильно. Опять же, я знаю, есть много различных комбинаций. Все, что мне нужно - это способ начать повторение всех возможных значений. Как я могу сделать это в моем цикле?

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

То, что я пытался:

В теле цикла у меня есть попробовал следующее:

key = new byte[16] { (byte)i, (byte)i, (byte)i, (byte)i, (byte)i, (byte)i, (byte)i, (byte)i, (byte)i, (byte)i, (byte)i, (byte)i, (byte)i, (byte)i, (byte)i, (byte)i }; 

Очевидно, что это неправильно, проверит только небольшое подмножество возможных значений. Просто попробуем i = 0, ..., 255, а затем начнем, когда i = 256 -> (байт) i = 0.

Я подозреваю, что мне нужно еще несколько гнездящихся. Возможно, до 16 вложенных циклов, что кажется безумным и, вероятно, неправильным? Я не могу решить эту проблему, любая помощь будет высоко оценена!

Цель: Цель этого вопроса - продемонстрировать, насколько практичным является неэффективный криптоанализ грубой силы. Остальная часть моей программы работает, я просто застрял в этом цикле.

+0

Упростите это немного. Как бы вы справились с массивом из двух байтов? Что насчет 3? Кроме того, блог eric lippert содержит отличный пост обо всех возможных подмножествах. Я найду его для тебя в одно мгновение. –

+1

[Есть пять частей; здесь часть первая] (http://ericlippert.com/2014/10/16/producing-combinations-part-two/). Это делает отличное чтение, особенно. о C#. –

+0

@BenKnoble Спасибо. Я дам ему прочитать сейчас :) – DSF

ответ

4

В случае, если вы не понимаете: 16 байт размеров Guid или размер стандартного размера криптографического ключа. Существует так много комбинаций, что вы не можете перечислить даже долю. Возможно, вы можете перечислить последние 8 байтов, если вы распараллеливаете 1000 машин и ждете в год.

Вы можете сделать это легко, выполнив цикл for от 0 до ulong.MaxValue. Я представляю это как ответ, потому что эта очень простая идея позволяет начать перечисление и, по сути, никогда не доходить до того момента, когда вы закончите.

for (ulong i = 0; i < ulong.MaxValue; i++) { 
var bytes = new [] { 
    0, 0, 0, 0, 0, 0, 0, 0 
    , (byte)(i >> (7 * 8)) 
    , (byte)(i >> (6 * 8)) 
    , (byte)(i >> (5 * 8)) 
    //... 
    , (byte)(i >> (0 * 8)) }; 
} 

Или просто используйте 16 вложенных для петель. Я не думаю, что это безумие, потому что это так просто, что это явно правильно.

+0

Возможно ли продлить ваш ответ, чтобы на самом деле попытаться перечислить все 16 байтов? Поэтому вместо 0s в начале я мог бы написать '(byte) (i >> (15 * 16)), (байт) (i >> (14 * 16)) ...., (байт) (i> > (0 * 16)). Будет ли это работать? Я знаю, что это совершенно неосуществимо, но мне просто нужно ** мой цикл, чтобы хотя бы попробовать. Никогда не думайте, что он не может завершить перечисление. – DSF

+2

Используйте два вложенных цикла. Внешняя обеспечила бы первые 8 байтов. Обратите внимание, что внешний цикл никогда не войдет во вторую итерацию, но теоретически там ... :) – usr

+0

Это работает, спасибо. Очень элегантное решение! – DSF

1

это образец кода без обработки исключений и рода неэффективны для имитации счетчика, как один вы упомянули

public static void NextIteration(byte[] input) 
{ 
    if (input.All(x => x == 255)) 
     throw new InvalidOperationException("there is no iteration left"); 

    var converted = input.Select(x => (int) x).ToArray(); 
    converted[0]++; 
    for (var i = 0; i < converted.Length; i++) 
    { 
     if (converted[i] == 256) 
     { 
      converted[i] = 0; 
      converted[i + 1]++; 
     } 
    } 
    for (var i = 0; i < input.Length; i++) 
    { 
     input[i] = (byte) converted[i]; 
    } 
} 
Смежные вопросы