2014-10-05 58 views
1

如何解密aes 128 ctr加密文件以支持http範圍支持? 這裏是加密文件: https://www.dropbox.com/s/8e9qembud6n3z7i/encrypted.txt?dl=0部分使用aes 128 ctr解密Mega.co.nz文件以支持流式範圍

密鑰BASE64加密:E7VQWj3cv1JUi5pklirtDQ9SRJt1DhiqYgzPSpIiVP0

米加文檔:https://mega.co.nz/#doc

的IV是通過解密其給出陣列中的密鑰計算:

Array 
(
    [0] => 330649690 
    [1] => 1037877074 
    [2] => 1418435172 
    [3] => 2519395597 
    [4] => 257049755 
    [5] => 1963858090 
    [6] => 1645006666 
    [7] => 2451723517 
) 

IV是通過在長度爲2的第4個偏移處對數組進行切片而獲得的並且數組的最後兩個元素被填充以0:

Array 
(
    [0] => 257049755 
    [1] => 1963858090 
    [2] => 0 
    [3] => 0 
) 

然後關鍵是異或並製成128bit的陣列,然後通過PHP函數包轉換成字符串:

$key = array($key[0]^$key[4], $key[1]^$key[5], $key[2]^$key[6], $key[3]^$key[7]); 
$key = base64_encode(a32_to_str($key)); 
$iv = base64_encode(a32_to_str($iv)); 

然後該文件被使用正常解密php aes庫。我正在使用mcrypt_generic進行解密過程。 當我試圖從第二個字節或第三個或中間解密文件時出現問題。 如果我從第一個字節解密它,它工作正常。

我注意到另一件事是,如果我解密從第2個字節的文件,但在此之前,我解密一個隨機字符串或僅僅是數字0,解密從那麼第2個字節的作品。 我想這與IV塊計數器有關。我解密一個隨機字節,然後繼續解密實際的密碼,以便它能正常工作。 我需要從一開始就開始解密文件,可以從40mb偏移量中說出來支持實時搜索。 但是這會消耗太多的內存,因爲在尋求可以完成之前,我將不得不解密40mb的0。 如何將IV計數器值移至40mb偏移?

我讀到IV爲解密每個塊增加+1。但是因爲我的IV是一個數組,所以我嘗試了一切,如果我在其中加1,它就不起作用。 我幾個月沒去過水果。請幫助

這是我剛纔的問題這有助於理解過程中的位:AES 128 bit CTR partial file decryption with PHP

回答

0

您最初的研究確實是正確的。在CTR模式下,IV(或隨機數)在每次加密操作後簡單地增加1。 (加密和解密在CTR模式下是相同的操作,所以您可以根據需要用一個字代替另一個字。)

換句話說,CTR模式密碼的狀態可以預先預測 - 只需添加數字的塊已經加密到最初的IV。特別是,國家不以任何方式依賴明文。 AES具有16的塊大小,因此將由16.

的IV可以被視爲存儲在大端128位整數添加加密的分割的字節數。您使用的加密API將其表示爲四個32位整數的數組。在初始化密碼之前,只需將塊數添加到第四個整數。如果你認爲你需要處理40億塊左右的塊,那麼你需要爲溢出處理添加第三個整數。

稍微有點棘手的部分是將密碼初始化爲已經加密了不能被塊大小整除的字節數的狀態。解決方案是首先將密碼初始化爲已加密的字節數除以16,向下舍入,然後加密(已加密的mod 16的字節數)虛擬字節。我相信這實際上是你已經懷疑的。

你正在寫PHP,但我從我用Java編寫的情況下,它可以幫助一個大型的下載程序發佈的方法:

public Cipher getDownloadCipher(final long startPosition) throws Exception { 
    final Cipher cipher = Cipher.getInstance("AES/CTR/NoPadding"); 
    final ByteBuffer buffer = ByteBuffer.allocate(16).put(nonce); 
    buffer.asLongBuffer().put(startPosition/16); 
    cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(key, "AES"), new IvParameterSpec(buffer.array())); 
    final int skip = (int) (startPosition % 16); 
    if (skip != 0) { 
     if (cipher.update(new byte[skip]).length != skip) { 
      //that should always work with a CTR mode cipher 
      throw new IOException("Failed to skip bytes from cipher"); 
     } 
    } 
    return cipher; 
} 
+0

在這種情況下,'nonce'場8個字節;它是問題中IV的兩個非零整數。 'startPosition/16'長是另外兩個整數。 – ntoskrnl 2014-10-06 11:49:26