我有一个编写DES的类项目,并且在从输入文件中获取64位块时遇到问题。
在加密阶段一切正常,但是当我解密时,在将文件读入缓冲区后,我的CharArrayToInt64()函数用F替换大部分输入缓冲区。
这是我的功能:
void charArrayToInt64(uint64_t *bufferText, char *buffer, long length){
for(size_t i = 0; i < length/8 + 1; i++){
bufferText[i] = 0x0;
bufferText[i] = ((uint64_t)buffer[i*8]<<56)
| ((uint64_t)buffer[i*8 + 1]<<48)
| ((uint64_t)buffer[i*8 + 2]<<40)
| ((uint64_t)buffer[i*8 + 3]<<32)
| ((uint64_t)buffer[i*8 + 4]<<24)
| ((uint64_t)buffer[i*8 + 5]<<16)
| ((uint64_t)buffer[i*8 + 6]<<8)
| ((uint64_t)buffer[i*8 + 7]);
}
}
这是缓冲区的输出,以及加密阶段的uint64_t数组:
Buffer: uint64_t array:
5468 6973 2069 7320 5468 6973 2069 7320
6120 7465 7874 2066 6120 7465 7874 2066
696c 6520 7772 6974 696c 6520 7772 6974
7465 6e20 666f 7220 7465 6e20 666f 7220
7465 7374 2070 7572 7465 7374 2070 7572
706f 7365 732e 2049 706f 7365 732e 2049
6620 4445 5320 776f 6620 4445 5320 776f
726b 7320 636f 7272 726b 7320 636f 7272
6563 746c 792c 2061 6563 746c 792c 2061
6e64 2074 6865 2066 6e64 2074 6865 2066
696c 6520 6973 2072 696c 6520 6973 2072
6561 6420 616e 6420 6561 6420 616e 6420
7370 6c69 7420 7072 7370 6c69 7420 7072
6f70 6572 6c79 2c20 6f70 6572 6c79 2c20
7468 6973 2074 6578 7468 6973 2074 6578
7420 7368 6f75 6c64 7420 7368 6f75 6c64
2072 6574 7572 6e20 2072 6574 7572 6e20
7265 6164 6162 6c65 7265 6164 6162 6c65
2efc ffff ffff fd7f 0000
以下是解密阶段缓冲区和uint64_t数组的输出(请注意,由于我使用的是以前加密的文本,因此它们与上述内容不匹配):
Buffer: uint64_t array:
e824 8aa4 db58 5b12 ffff ffff db58 5b12
b8d2 2b8f 980c 915f ffff ffff ffff 915f
f942 a226 9c69 bcc4 ffff ffff ffff ffc4
c660 bd78 179d b628 ffff ffff ffff b628
1ed1 d846 ceb1 f8b5 ffff ffff ffff ffb5
2e67 fa25 66bd 0f13 ffff ffff ffbd 0f13
d11d 1203 d10f dc9e ffff ffff ffff ff9e
6124 0cf1 9393 3816 ffff ffff ff93 3816
efab b9ad fb20 23c0 ffff ffff ffff ffc0
6a2a 20c1 a610 1422 ffff ffff a610 1422
119d d9c5 9de1 0f08 ffff ffff ffe1 0f08
331e d4e7 2214 bdb1 ffff ffff ffff ffb1
c408 74e2 6e14 84e6 ffff ffff ffff ffe6
3fe6 5eca 04c5 70c6 ffff ffff ffff ffc6
12f8 bcaa 1df7 342d ffff ffff fff7 342d
93eb 15d8 eb8d b51e ffff ffff ffff b51e
7fd2 a2d7 b357 a6eb ffff ffff ffff ffeb
7fb9 bf2b 0ebe bb99 ffff ffff ffff ff99
3300 3300 0000 0000 0000
正如你所看到的,在加密阶段,我的功能只会弄乱最后一行,而在解密阶段,完全相同的功能会扰乱最后一行......
任何帮助都会非常感激,因为我花了几个小时试图弄清楚这一点无济于事。
如果您需要/想要任何额外信息,我会尽力提供。
EDIT-1:在@coderredoc,@ chux和@Myst的帮助下,我的问题基本上已经解决了,代码也更清晰了! (之前的函数 charArrayToInt64()
不再使用)
还有一个问题:那就是如果bufferText
中的最后一个64位bloc没有被fread()
完全填充,我最终会得到我无法摆脱的尾随位(即使我在填充之前将整个块设置为0)。这会在解密阶段导致问题:
原始输入文件:
这是为测试目的而编写的文本文件。如果DES正常工作,并且文件被正确读取和分割,则该文本应该可读并且没有错误。
带有尾随“随机”位的解密输出:
这是为测试目的而编写的文本文件。如果DES工作正常,并且文件被正确读取和拆分,则该文本应该可以返回,并且没有错误的文件
我试过了:
memset(bufferText, 0, length + 8);
(以及最后一个参数的变体)
bufferText[length/8] = bufferText[length/8]<<((length%8)*8);
(以及之后将它们移回原位)
EDIT-2
以前的编辑已经过时,结果我跳过了我的任务的一部分,要求我一次读取一个字节,这又需要使用fgetc()
和fputc()
进行读写。所有的答案仍然非常有用,虽然如此,非常感谢![/ p>
答案 0 :(得分:2)
在这个答案中,我将解决实际问题:
从输入文件中获取64位块时遇到问题
...而不是到目前为止提到的那个:
将文件读入缓冲区后,我的CharArrayToInt64()函数用F替换输入缓冲区的大部分。
我建议(恕我直言)你直接将文件读入uint64_t
数组/缓冲区,而不是从字节数组中复制数据。
虽然unsigned char
数组可能会遇到内存对齐问题,但uint64_t
数组保证正确对齐内存,您只需要担心填充...
...哦,请使用unsigned
版本,正如此帖子中的其他人所指出的那样,这就是造成转变问题的原因。
一旦两个数组(加密和解密)使用相同的无符号类型,您的代码看起来会更清晰。
祝你好运。答案 1 :(得分:1)
问题出在你的情况下char
已签名(这是实现定义的 - 在您的机器中默认签署了char) - 因此在转移时,它会对具有MSB 1
的字符进行预测。导致数字左侧出现一系列ff
。
例如,如果我们将0x24
扩展到所有这些班次,那么它将是
2400000000000000
24000000000000
240000000000
2400000000
24000000
240000
2400
24
对于0xe8
,同样是
e800000000000000
ffe8000000000000
ffffe80000000000
ffffffe800000000
ffffffffe8000000
ffffffffffe80000
ffffffffffffe800
ffffffffffffffe8
现在想想这一点,当你OR
与其他人ff
获胜时,所有的位都被设置了。你看到ff
的。
在您的情况下,正确的解决方案是
bufferText[i] = (((uint64_t)buffer[i*8]<<56) & (uint64_t)0xff<<56)
| (((uint64_t)buffer[i*8 + 1]<<48) & (uint64_t)0xff<<48)
| (((uint64_t)buffer[i*8 + 2]<<40) & (uint64_t)0xff<<40)
| (((uint64_t)buffer[i*8 + 3]<<32) & (uint64_t)0xff<<32)
| (((uint64_t)buffer[i*8 + 4]<<24) & (uint64_t)0xff<<24)
| (((uint64_t)buffer[i*8 + 5]<<16) & (uint64_t)0xff<<16)
| (((uint64_t)buffer[i*8 + 6]<<8) & (uint64_t)0xff<<8)
| (((uint64_t)buffer[i*8 + 7]) & (uint64_t)0xff<<0);
如 chux 所述,使用unsigned char
类型转换有一个更清晰的解决方案,就像
bufferText[i] = ((uint64_t)(unsigned char)buffer[i*8]<<56) |
...
编辑-1
如果您已将char缓冲区类型声明为unsigned
,则不需要void charArrayToInt64(uint64_t *bufferText, char *buffer, long length){
而是在函数明确提及它是unsigned char
缓冲区
void charArrayToInt64(uint64_t *bufferText,unsigned char *buffer, long length){ ...
然后不需要显式演员。你会用原来的方法做得很好。
使用memset
可以清除整个缓冲区。检查该功能。此外,如果您在使用bufferText[i] = 0x0;
的上下文中进行讨论,那么在逻辑上您甚至不需要使用0
对其进行初始化,因为毕竟您下次正在设置它。这就是为什么你甚至可以从代码bufferText[i] = 0x0;
中删除这一行,而不是使用long
长度,最好使用size_t
,这与{{1}一起使用}}