2014-10-05 41 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