簡體   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