繁体   English   中英

如何可靠地将字符数组转置为uint64_t数组并再次返回

[英]How can I reliably transpose an array of chars to an array of uint64_t and back again

我有一个编码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位块没有被 fread()完全填充,我最终会 bufferText似乎无法摆脱的尾随位(即使我在填充它之前将完整块设置为0) )。 这在解密阶段会引起问题:

原始输入文件:

这是为测试目的而编写的文本文件。 如果DES正常工作,并且文件已正确读取和拆分,则此文本应返回可读且没有错误。

带有尾随“随机”位的解密输出:

这是为测试目的而编写的文本文件。 如果DES正常工作,并且可以正确读取和拆分文件,则此文本应返回可读且无错误†

我试过了: memset(bufferText, 0, length + 8); (以及最后一个参数的变体) bufferText[length/8] = bufferText[length/8]<<((length%8)*8); (以及之后将它们移回原始位置)


编辑-2

以前的编辑已过时,原来我跳过了一部分作业,该作业要求我一次读取一个字节,进而需要使用fgetc()fputc()进行读写。 所有的答案仍然非常有帮助,虽然很重要,但还是要谢谢大家!

在这个答案中,我将解决实际的问题:

从输入文件获取64位块时遇到问题

...而不是目前为止解决的问题:

将文件读入缓冲区后,我的CharArrayToInt64()函数将输入缓冲区的大部分替换为F。

我建议(IMHO)您直接将文件读取到uint64_t数组/缓冲区中 ,而不是从字节数组中复制数据。

当您使用unsigned char数组可能会遇到内存对齐问题时,可以确保uint64_t数组正确地进行了内存对齐,您只需要担心填充问题...

...哦,请使用unsigned版本,如该线程上的其他人所指出的,这就是导致问题转移的原因。

一旦两个数组(加密和解密)使用相同的无符号类型,您的代码就会看起来更加整洁。

祝好运。

问题是在您的情况下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 typecast的更清洁的解决方案,它类似于

 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;删除该行的原因bufferText[i] = 0x0; 另外还有一件事是使用size_t而不是使用long length更好,这与你使用length一起使用更好。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM