【问题标题】:File containing its own checksum包含自己校验和的文件
【发布时间】:2010-11-10 05:19:11
【问题描述】:

是否可以创建一个包含其自己的校验和(MD5、SHA1 等)的文件?为了让小丑们不快,我的意思是简单的校验和,而不是计算它的函数。

【问题讨论】:

    标签: security checksum data-integrity


    【解决方案1】:

    我用 C 编写了一段代码,然后 bruteforce 运行了不到 2 分钟,得到了这个奇迹:

    The CRC32 of this string is 4A1C449B
    

    注意句后不能有字符(行尾等)。

    您可以在这里查看: http://www.crc-online.com.ar/index.php?d=The+CRC32+of+this+string+is+4A1C449B&en=Calcular+CRC32

    这个也很好玩:

    I killed 56e9dee4 cows and all I got was...
    

    源代码(抱歉有点乱)在这里:http://www.latinsud.com/pub/crc32/

    【讨论】:

    • 嘿,你是如何制作这个预计算表的?我也想做同样的事... :)
    • 我想我找到了代码。它很脏,并且没有预先计算的表。 latinsud.com/pub/crc32
    • @LatinSuD 我是一个 java 人,不擅长 c。你能解释一下代码是如何工作的吗?当 crc 是您正在计算的字符串的一部分时,我不明白您如何使用预先计算的表。
    【解决方案2】:

    是的。这是可能的,并且在简单的校验和中很常见。让一个文件包含它自己的 md5sum 将非常具有挑战性。

    在最基本的情况下,创建一个校验和值,这将导致求和的模数等于零。然后校验和函数就变成了

    (n1 + n2 ... + CRC) % 256 == 0
    

    如果校验和则成为文件的一部分,并自行检查。一个非常常见的例子是信用卡号码中使用的Luhn algorithm。最后一位是校验位,它本身就是 16 位数字的一部分。

    【讨论】:

    • 对,我就是这么说的。 :-) 由于它只有 32 位,因此完全可行的解决方案是暴力破解。
    • 这没有显示如何在文件中包含文件的 md5sum,这就是问题所在。
    【解决方案3】:

    检查一下:

    echo -e '#!/bin/bash\necho My cksum is 918329835' > magic
    

    【讨论】:

    • 只是增加了数字并通过 bash 脚本以大约每秒 350 次检查的速度检查了 3 个月左右。我认为这不是该文件唯一有效的 cksum
    【解决方案4】:

    “我希望我的 crc32 是 802892ef...”

    嗯,我觉得这很有趣,所以今天我编写了一个 Java 小程序来查找冲突。以为我会把它留在这里,以防有人发现它有用:

    import java.util.zip.CRC32;
    
    public class Crc32_recurse2 {
    
        public static void main(String[] args) throws InterruptedException {
    
            long endval = Long.parseLong("ffffffff", 16);
    
            long startval = 0L;
    //      startval = Long.parseLong("802892ef",16); //uncomment to save yourself some time
    
            float percent = 0;
            long time = System.currentTimeMillis();
            long updates = 10000000L; // how often to print some status info
    
            for (long i=startval;i<endval;i++) {
    
                String testval = Long.toHexString(i);
    
                String cmpval = getCRC("I wish my crc32 was " + testval + "...");
                if (testval.equals(cmpval)) {
                    System.out.println("Match found!!! Message is:");
                    System.out.println("I wish my crc32 was " + testval + "...");
                    System.out.println("crc32 of message is " + testval);
                    System.exit(0);
                }
    
                if (i%updates==0) {
                    if (i==0) {
                        continue; // kludge to avoid divide by zero at the start
                    }
                    long timetaken = System.currentTimeMillis() - time;
                    long speed = updates/timetaken*1000;
                    percent =  (i*100.0f)/endval;
                    long timeleft = (endval-i)/speed; // in seconds
                    System.out.println(percent+"% through - "+ "done "+i/1000000+"M so far"
                            + " - " + speed+" tested per second - "+timeleft+
                            "s till the last value.");
                    time = System.currentTimeMillis();
                }       
            }       
        }
    
        public static String getCRC(String input) {
            CRC32 crc = new CRC32();
            crc.update(input.getBytes());
            return Long.toHexString(crc.getValue());
        }
    
    }
    

    输出:

    49.825756% through - done 2140M so far - 1731000 tested per second - 1244s till the last value.
    50.05859% through - done 2150M so far - 1770000 tested per second - 1211s till the last value.
    Match found!!! Message is:
    I wish my crc32 was 802892ef...
    crc32 of message is 802892ef
    

    请注意,消息末尾的点实际上是消息的一部分。

    在我的 i5-2500 上,搜索从 00000000 到 ffffffff 的整个 crc32 空间大约需要 40 分钟,大约每秒进行 180 万次测试。它正在最大化一个核心。

    我对 java 还很陌生,所以对我的代码有任何建设性的 cmets 将不胜感激。

    “我的 crc32 是 c8cb204,我得到的只是这件糟糕的 T 恤!”

    【讨论】:

      【解决方案5】:

      当然,这是可能的。但是校验和的用途之一是检测文件的篡改 - 如果修改器也可以替换校验和,您如何知道文件是否已被修改?

      【讨论】:

      • @AmigableClarkKant,我的观点是走这条路是有害的——它首先违背了拥有校验和的目的。该问题特别提到了加密算法,因此我认为其目的是检测故意篡改而不是意外损坏。
      • @MarkRansom 我不会相信任何从缺乏公开讨论如何破解它而获得其“安全性”的加密算法。在这种情况下,应该进行公开讨论。它不会破坏安全性,因为无论如何任何安全性都是假的,这样人们就会知道算法实际上并不安全,他们应该改用其他东西。
      • @flarn2006 我的观点是,将校验和放在文件中根本不会提供任何安全性。如果您想检测文件的意外损坏,那么它可能很有用,但对于故意攻击则毫无价值。
      【解决方案6】:

      当然,您可以将文件本身的摘要连接到文件末尾。要检查它,您将计算除最后一部分之外的所有部分的摘要,然后将其与最后一部分中的值进行比较。当然,如果没有某种形式的加密,任何人都可以重新计算摘要并替换它。

      编辑

      我应该补充一点,这并不罕见。一种技术是连接 CRC-32,以便整个文件(包括该摘要)的 CRC-32 为零。不过,这不适用于基于加密哈希的摘要。

      【讨论】:

        【解决方案7】:

        我不知道我是否正确理解了您的问题,但您可以将文件的前 16 个字节作为文件其余部分的校验和。

        所以在写文件之前,先计算hash,先写hash值,再写文件内容。

        【讨论】:

        • 虽然它是完全有效的实用方法,但我的意思是校验和也会包含自身
        • 我不是数学家,但我认为这根本不可能
        • 不是不可能,但是非常非常难。
        • 对于CRC-32,其实很简单。对于加密哈希,你是完全正确的。
        【解决方案8】:

        在 python-stdnum 库 (see luhn.py) 中有一个简洁的 Luhn Mod N 算法实现。 calc_check_digit 函数将计算一个数字或字符,当附加到文件时(表示为字符串)将创建一个有效的Luhn Mod N 字符串。正如上面许多答案中所指出的,这对文件的有效性进行了健全性检查,但对篡改没有显着的安全性。接收者需要知道使用什么字母来定义 Luhn mod N 的有效性。

        【讨论】:

          【解决方案9】:

          如果问题是询问一个文件是否可以包含它自己的校验和(除了其他内容),对于固定大小的校验和,答案是肯定的,因为一个文件可以包含所有可能的校验和价值观。

          如果问题是一个文件是否可以它自己的校验和组成(仅此而已),构造一个校验和算法来使这样的文件不可能是微不足道的:对于 n 字节校验和,取文件前 n 个字节的二进制表示并加 1。由于构造一个始终对自身进行编码的校验和也很简单(即在不加 1 的情况下执行上述操作),显然有一些校验和 can 对自己进行编码,还有一些不能。可能很难判断其中哪个是标准校验和。

          【讨论】:

            【解决方案10】:

            有很多方法可以嵌入信息以检测传输错误等。CRC校验和擅长检测连续位翻转的运行,并且可以以校验和始终为例如的方式添加。 0. 然而,这类校验和(包括纠错码)很容易重新创建,并且无法阻止恶意篡改。

            如果接收者对发送者一无所知,则不可能在消息中嵌入某些内容以便接收者可以验证其真实性。例如,接收者可以与发送者共享一个密钥。然后,发送者可以附加一个加密的校验和(需要加密安全,例如 md5/sha1)。也可以使用非对称加密,发送者可以发布他的公钥并用他的私钥签署 md5 校验和/哈希。然后可以将哈希和签名作为一种新的校验和标记到数据上。现在互联网上一直都是这样做的。

            剩下的问题是 1. 接收者如何确定他得到了正确的公钥和 2. 所有这些东西在现实中的安全性如何? 1 的答案可能会有所不同。在互联网上,公钥由每个人都信任的人签名是很常见的。另一个简单的解决方案是接收者从个人会议中获得公钥...... 2 的答案可能每天都在变化,但是今天强制执行的成本可能会在未来一段时间内被破坏.到那时,新算法和/或扩大的密钥大小有望出现。

            【讨论】:

              【解决方案11】:

              当然可以,但在这种情况下,整个文件的 SHA 摘要将不是您包含的 SHA,因为它是一个加密散列函数,因此更改文件中的单个位会更改整个散列。您正在寻找的是一个checksum,它使用文件内容以匹配一组标准的方式计算。

              【讨论】:

                【解决方案12】:

                当然。

                最简单的方法是通过 MD5 算法运行文件并将该数据嵌入文件中。如果您想尝试隐藏它,您可以拆分校验和并将其放置在文件的已知点(基于文件的一部分大小,例如 30%、50%、75%)。

                同样,您可以加密文件,或加密文件的一部分(连同 MD5 校验和)并将其嵌入文件中。 编辑 我忘了说您需要在使用之前删除校验和数据。

                当然,如果您的文件需要易于被其他程序读取,例如Word 然后事情变得有点复杂,因为您不想“损坏”文件使其不再可读。

                【讨论】:

                • 如果您将这些数据嵌入到文件中,那不会改变 md5 校验和吗?
                • 如果您再次对其运行校验和例程就会出现这种情况,但这是在使用前将其删除的关键。最简单的方法是将校验和添加到文件的末尾。收到文件后,您删除校验和数据并在剩余数据上重新运行校验和例程。校验和或原始数据的任何数据损坏都会显示在此处。
                • 我相当肯定 zakovyrya 要求校验和包含在它自己的计算中。
                猜你喜欢
                • 2022-11-25
                • 1970-01-01
                • 2012-01-13
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2012-12-05
                • 2013-05-23
                相关资源
                最近更新 更多