Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/iphone/38.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Iphone IOS-如果文件太大,无法将其全部加载到内存中,如何对大文件进行解密?_Iphone_Ios_Encryption_Cryptography - Fatal编程技术网

Iphone IOS-如果文件太大,无法将其全部加载到内存中,如何对大文件进行解密?

Iphone IOS-如果文件太大,无法将其全部加载到内存中,如何对大文件进行解密?,iphone,ios,encryption,cryptography,Iphone,Ios,Encryption,Cryptography,我知道如何加密和解密NSData,但这需要先将整个文件加载到内存中 假设我有一个名为data.dat.enc的50mb加密文件,我如何将其解密为文件data.dat,而不必首先将其全部加载到内存中?您有两个选项(这里我只描述了加密过程,但解密过程类似): 使用流密码(如AES-CTR) 使用16字节密钥初始化密码,然后真正地随机写入16字节nonce,写入nonce,加载第一个片段,加密它,写入结果,加载第二个片段,依此类推。 请注意,您只能初始化密码一次。工件的尺寸可以是任意的; 它甚至不需要

我知道如何加密和解密
NSData
,但这需要先将整个文件加载到内存中

假设我有一个名为
data.dat.enc
的50mb加密文件,我如何将其解密为文件
data.dat
,而不必首先将其全部加载到内存中?

您有两个选项(这里我只描述了加密过程,但解密过程类似):

使用流密码(如AES-CTR)

使用16字节密钥初始化密码,然后真正地随机写入16字节nonce,写入nonce,加载第一个片段,加密它,写入结果,加载第二个片段,依此类推。 请注意,您只能初始化密码一次。工件的尺寸可以是任意的; 它甚至不需要每次都相同

使用具有一次传递链接模式的分组密码,例如AES128-CBC

使用16字节密钥初始化密码,生成一个随机的16字节IV,写入IV,写入文件的总长度,加载第一个片段,将其与IV一起加密,写入结果,加载第二个片段,使用上一个加密块的最后16个字节作为IV加密,写入结果,依此类推。工件的大小必须是16字节的倍数;同样,它甚至不需要每次都相同。您可能需要用零填充最后一个块

在这两种情况下

必须计算原始未加密文件的加密散列(例如,使用SHA-256),并在加密完成时写入。这很容易:您在一开始就初始化散列,并在加载每个块后(包括nonce/IV和可能的length字段)将其馈送给它。在解密端,您也可以这样做。最后,您必须验证计算的摘要是否与加密文件附带的摘要匹配

如何在iOS上做到这一点?恐怕我对平台不熟悉,但似乎符合要求


编辑:nonce/IV和length也是散列的。

编辑:此代码已扩展为


这是一个很好的例子。它来自第11章的示例代码。看看:

+ (BOOL)decryptFromStream:(NSInputStream *)fromStream
                 toStream:(NSOutputStream *)toStream
                 password:(NSString *)password
                    error:(NSError **)error;
它假设盐和IV已经预先添加到流中(这在本书中都有解释)。有关AES加密的更多一般性讨论,请参阅

有关其使用示例,请参见同一项目中的

如果有足够的兴趣,我可以把这个对象拉出来,作为一个独立的项目来支持它,而不仅仅是作为一段示例代码。它似乎对人们相当有用。但整合起来并没有那么难


更一般的答案是,使用
CCCryptorCreate
创建一个加密程序,然后为每个块调用
CCCryptorUpdate
。然后你调用
CCCryptorFinal
来完成事情。

为什么不在加密之前拆分数据,然后取消加密并将其重新组合起来?@PRNDLDevelopmentStudios是的,如果有必要,我想我会这样做,但我有多个大文件,管理一堆分开的文件会更加困难。你可以尝试在加密之前压缩数据,但我不知道压缩比是否足够高,是否真的重要。可能打开到服务器的SSL连接,上传加密数据,服务器解密,然后发送回?首先,使用RC4存在很多问题,请阅读wikipedia页面。RC4不使用IV,尽管一些实现可能会将某些元素称为IV。第二段,使用AES128-CBC作为解决方案是绝对合适的,除了使用零填充。仅仅在纯文本上计算一个哈希值根本不是一个好主意,如果只是因为你会泄露关于所述纯文本的信息(对同一纯文本加密两次,你可以比较结果,举个例子)。如果你将你的CBC解决方案作为一个单独的答案发布,建议使用PKCS#7填充而不是零填充,我很乐意投赞成票。这一个因为许多额外的错误而被否决。请注意,OP的原始代码几乎肯定使用CBC。这是iOS库中的默认设置。几乎没有理由使用EBC(另一种模式),无论您是一次性加密/解密还是“随用随用”。PKCS#7填充也是iOS库支持的唯一填充,因此它可能也已经在使用中(除非负载不需要填充)。当指向RC4时,你应该建议人们如何正确使用它。填充oracle攻击在没有填充oracle的情况下无法工作,为了避免它们,需要进行某种完整性检查/身份验证。仅仅是散列是行不通的,而您对纯文本执行散列的方法显然是错误的。另外,我已经实施了Vaudenay padding Oracle攻击,并在Web服务中的漏洞暴露之前将其用于XML加密。当然,任何东西都可能被错误地使用,但你不能指向RC4,一种具有已知弱点的密码,并期望第一次使用它的用户能够正确使用它。散列并没有错,但是公开你想要保密的文本信息是错误的。PKCS#7的优势在于它或多或少是一种标准,在不需要的情况下,创建自己的带有长度前缀的方案(哪种格式?big-endian?哪种大小?)不是一个好主意。如果得到的是一个流而不是一个文件大小已知的文件,会发生什么?然而,你的假设是正确的,从密码学的角度来说,它并没有错。可能已经猜到某个地方会有一个更新函数。刚刚完成测试。非常感谢!它工作得非常完美:)@Rob在我的测试中,我发现用错误的密码解密加密文件有时会从这个函数返回
true
(大约0.5%的时间)。结果是“