2013-08-30 15 views
1

我想在沒有填充的CFB模式下使用SecTransformExecute。我試圖得到一個與輸入數據大小相同的加密結果(我相信CFB應該這樣做,因爲它只是將明文與生成的密鑰流的明文進行XOR來創建密文。然而,我的測試代碼在下面,而且它似乎使用填充選項或不導致相同的結果爲20字節的字符串。奇怪的是,一個32字節的字符串似乎有16個字節的填充添加到它的轉換。也許我需要下降到CommonCrypto這個級別的控制?我在這裏錯過了什麼?我想創建一些東西,我可以通過傳遞最後一個塊作爲下一個塊的iv來鏈接新的加密數據。安全性轉換似乎沒有可用的CTR模式在Objective-C安全性轉換中忽略沒有填充的CFB? :與kSedPaddingNoneKey kSecModeCFBKey似乎無論如何填充

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> 
+0

嗨ijcd和歡迎。你是否試圖簡單地將密文縮減爲明文大小?如果不解密,則可以嘗試添加X個字節以再次獲得N倍的塊大小,並使用密文大小作爲明文大小。這可能是該實現僅執行完整塊的XOR。 –

+0

是的,我確實嘗試過。如果我修剪任何數量的密文(甚至1個字節),結果是plainText,但是遺漏了最後4個字節。我猜這是解密和刪除填充,但它不清楚它在做什麼。 – ijcd

+0

@owlstead根據頭文件和https://developer.apple.com/library/mac/documentation/System/Reference/SecEncryptTransform_header_reference/Reference/reference.html它「表示在加密或解密時將使用PKCS7填充。」 – ijcd

回答

0

你用什麼樣的SecKey?例如,AES128-CFB需要填充到16個字節邊界(cipherDataUnpadded會給出null)。

根據使用的加密算法(AES128和AES256是兩種截然不同的算法),CFB只有'塊'的概念。

另請注意,PKCS#7填充即使在滿足塊大小的長度上,也會在消息的長度上至少添加一個八位字節,請參閱RFC5652