非常に大きなファイル (~50 Go) を XOR したいと思います。
より正確には、平文ファイルの 32 バイトの各ブロック (メモリ不足のため) をキー 3847611839 で XOR し、(ブロックごとに) 新しい暗号ファイルを作成することで、これを行いたいと考えています。
助けてくれてありがとう!!
これは楽しそうで、宿題とは思えません。
試す前に xor で暗号化されたファイルはありませんが、ファイルを前後に変換すると、差分はありません。
少なくとも試したこと。楽しみ!:) この xor は 4 バイトごとに 0xE555E5BF です。
ここにbloxor.cがあります
// bloxor.c - by Peter Boström 2009, public domain, use as you see fit. :)
#include <stdio.h>
unsigned int xormask = 0xE555E5BF; //3847611839 in hex.
int main(int argc, char *argv[])
{
printf("%x\n", xormask);
if(argc < 3)
{
printf("usage: bloxor 'file' 'outfile'\n");
return -1;
}
FILE *in = fopen(argv[1], "rb");
if(in == NULL)
{
printf("Cannot open: %s", argv[2]);
return -1;
}
FILE *out = fopen(argv[2], "wb");
if(out == NULL)
{
fclose(in);
printf("unable to open '%s' for writing.",argv[2]);
return -1;
}
char buffer[1024]; //presuming 1024 is a good block size, I dunno...
int count;
while(count = fread(buffer, 1, 1024, in))
{
int i;
int end = count/4;
if(count % 4)
++end;
for(i = 0;i < end; ++i)
{
((unsigned int *)buffer)[i] ^= xormask;
}
if(fwrite(buffer, 1, count, out) != count)
{
fclose(in);
fclose(out);
printf("cannot write, disk full?\n");
return -1;
}
}
fclose(in);
fclose(out);
return 0;
}
starblueがコメントで述べたように、「これはせいぜい難読化であり、暗号化ではないことに注意してください」。そして、それはおそらく難読化ではありません。
XORの特性の1つは、それ(Y xor 0) == Y
です。これがアルゴリズムにとって意味することは、ゼロが実行される非常に大きなファイルの任意の場所(ファイルのサイズを考えるとおそらくそうです)では、キーが暗号ファイルに表示されるということです。日として平野。
XOR暗号化されたもののもう1つの優れた機能は、誰かが平文と暗号文の両方を持っている場合、それらの項目をXORすると、暗号を繰り返し実行するために使用されるキーを持つ出力が得られることです。2つのファイルが平文/暗号文のペアであることを知っている人は、キーが複数の暗号化に使用されている場合に悪いキーを学習しました。攻撃者が平文と暗号文が関連しているかどうかわからない場合、キーは出力で繰り返されるパターンであるため、この後はかなり良い考えがあります。キーの各ビットが1回だけ使用されるため、これは1つのタイムパッドでは問題になりません。したがって、1人はこの攻撃から新しいことを学びます。
多くの人は、ワンタイムパッドは壊れないことが証明されているので、実行される基本的な操作は同じであるため、XOR暗号化は「うまく行けば」大丈夫だと誤解します。違いは、ワンタイムパッドがキーの各ランダムビットを1回だけ使用することです。したがって、とりわけ、平文にゼロが含まれている場合、単純な固定キーXOR暗号とは異なり、キーについては何も学習されません。
ブルース・シュナイアーが言ったように、「この世界には2種類の暗号化があります。あなたの子供の妹があなたのファイルを読むのを止める暗号化と、主要な政府があなたのファイルを読むのを止める暗号化です。」
XOR暗号は、かろうじて妹の証拠です-それでも。
ストリーミング アーキテクチャに関するソリューションを作成する必要があります。「ストリーム」で入力ファイルを読み取り、それを変更して、結果を出力ファイルに書き込みます。
この方法では、すべてのファイルを一度に読み取る必要はありません。
あなたの質問が、ディスク上の余分なスペースを使用せずにそれを行う方法である場合、32 バイトの倍数 (できるだけ大きいサイズ) でチャンクを読み取り、メモリ内のチャンクで作業してから、再度書き込みます。ftell
および関数を使用してそれを行うことができるはずです (もちろん、型が十分に大きいとfseek
仮定します)。long
アドレス空間をそれほど節約できる場合(およびOSがサポートしている場合)、ファイルをメモリマップする方が速いかもしれませんが、最初に最も簡単な解決策を試してみます.
もちろん、スペースが問題にならない場合は、チャンクを読み込んで、次のような新しいファイルに書き込むだけです (疑似コード):
open infile
open outfile
while not end of infile:
read chunk from file
change chunk
write chunk to outfile
close outfile
close infile
この種の読み取り/処理/書き込みは、かなり基本的なものです。より複雑な要件がある場合は、質問を更新する必要があります。