这对某些人来说可能真的很容易。我不太明白如何使用密码分析和蛮力破解 XOR 加密文件。我有一个PDF文件,它使用一个程序加密,该程序将八个字节乘以八个字节进行XOR处理。程序代码是
int main(int argc, char** argv) {
if (argc!=3) {
printf("command (for example) : ./enc1 file_to_encrypt key_in_hexn");
return 1;
}
// get the key
unsigned long long key=strtoull(argv[2], NULL, 16);
// open the file
char* file=argv[1];
int fdp=open(file, O_RDONLY);
if (fdp<0) {
printf("cannot open the file %sn", file);
return 1;
}
// open the file to save the encryption
char enc[strlen(file)+10];
strncpy(enc, file, strlen(file));
strncpy(enc+strlen(file), ".enc1 ", 5);
enc[strlen(file)+5]=' ';
int fdc=open(enc, O_CREAT|O_WRONLY, S_IRUSR|S_IWUSR);
if (fdc<0) {
printf("cannot save the encrypted file %sn", enc);
return 1;
}
// encryption
unsigned long long buf;
unsigned long long k;
int len;
k=key;
while ((len=read(fdp, (char*)&buf, 8))>0) {
buf^=k;
k*=key;
write(fdc, (char*)&buf, len);
}
close(fdp);
close(fdc);
return 0;
}
我知道PDF文件的标题是
%PDF-1.0%PDF-1.1
如何使用该信息获取明文?我是否对标题进行了 Xored ?非常感谢
XOR很容易逆转。假设 m 是您的原始文件,e 是其加密版本。然后
e[0] = k[0] ^ m[0]
e[1] = k[1] ^ m[1]
e[2] = k[2] ^ m[2]
e[3] = k[3] ^ m[3]
但是XOR是可逆的,所以你可以通过知道e和m的一部分来找到k:
k[0] = e[0] ^ m[0]
k[1] = e[1] ^ m[1]
k[2] = e[2] ^ m[2]
k[3] = e[3] ^ m[3]
OP 尚未接受答案,并且似乎仍然有问题,因此这是我的答案,借鉴了 user1202136 和 OmnipotentEntity 的答案。
要确定密钥,请逐个字符对加密文件的前 8 个字符进行 XOR 操作,其中包含您期望的标头字符串,例如 %PDF-1.4。结果是一个相同长度的字符串,您可以将其复制到密钥的unsigned long long
中(也占用 8 个字节)。程序需要十六进制键值,因为strtoull
给定的基参数为 16。因此,请使用 %llx
说明符来格式化结果,否则它将是十进制的并且不起作用。
void find_key(const char *filename, const char *m)
{
// open the encrypted file
FILE *fp = fopen(filename, "r");
if (!fp)
return;
// read encrypted header
char e[8];
for (int i = 0; i < 8; i++)
e[i] = fgetc(fp);
fclose(fp);
// xor with known header
char k[8];
for (int j = 0; j < 8; j++)
k[j] = e[j] ^ m[j];
// copy into 8 byte value, and output in base-16
unsigned long long newkey;
memcpy(&newkey, &k, 8);
printf("Testing for %s gives key %llxn", m, newkey);
}
由于您不确定标头版本,因此使用不同的选项运行几次。如果加密文件是这些.pdf版本之一,那么您将有一个用于解密它的密钥。
int main(int argc, char *argv[])
{
if (argc != 2)
return 1;
find_key(argv[1], "%PDF-1.0");
find_key(argv[1], "%PDF-1.1");
find_key(argv[1], "%PDF-1.2");
find_key(argv[1], "%PDF-1.3");
find_key(argv[1], "%PDF-1.4");
return 0;
}
您的程序用于加密和解密。这是因为如上所述的异或的可逆性质。将加密的文件名和生成的密钥作为参数传递。
在此测试示例中,我首先使用给定密钥使用程序加密.pdf,然后使用上述方法再次找到密钥,然后使用最佳密钥结果使用程序解密它。
$ ./enc1 test.pdf 1234ABCD
$ ./find-key test.pdf.enc1
Testing for %PDF-1.0 gives key 30000001234abcd
Testing for %PDF-1.1 gives key 20000001234abcd
Testing for %PDF-1.2 gives key 10000001234abcd
Testing for %PDF-1.3 gives key 1234abcd
Testing for %PDF-1.4 gives key 70000001234abcd
$ ./enc1 test.pdf.enc1 1234abcd
希望这有帮助。
要添加到user1202136的答案中,
如果您有两条不同的消息使用相同的密钥编码,则可以检索密钥(以及两条消息)的前n
个字符(其中n
是较短消息的长度)(这就是WEP破解的工作方式,孩子们。 (以下内容不是代码,而是数学。
eA[0] = k[0] ^ mA[0]
eB[0] = k[0] ^ mB[0]
eA[0] ^ eB[0] = k[0] ^ k[0] ^ mA[0] ^ mB[0]
eA[0] ^ eB[0] = mA[0] ^ mB[0]
eA[0] ^ eB[0] ^ mA[0] = mB[0]
mB[0] ^ eB[0] = k[0]