我在 Java 中使用 CTR 模式加密了一条消息,并试图在 iOS 中解密该消息。但是,我的测试程序在解密时会打乱最后一个块
代码如下:
+ (NSData *)doCipher:(NSData *)data key:(NSData *)symmetricKey context:(CCOperation)encryptOrDecrypt {
CCCryptorStatus status = kCCSuccess;
// symmetric cipher reference
CCCryptorRef cryptor = NULL;
// Cipher Text container.
NSData *cipherOrPlainText = nil;
// Pointer to output buffer.
uint8_t *bufferPtr = NULL;
// Remaining bytes to be performed on.
size_t remainingBytes = 0;
// Number of bytes moved to buffer.
size_t movedBytes = 0;
// Total size of the buffer.
size_t bufferPtrSize = 0;
// Placeholder for total written.
size_t totalBytesWritten = 0;
// A friendly helper pointer.
LOGGING_FACILITY(data != nil, @"PlainText object cannot be nil." );
LOGGING_FACILITY(symmetricKey != nil, @"Symmetric key object cannot be nil." );
LOGGING_FACILITY([symmetricKey length] == kCCKeySizeAES256, @"Disjoint choices for key size." );
// pointer to the bytes
void *inputDatPtr = [data bytes];
// Initialization vector;
void *ivPtr;
void *dataPtr = &inputDatPtr[0];
size_t dataBufferSize = [data length];
if (encryptOrDecrypt == kCCDecrypt) {
// iv is first block
ivPtr = &inputDatPtr[0];
dataPtr+= kCCBlockSizeAES128;
dataBufferSize -= kCCBlockSizeAES128;
// NSData *iv = [[data subdataWithRange:NSMakeRange(0, kCCBlockSizeAES128)] copy];
// ivPtr = [iv bytes];
// NSData *inputData = [[data subdataWithRange:NSMakeRange(kCCBlockSizeAES128, data.length - kCCBlockSizeAES128)] copy];
// dataPtr = [inputData bytes];
} else {
NSData *iv = [self generateIv];
ivPtr = [iv bytes];
}
LOGGING_FACILITY(dataBufferSize > 0, @"Empty plaintext passed in." );
// Create and Initialize the cipher reference.
status = CCCryptorCreateWithMode(kCCEncrypt, kCCModeCTR, kCCAlgorithmAES128, ccNoPadding,
ivPtr, [symmetricKey bytes], kCCKeySizeAES256, NULL, 0, 0, kCCModeOptionCTR_BE, &cryptor);
LOGGING_FACILITY1( status == kCCSuccess, @"Problem creating the context, status == %d.", status );
// Calculate byte block alignment for all calls through to and including final.
bufferPtrSize = CCCryptorGetOutputLength(cryptor, dataBufferSize, true);
// Allocate buffer.
bufferPtr = malloc(bufferPtrSize * sizeof(uint8_t));
// Zero out buffer.
memset((void *) bufferPtr, 0x0, bufferPtrSize);
// Initialize some necessary book keeping.
uint8_t *ptr = bufferPtr;
// Set up initial size.
remainingBytes = bufferPtrSize;
// Actually perform the encryption or decryption.
status = CCCryptorUpdate(cryptor,
dataPtr,
dataBufferSize,
ptr,
remainingBytes,
&movedBytes
);
LOGGING_FACILITY1( status == kCCSuccess, @"Problem with CCCryptorUpdate, status == %d.", status );
// Handle book keeping.
ptr += movedBytes;
remainingBytes -= movedBytes;
totalBytesWritten += movedBytes;
// Finalize everything to the output buffer.
status = CCCryptorFinal(cryptor,
ptr,
remainingBytes,
&movedBytes
);
totalBytesWritten += movedBytes;
if (cryptor) {
(void) CCCryptorRelease(cryptor);
cryptor = NULL;
}
LOGGING_FACILITY1( status == kCCSuccess, @"Problem with encipherment status == %d", status );
cipherOrPlainText = [NSData dataWithBytes:bufferPtr length:(NSUInteger) totalBytesWritten];
if (bufferPtr) free(bufferPtr);
return cipherOrPlainText;
}
测试代码为:
NSString *base64Encrypted = [NSString stringWithFormat:@"HWwBZ7Tw94Bk6qTWbXlvRvISkLZrxxy7bmHG1pFWMGgsuA2LY1Q="];
NSData *encrypted = [NSData dataWithBase64EncodedString:base64Encrypted];
NSString *hexKey = @"38a3ba5932c14cd99924eb303fab0c35f300e1bf022286d15160edd247ef263c";
NSData *keyData = [Crypto dataForHexString:hexKey];
NSData *data = [Crypto doCipher:encrypted key:keyData context:kCCDecrypt];
NSString *decryptedText = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
NSLog(@"decrypted: %@", decryptedText);
消息应该是:Multiple block message
但是我得到的输出:
2012-11-29 11:04:22.209 crypto-test[23748:1307] decrypted: Multiple block mtn4¶
请注意,IV 是随机生成并附加到密文的,并且数据应该是 UTF8 编码的(但是在将编码设置为 NSUTF8StringEncoding 时我得到 NULL 输出)