CCCryptorCreateWithMode忽略填充参数

时间:2017-07-12 13:25:13

标签: objective-c cryptography aes commoncrypto ctr-mode

我正在尝试使用CommonCrypto进行AES-CTR和PKCS7填充加密。

我知道点击率不会需要填充才能正常工作,除此之外还有用于填充的用法。引用RFC 3686

  

出于这个原因,AES-CTR不要求将明文填充到块大小的倍数。但是,为了提供有限的业务流机密性,可以包括填充,如ESP中所述。

引用文档的

Section 2.4是相关的,并列出了填充的几种用法。

因此,我认为CommonCrypto应该能够将填充应用于任何密码(模式)。代码似乎很简单,分解为:

CCCryptorRef cryptor = nil;
NSData* input = [NSMutableData dataWithLength:3];
NSData* key = [NSMutableData dataWithLength:32];
NSMutableData* output = [NSMutableData dataWithLength:32];

CCCryptorCreateWithMode(
        kCCEncrypt, kCCModeCTR, kCCAlgorithmAES, ccPKCS7Padding,
        nil,
        key.bytes, key.length,
        nil, 0, 0,
        kCCModeOptionCTR_BE,
        &cryptor
);

size_t written = 0;
CCCryptorUpdate(
        cryptor,
        input.bytes, input.length,
        output.mutableBytes, output.length,
        &written
);

size_t writtenF = 0;
CCCryptorFinal(
    cryptor, 
    output.mutableBytes + written, output.length - written, 
    &writtenF);

CCCryptorRelease(cryptor);

output.length = written + writtenF;

NSLog(@"Expected: 16 bytes");
NSLog(@"Actual: %i bytes", output.length);

输出结果为:

  

预计:16个字节
  实际:3个字节

如果您检查状态代码,您会发现没有错误。

我可以解密输出就好了,所以加密本身似乎工作得很好。但显然没有填充。

我无法调试到实现,所以我不知道出了什么问题。我是否错误地使用了这些选项?

Nota bene:我可以CCCrypt使用kCCOptionPKCS7Padding进行填充,但后来我没有办法选择点击率模式。

2 个答案:

答案 0 :(得分:2)

  

引用RFC 3686:

     
    

出于这个原因,AES-CTR不要求将明文填充到块大小的倍数。但是,要提供有限的流量     流量机密性,可以包括填充,如ESP中所规定的那样。

  

这是填充的不同用法。块密码中使用的 PKCS#7填充。它是RFC 2406 padding放在有效载荷数据后面的ESP数据包中(见下文)。

  

因此,我认为CommonCrypto应该能够将填充应用于任何密码(模式)......

混乱让你陷入了一个兔子洞。它与您正在考虑的CommonCrypto不相交。现在停止:)

来自RFC 2406的第2页:

2.  Encapsulating Security Payload Packet Format

   The protocol header (IPv4, IPv6, or Extension) immediately preceding
   the ESP header will contain the value 50 in its Protocol (IPv4) or
   Next Header (IPv6, Extension) field [STD-2].

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ----
|               Security Parameters Index (SPI)                 | ^Auth.
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |Cov-
|                      Sequence Number                          | |erage
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ----
|                    Payload Data* (variable)                   | |   ^
~                                                               ~ |   |
|                                                               | |Conf.
+               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |Cov-
|               |     Padding (0-255 bytes)                     | |erage*
+-+-+-+-+-+-+-+-+               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ |   |
|                               |  Pad Length   | Next Header   | v   v
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ ------
|                 Authentication Data (variable)                |
~                                                               ~
|                                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

答案 1 :(得分:-1)

这是一个尝试答案,最终不成功,希望其他人可以使用指针并更好地了解情况。

ccSetupCryptor的{​​{3}}(由CCCryptorCreateWithMode调用),我们发现:

case ccPKCS7Padding:
        if(mode == kCCModeCBC)
            ref->padptr = &ccpkcs7_pad;
        else
            ref->padptr = &ccpkcs7_ecb_pad;
        break;

这似乎表明PKCS7仅适用于CBC和ECB。

但填充应该某事。深入挖掘,ccpkcs7_ecb_pad中定义了const cc2CCPaddingDescriptor ccpkcs7_ecb_pad = { .encrypt_pad = ccpkcs7_encrypt_ecb_pad, .decrypt_pad = ccpkcs7_decrypt_ecb_pad, .padlen = ccpkcs7_padlen, .padreserve = ccpkcs7_reserve, };

ccpkcs7_encrypt_ecb_pad

ccpkcs7_padlen会导致implementation,我确信它不会在点击率模式下执行。

跟踪static size_t ccctr_mode_get_block_size(const corecryptoMode modeObject) { return modeObject.ctr->block_size; } 让我想到了这个:

corecryptoMode

现在,corecryptoSymmetricBridge定义了此block_size,但我找不到public class MyView : MvxActivity<MyViewModel> 的定义,或其他地方。

对于所有AES模式, 为128位,但是由于CTR可以处理任意长度的输入,因此它可能设置为零或一个? 解释为什么会添加零填充字节,但我无法确认是否会发生这种情况。