1

我正在尝试在没有填充的 CFB 模式下使用 SecTransformExecute。我正在尝试获得与输入数据大小相同的加密结果(我相信 CFB 应该这样做,因为它只是将明文与块生成的密钥流进行异或以创建密文。但是,我的测试代码如下,它似乎是否使用填充选项会导致 20 字节字符串的结果相同。奇怪的是,一个 32 字节的字符串似乎通过转换添加了 16 个字节的填充。也许我需要下拉到 CommonCrypto 这个级别控制?我在这里错过了什么?我想创建一些东西,我可以通过将最后一个块作为下一块的 iv 传递,将新的加密数据链接到末尾。安全转换似乎没有可用的 CTR 模式.

CFErrorRef error = NULL;

// 16 byte buffer with random data for iv
NSData *iv = [NSMutableData dataWithLength:16];
arc4random_buf((void *)[iv bytes], 16);
DDLogVerbose(@"iv: %@, length: %lu", iv, [iv length]);

// something to encrypt
NSString *plainText = @"I'm a secret string."; // 20 bytes
NSData *plainData = [plainText dataUsingEncoding:NSUTF8StringEncoding];

DDLogVerbose(@"plainText           : %lu : %@", [plainText length], plainText);
DDLogVerbose(@"plainData           : %lu : %@", [plainData length], plainData);

// setup padding encryptor
SecTransformRef encryptPadded = SecEncryptTransformCreate(key, &error);
SecTransformSetAttribute(encryptPadded, kSecModeCFBKey, NULL, &error);
SecTransformSetAttribute(encryptPadded, kSecPaddingKey, kSecPaddingPKCS7Key, &error);
SecTransformSetAttribute(encryptPadded, kSecIVKey, (__bridge CFTypeRef)(iv), &error);
SecTransformSetAttribute(encryptPadded, kSecTransformInputAttributeName, (__bridge CFTypeRef)(plainData), &error);

// encrypt with it
NSData *cipherDataPadded = (__bridge NSData *) SecTransformExecute(encryptPadded, &error);
DDLogVerbose(@"cipherDataPadded    : %lu : %@", [cipherDataPadded length], cipherDataPadded);

// setup unpadded encryptor
SecTransformRef encryptUnpadded = SecEncryptTransformCreate(key, &error);
SecTransformSetAttribute(encryptUnpadded, kSecModeCFBKey, NULL, &error);
SecTransformSetAttribute(encryptUnpadded, kSecPaddingKey, kSecPaddingNoneKey, &error);
SecTransformSetAttribute(encryptUnpadded, kSecIVKey, (__bridge CFTypeRef)(iv), &error);
SecTransformSetAttribute(encryptUnpadded, kSecTransformInputAttributeName, (__bridge CFTypeRef)(plainData), &error);

// encrypt with it
NSData *cipherDataUnpadded = (__bridge NSData *) SecTransformExecute(encryptUnpadded, &error);
DDLogVerbose(@"cipherDataUnpadded  : %lu : %@", [cipherDataUnpadded length], cipherDataUnpadded);

// something to encrypt
NSString *plainText32 = @"I'm a secret string of 32 bytes."; // 20 bytes
NSData *plainData32 = [plainText32 dataUsingEncoding:NSUTF8StringEncoding];

DDLogVerbose(@"plainText32         : %lu : %@", [plainText32 length], plainText32);
DDLogVerbose(@"plainData32         : %lu : %@", [plainData32 length], plainData32);

// setup padded encryptor for 32 bytes
SecTransformRef encryptPadded32 = SecEncryptTransformCreate(key, &error);
SecTransformSetAttribute(encryptPadded32, kSecModeCFBKey, NULL, &error);
SecTransformSetAttribute(encryptPadded32, kSecPaddingKey, kSecPaddingPKCS7Key, &error);
SecTransformSetAttribute(encryptPadded32, kSecIVKey, (__bridge CFTypeRef)(iv), &error);
SecTransformSetAttribute(encryptPadded32, kSecTransformInputAttributeName, (__bridge CFTypeRef)(plainData32), &error);

// encrypt with it
NSData *cipherDataPadded32 = (__bridge NSData *) SecTransformExecute(encryptPadded32, &error);
DDLogVerbose(@"cipherDataPadded32  : %lu : %@", [cipherDataPadded32 length], cipherDataPadded32);

// setup unpadded encryptor for 32 bytes
SecTransformRef encryptUnpadded32 = SecEncryptTransformCreate(key, &error);
SecTransformSetAttribute(encryptUnpadded32, kSecModeCFBKey, NULL, &error);
SecTransformSetAttribute(encryptUnpadded32, kSecPaddingKey, kSecPaddingNoneKey, &error);
SecTransformSetAttribute(encryptUnpadded32, kSecIVKey, (__bridge CFTypeRef)(iv), &error);
SecTransformSetAttribute(encryptUnpadded32, kSecTransformInputAttributeName, (__bridge CFTypeRef)(plainData32), &error);

// encrypt with it
NSData *cipherDataUnpadded32 = (__bridge NSData *) SecTransformExecute(encryptUnpadded32, &error);
DDLogVerbose(@"cipherDataUnpadded32: %lu : %@", [cipherDataUnpadded32 length], cipherDataUnpadded32);

产生以下输出:

>>> plainText           : 20 : I'm a secret string.
>>> plainData           : 20 : <49276d20 61207365 63726574 20737472 696e672e>
>>> cipherDataPadded    : 32 : <54e26843 a6e96b71 6ebe4605 5c10ec1e 28b9c87a a2574f21 66e788c4 dfca3f32>
>>> cipherDataUnpadded  : 32 : <54e26843 a6e96b71 6ebe4605 5c10ec1e 28b9c87a a2574f21 66e788c4 dfca3f32>
>>> plainText32         : 32 : I'm a secret string of 32 bytes.
>>> plainData32         : 32 : <49276d20 61207365 63726574 20737472 696e6720 6f662033 32206279 7465732e>
>>> cipherDataPadded32  : 48 : <54e26843 a6e96b71 6ebe4605 5c10ec1e 63cd5eaf 5e86fb77 d672cd15 528f19b5 2b0bcff4 c5cb2ca6 bc195f9d bba54baf>
>>> cipherDataUnpadded32: 48 : <54e26843 a6e96b71 6ebe4605 5c10ec1e 63cd5eaf 5e86fb77 d672cd15 528f19b5 2b0bcff4 c5cb2ca6 bc195f9d bba54baf>
4

1 回答 1

0

你用什么样的SecKey?例如 AES128-CFB 需要填充到 16 字节边界(cipherDataUnpadded 将给出null)。

CFB 只有一个“块”的概念,具体取决于所使用的加密算法(AES128 和 AES256 是两种不同的算法)。

另请注意,PKCS#7 填充将至少一个八位位组添加到消息的长度中,即使长度会满足块大小,请参阅RFC5652

于 2013-09-01T21:04:50.950 回答