3

我必须分析一个小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);
          }

      }
}

但我真的不明白为什么要做一个 mod 16 并把 result = 12 ?

4

3 回答 3

2

这可能是因为没有模数就很难嵌入校验和。假设您已经编写了程序。您可以一次编写所有内容,但要获得正确的校验和,您必须进行试验。

假设您编写了以 4 为模的校验和。一开始您将值与 0 进行比较。您运行程序,但它检测到它被篡改了。为什么?因为在您编写完整的源代码之前您不知道校验和。并且由于校验和值嵌入其中,源代码的每次更改都会更改校验和。

所以它就像一条狗追逐自己的尾巴。或者一条蛇吃自己的尾巴。从技术上讲,这是一种带有反馈回路的动态系统的情况。好的,类比就够了。

让它发挥作用的唯一方法是进行实验。从校验和为零开始并编译。很可能它会识别它被篡改(不正确),因为您有大约 1/4 的概率(因为任何模 4 的值都可以有 4 个值)来正确猜测。接下来,将值更改为 1。如果它不起作用,则更改为 2,最后更改为 3。

其中之一可以匹配,但具有低模值会降低检测篡改的可能性。所以值 16 基本上是一个折衷方案。您希望将模值保持在尽可能低的水平,以便进行合理的猜测。另一方面,您希望算法通过具有高模值来防篡改。

于 2011-01-03T20:11:49.847 回答
1

mod 16 没有给出最后 16 个字节,甚至没有给出最低 4 位。它给出了 n / 16 的余数。这可以很容易地成为负数和正数,并且不是累积摘要字节的好方法。

两个随机文件产生相同结果的可能性为 1/31。

我能想到的最简单的方法是

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

两个文件有 40 亿分之一的机会拥有相同的哈希码,而且代码要短得多。

于 2011-01-03T20:07:46.007 回答
1

也许这个示例代码的作者不想检查整个 16 字节的摘要,所以他决定从散列中做一个散列,这就是 mod 16 操作的目的。它对摘要的前 16 个字节进行模 16 散列(更具体地说,它是摘要的 4 位摘要),然后将结果与 10 进行比较。如果我错了,请纠正我,但我认为值 12 和10 是随机选择的,以确保实际的哈希值和它检查的值匹配。

正如彼得所说,这不是一个非常完美的解决方案。

于 2011-01-03T20:11:27.920 回答