最近我正在实现一种使用 3DES 的加密算法。但是,我发现4096数据块的前8个字节总是损坏。但可以肯定的是,它可以在java中正确解密。以下是我的代码:
+ (void) DecryptBy3DES:(NSInputStream*)strmSrc Output:(NSOutputStream*)strmDest CryptoRef:(CCCryptorRef)tdesCrypto
{
size_t dataOutMoved;
uint8_t inputBuf[BlockSize];
uint8_t outputBuf[BlockSize];
CCCryptorStatus cryptStatus;
int iBytesRead = 0;
int iBuffUsed = 0;
while ( (iBytesRead = [strmSrc read:inputBuf maxLength:BlockSize]) > 0 )
{
cryptStatus = CCCryptorUpdate(tdesCrypto, &inputBuf, iBytesRead, &outputBuf, BlockSize, &dataOutMoved);
assert(cryptStatus==noErr);
[strmDest write:outputBuf maxLength:dataOutMoved];
}
CCCryptorReset(tdesCrypto, nil);
}
其中块大小为 4096。
我重用了CCCryptoRef tdesCrypto来解密几个区块。要解密的第一个块是正确的,但随后的块在开始时都有损坏的字节。我还尝试重置CCCryptoRef,这似乎是徒劳的。
我真的很困惑。有人有同样的问题吗?
忘记我之前的答案,我删除了它。您在缓冲区中获得"错误字节"的原因是它们是您之前尝试解密的缓冲区的最后 8 个字节的纯文本。
您必须
在最后一次呼叫CCCryptorFinal()
后立即呼叫CCCryptorUpdate()
。这将在写入纯文本的最后几个字节之前删除填充字节。由于密码内部不知道最后一个缓冲区的最后一个块包含填充字节,因此它还不能将数据写入输出缓冲区。
请不要在while循环中破坏或重置CCCryptor。只需将调用添加到CCCryptorFinal()
之后,并且不要忘记将生成的输出也写入流。之后,您可以重置CCCryptor。
我假设(猜测)DESede 带有 CBC 模式和 PKCS#5 填充在这里。请参阅维基百科以了解我在说什么。
的CryptoRef:
CCCryptorCreateWithMode(kCCEncrypt, kCCModeCBC, kCCAlgorithm3DES, ccNoPadding, [abIV bytes], [abKey bytes], [abKey length], nil, 0, 0, kCCModeOptionCTR_BE, &cryptRef);
由于我使用 CBC 模式和 ccNoPadding,因此无需调用 CCCryptorFinal()
。相反,当我完成一个操作(即完成加密/解密一个文件等)时,我应该调用CCCryptorReset()
在下一次操作之前将 CryptoRef 的 iv 重置为初始状态。或者第一个数据块将是缺陷。
感谢您的评论,很抱歉将此问题抛在脑后。我希望这可以帮助遇到同样问题的人。