web-dev-qa-db-ja.com

独自のチェックサムを含むファイル

独自のチェックサム(MD5、SHA1など)を含むファイルを作成することはできますか?ジョーカーを混乱させるために、私はプレーンなチェックサムを意味し、それを計算する関数ではありません。

48
zakovyrya

私はCでコードの一部を作成し、ブルートフォースを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/

33
LatinSuD

はい。それは可能であり、単純なチェックサムでは一般的です。独自のmd5sumを含むファイルを取得するのは非常に困難です。

最も基本的なケースでは、合計された係数がゼロになるチェックサム値を作成します。チェックサム関数は次のようになります

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

チェックサムがファイルの一部になると、それ自体がチェックされます。これの非常に一般的な例は、クレジットカード番号で使用される Luhnアルゴリズム です。最後の桁はチェックディジットであり、それ自体が16桁の数字の一部です。

17
brianegge

これをチェックして:

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

"自分の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万回のテストを実行していました。 1つのコアを使い果たしました。

私はJavaでかなり新しいので、私のコードに対する建設的なコメントがあれば幸いです。

"私のcrc32はc8cb204で、私が手に入れたのはこのお粗末なTシャツだけでした!"

8
localhost

確かに、それは可能です。しかし、チェックサムの用途の1つは、ファイルの改ざんを検出することです。ファイルが変更されているかどうか、修飾子もチェックサムを置き換えることができる場合、どうすればわかりますか?

7
Mark Ransom

もちろん、ファイル自体のダイジェストをファイルの最後に連結することができます。これをチェックするには、最後の部分を除くすべてのダイジェストを計算し、最後の部分の値と比較します。もちろん、何らかの暗号化がなければ、だれでもダイジェストを再計算して置き換えることができます。

編集する

これはそれほど珍しいことではありません。 1つの手法は、CRC-32を連結して、ファイル全体(そのダイジェストを含む)のCRC-32がゼロになるようにすることです。ただし、これは暗号化ハッシュに基づくダイジェストでは機能しません。

5
Steven Sudit

あなたの質問を正しく理解しているかどうかはわかりませんが、ファイルの最初の16バイトを残りのファイルのチェックサムにすることができます。

したがって、ファイルを書き込む前に、ハッシュを計算し、最初にハッシュ値を書き込んでから、ファイルの内容を書き込みます。

2

Python-stdnumライブラリーにLuhn Mod Nアルゴリズムのきちんとした実装があります( luhn.py を参照)。 calc_check_digit関数は、数字または文字を計算し、ファイルに追加すると(文字列として表現)、有効なLuhn Mod N文字列を作成します。上記の多くの回答で述べたように、これはファイルの有効性の健全性チェックを提供しますが、改ざんに対する重要なセキュリティは提供しません。受信者は、Luhn mod Nの有効性を定義するために使用されているアルファベットを知る必要があります。

1
Martin Juckes

ファイルが(他のコンテンツに加えて)contain自身のチェックサムを実行できるかどうかを尋ねる質問の場合、ファイルにはすべての可能なチェックサム値が含まれる可能性があるため、固定サイズのチェックサムの答えは簡単です。

質問が、ファイルがconsist of独自のチェックサム(およびそれ以外)であるかどうかである場合、そのようなファイルを不可能にするチェックサムアルゴリズムを構築するのは簡単です。nバイトのチェックサムの場合、ファイルの最初のnバイトのバイナリ表現と1を追加します。常にそれ自体をエンコードするチェックサムを作成することも簡単です(つまり、1を追加せずに上記を行う)ので、明らかにcanのチェックサムがいくつかあります自分自身をエンコードし、その一部はcannotです。これらのうちどれが標準チェックサムであるかを判別することはおそらく非常に難しいでしょう。

1
tloflin

承知しました。

最も簡単な方法は、MD5アルゴリズムを使用してファイルを実行し、そのデータをファイル内に埋め込むことです。チェックサムを分割して、ファイルの既知のポイントに配置できます(30%、50%、75%など、ファイルの一部のサイズに基づいて)。

同様に、ファイルを暗号化するか、ファイルの一部を(MD5チェックサムとともに)暗号化して、ファイルに埋め込むことができます。 編集使用する前にチェックサムデータを削除する必要があることを忘れていました。

もちろん、ファイルを別のプログラムで簡単に読み取れるようにする必要がある場合。 Wordは、ファイルを "破損"させて読み取り不可能にしたくないので、少し複雑になります。

0
ChrisBD

もちろんできますが、その場合、ファイル全体のSHAダイジェストは、SHA含まれていません。これは暗号化ハッシュ関数であるため、したがって、ファイル内の単一のビットを変更すると、ハッシュ全体が変更されます。探しているのは、一連の基準に一致するようにファイルのコンテンツを使用して計算された checksum です。

0
bandi

伝送エラーなどを検出するために情報を埋め込むには多くの方法があります。CRCチェックサムは、連続するビットフリップの実行を検出するのに優れており、チェックサムが常にあるように追加される場合があります。 0.ただし、これらの種類のチェックサム(エラー修正コードを含む)は簡単に再作成でき、悪意のある改ざんを防ぎません。

メッセージに何かを埋め込むことは不可能であり、受信者が送信者について/送信者から他に何も知らない場合、受信者はその信頼性を検証できます。たとえば、受信者は送信者と秘密鍵を共有できます。次に、送信者は暗号化されたチェックサムを追加できます(md5/sha1など、暗号的に安全である必要があります)。送信者が自分の公開鍵を公開し、自分の秘密鍵でmd5チェックサム/ハッシュに署名できる非対称暗号化を使用することもできます。ハッシュと署名は、新しい種類のチェックサムとしてデータにタグ付けできます。これは、今日インターネット上で常に行われています。

残りの問題は、1。受信者が正しい公開鍵を取得したことをどのように確認できるか、2。これらすべてが実際にどれほど安全か、です。 1に対する答えは異なる場合があります。インターネットでは、誰もが信頼する誰かが公開鍵に署名するのが一般的です。もう1つの簡単な解決策は、受信者が個人的に会議から公開鍵を取得することです... 2への答えは日々変わる可能性がありますが、日々強制するのにコストがかかるものは、おそらく将来的に中断するのに安くなるでしょう。 。その時までに、新しいアルゴリズムおよび/または拡大されたキーサイズがうまくいけば出現しました。

0
Markarian451