Самопроверкающаяся программа Java (автоматическая контрольная сумма) - PullRequest
3 голосов
/ 03 января 2011

Я должен проанализировать небольшую программу самопроверки Java, вот пример

public class tamper {
      public static int checksum_self () throws Exception {
          File file = new File ("tamper.class");
          FileInputStream fr = new FileInputStream (file);
          int result;                   // Compute the checksum

          DigestInputStream sha = new DigestInputStream(fr, MessageDigest.getInstance("SHA"));
   byte[] digest = sha.getMessageDigest();

    int result = 12  // why???
    for(int i=0;i<=digest;i++)
     {
     result = (result + digest[i]) % 16 /// modulus 16 to have the 16 first bytes but why ??
    }

    return result;
      }

      public static boolean check1_for_tampering () throws Exception {
            return checksum_self () != 10; 
      }

      public static void main (String args[]) throws Exception {
          if (check1_for_tampering ()) {
            System.exit (-1);
          }

      }
}

Но я не совсем понимаю, зачем делать мод 16 и ставить результат = 12?

Ответы [ 3 ]

2 голосов
/ 03 января 2011

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

Давайте предположим, что вы пишете контрольную сумму по модулю 4. Сначала вы сравниваете значение с 0. Вы запускаете программу, но она обнаруживает, что она была подделана. Зачем? Потому что вы не знаете контрольную сумму, пока не напишите весь исходный код. И поскольку в него встроено значение контрольной суммы, каждое изменение исходного кода изменяет контрольную сумму.

Так что это как собака, гоняющаяся за собственным хвостом. Или змея ест свой хвост. Технически говоря, это динамическая система с обратной связью. Хорошо, достаточно аналогий.

Единственный способ заставить это работать - это экспериментировать. Начните с контрольной суммы, равной нулю, и скомпилируйте. Скорее всего, он распознает, что он был подделан (неверно), поскольку у вас есть приблизительно 1/4 вероятности (поскольку любое значение по модулю 4 может иметь 4 значения), чтобы угадать правильно. Затем вы меняете значение на 1. Если это не работает, чем на 2 и, наконец, на 3.

Один из них может совпадать, но наличие низкого значения по модулю снижает вероятность обнаружения взлома. Таким образом, значение 16 в основном является компромиссом. Вы хотите, чтобы значение по модулю было как можно ниже, чтобы иметь достаточно низкое количество догадок. С другой стороны, вы хотите, чтобы алгоритм был достаточно защищен от взлома по модулю.

1 голос
/ 03 января 2011

Может быть, создатель этого примера кода не хотел проверять все 16 байтов дайджеста, поэтому он решил создать хеш из хеша, для этого и нужна операция мода 16.Он хэширует по модулю 16 первые 16 байтов дайджеста (точнее, это 4-битный дайджест дайджеста), а затем сравнивает результат с 10. Поправьте меня, если я ошибаюсь, но я думаю, что значения 12 и10 выбираются случайным образом, чтобы гарантировать совпадение фактического хэша и значения, с которым он проверяется.

Как сказал Питер, это не совсем идеальное решение.

1 голос
/ 03 января 2011

mod 16 не дает последние 16 байтов или даже самые младшие 4 бита. Это дает остаток от n / 16. Это так же легко может быть как отрицательным, так и положительным и не является хорошим способом для накопления байтов дайджеста.

Вероятность того, что два случайных файла дадут одинаковый результат, составляет 1/31.

Простой способ, который я могу придумать, который был бы гораздо более проницательным, был бы

return new String(digest, 0).hashCode();

Два файла имеют один шанс из 4 миллиардов иметь одинаковый хэш-код, а код намного короче.

...