我收到了一个加密文件,其中明文的格式是“常见的(但现在不是很常见)”。~80000 字节
它已使用我将描述为带有修改加密表的 Vigenere 密码进行加密。一个字节的密钥和一个字节的明文映射到一个字节的密文。密钥串具有一定的长度,因此用于加密的密钥字符在密钥串中循环。
密钥仅包含字母数字字符。
到目前为止,我通过找到密文中重复三元组的起始位置的最小公约数来确定密钥长度为 30/60。Vigenere 的标准。
现在,我一直在猜测密钥的可能字符,方法是观察解密的字节是什么,并消除它们超出可接受范围的可能性(因为 32-126 是可见的,没有 16-31 之间的值等)
这个第一部分工作,它有一个小密钥,明文是直接的 ASCII。
当我尝试使用较大的文件和“新文件格式”时,它会拒绝所有可能的字符。
这消除了 ASCII、Ascii85、Base64、windows-1252、utf-7、QP 和 uuencode,因为它们都依赖于 ASCII 字符集。我还为拒绝所有密钥的 EBCDIC 和 ISO8859-1 制作了过滤器。Utf-8 也失败了,因为没有密钥会使所有字节都以 0、10、110、1110、11110、111110 或 1111110 开头。
我没有尝试过的其余字符编码我怀疑是 UTF-16,32,1,我不确定如何过滤。
我的问题是:
- 还有其他我忘记的字符编码吗?
- 是否有可能我过滤掉了太多并且应该允许一些超出范围的字符滑过?
- 文件格式可能意味着字符编码以外的东西吗?如果是这样,我该如何协调它与过滤器仍然破坏 ASCII 字符?
- 如果文件格式意味着压缩或存档怎么办?
这是我使用的过滤代码,过滤器是可变的,具体取决于我要筛选的内容。
void guessCrypt(string fileName, int keyLength, int index)
{
byte[] file = cast(byte[])read(fileName);
foreach(key;ValidKeyChars)
{
bool work = true;
for(int x = index; x < file.length-10; x+=keyLength)
{
byte single = file[x];
int res = sdecrypt(single,key);
if ((res < 32 && res > 15) || res > 126) //FILTER - this one ASCII
{
work = false;
break;
}
}
if (work == true)
{
writefln("\nwork: %s",key);
}
}
}