2011-01-03 7 views
3

Ich habe hier einen kleinen Java-Selbst Prüfprogramm analze ist die ProbeJava Selbst cheking Programm (Auto-Prüfsumme)

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

     } 
} 

aber ich nicht wirklich understant warum ein mod 16 und Ergebnis legen tun = 12 ?

Antwort

1

Mod 16 gibt nicht die letzten 16 Bytes oder sogar die niedrigsten 4 Bits. Es gibt den Rest von n/16. Dies kann ebenso einfach negativ wie positiv sein und ist keine gute Möglichkeit, die Bytes des Digests zu kumulieren.

Es besteht eine Wahrscheinlichkeit von 1/31, dass zwei zufällige Dateien das gleiche Ergebnis liefern.

Die einfache Weise, die ich davon denken kann, wäre viel mehr anspruchsvolle

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

zwei Dateien eine Eins in 4 Milliarden Chance sein würde, hätten den gleichen Hash-Code zu haben und der Code ist viel kürzer.

1

Vielleicht wollte der Schreiber dieses Beispielcodes nicht die ganzen 16 Bytes des Digests überprüfen, also entschied er sich, einen Hash aus dem Hash zu machen, dafür ist die Mod 16 Operation gedacht. Es hashes modulo 16 die ersten 16 Bytes des Digests (um genauer zu sein, es ist ein 4-Bit-Digest des Digests), und vergleicht dann das Ergebnis mit 10. Korrigieren Sie mich, wenn ich falsch liege, aber ich denke, die Werte 12 und 10 werden nach dem Zufallsprinzip ausgewählt, um sicherzustellen, dass der tatsächliche Hash und der Wert, gegen den er geprüft wird, übereinstimmen.

Wie Peter sagte, es ist keine vollkommene Lösung.

2

Es ist wahrscheinlich, denn ohne den Modulo wäre es sehr schwer die Prüfsumme einzubetten. Stellen Sie sich vor, Sie haben das Programm geschrieben. Sie können alles auf einmal schreiben, aber um eine korrekte Prüfsumme zu haben, müssen Sie experimentieren.

Nehmen wir an, Sie schreiben die Prüfsumme modulo 4. Am Anfang vergleichen Sie den Wert mit 0. Sie starten das Programm, aber es erkennt, dass es manipuliert wurde. Warum? Weil Sie die Prüfsumme erst kennen, wenn Sie den gesamten Quellcode schreiben. Und da der Prüfsummenwert darin eingebettet ist, ändert jede Änderung des Quellcodes die Prüfsumme.

So ist es wie ein Hund, der seinen eigenen Schwanz jagt. Oder eine Schlange, die ihren eigenen Schwanz isst. Technisch gesehen ist dies eine Situation eines dynamischen Systems mit einer Rückkopplungsschleife darin. Ok, das ist genug von Analogien.

Der einzige Weg, es zum Laufen zu bringen, ist zu experimentieren. Beginnen Sie mit einer Prüfsumme gleich Null und kompilieren. Höchstwahrscheinlich wird es erkennen, dass es manipuliert wurde (unkorrekt), da Sie etwa 1/4 Wahrscheinlichkeit haben (da jeder Wert modulo 4 4 Werte haben kann), um richtig zu raten. Als nächstes ändern Sie den Wert zu 1. Wenn es nicht funktioniert als zu 2 und zuletzt zu 3.

Einer von ihnen könnte übereinstimmen, aber mit niedrigen Modulo-Wert verringert die Wahrscheinlichkeit der Erkennung der Manipulation. Der Wert 16 ist also grundsätzlich ein Kompromiss. Sie möchten den Modulo-Wert so niedrig wie möglich halten, um eine vernünftige Anzahl von Raten zu erhalten. Auf der anderen Seite möchten Sie, dass der Algorithmus ziemlich manipulationssicher ist, indem er Modulo-Wert hoch hat.