iPhone SDK CCCrypt 3DES和ECB模式始终返回PARAM ERROR

时间:2010-01-25 15:43:56

标签: iphone encryption sdk

我在网络各个地方的iPhone上看到了很多关于CCCrypt和3DES的帖子,但似乎没有一个使用ECB模式的例子,总是使用PKCS7Padding。

是否有人使用CCCrypt函数使用3DES和ECB模式加密和解密传递的字符串?

目前我的代码(我承认来自某个网​​站,我认为这是Apple自己的开发者论坛)如下:

+ (NSString*)doCipher:(NSString*)plainText action:(CCOperation)encryptOrDecrypt { 
 const void *vplainText;
 size_t plainTextBufferSize;

 if (encryptOrDecrypt == kCCDecrypt) {
  NSData *EncryptData = [[NSData alloc] initWithBase64EncodedString:plainText];
  plainTextBufferSize = [EncryptData length];
  vplainText = [EncryptData bytes];
 }
 else {
  //plainTextBufferSize = [plainText length];
  //vplainText = (const void *)[plainText UTF8String];

  NSData *plainTextData = [plainText dataUsingEncoding: NSUTF8StringEncoding]; 
  plainTextBufferSize = [plainTextData length]; 
  vplainText = [plainTextData bytes];
 }

 CCCryptorStatus ccStatus;
 uint8_t *bufferPtr = NULL;
 size_t bufferPtrSize = 0;
 size_t movedBytes = 0;
 // uint8_t ivkCCBlockSize3DES;

 bufferPtrSize = (plainTextBufferSize + kCCBlockSize3DES) & ~(kCCBlockSize3DES - 1);
 bufferPtr = malloc( bufferPtrSize * sizeof(uint8_t));
 memset((void *)bufferPtr, 0x0, bufferPtrSize);
 // memset((void *) iv, 0x0, (size_t) sizeof(iv));

 NSString *key = @"123456789012345678901234";
 NSString *initVec = @"init Vec";
 const void *vkey = (const void *)[key UTF8String];
 const void *vinitVec = (const void *)[initVec UTF8String];

 ccStatus = CCCrypt(encryptOrDecrypt,
        kCCAlgorithm3DES,
        kCCOptionECBMode,
        vkey, //"123456789012345678901234", //key
        kCCKeySize3DES,
        nil, //"init Vec", //iv,
        vplainText, //"Your Name", //plainText,
        plainTextBufferSize,
        (void *)bufferPtr,
        bufferPtrSize,
        &movedBytes);

 //if (ccStatus == kCCSuccess) NSLog(@"SUCCESS");
 /*else*/ if (ccStatus == kCCParamError) return @"PARAM ERROR";
 else if (ccStatus == kCCBufferTooSmall) return @"BUFFER TOO SMALL";
 else if (ccStatus == kCCMemoryFailure) return @"MEMORY FAILURE";
 else if (ccStatus == kCCAlignmentError) return @"ALIGNMENT";
 else if (ccStatus == kCCDecodeError) return @"DECODE ERROR";
 else if (ccStatus == kCCUnimplemented) return @"UNIMPLEMENTED";

 NSString *result;

 if (encryptOrDecrypt == kCCDecrypt) {
  result = [[[NSString alloc] initWithData:[NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes] encoding:NSASCIIStringEncoding] autorelease];
 }
 else {
  NSData *myData = [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes];
  result = [myData base64EncodingWithLineLength:movedBytes];
 }

 return result; }

上述ALWAYS失败并出现PARAM ERROR。

2 个答案:

答案 0 :(得分:2)

- (NSData *) encrypt:(NSString *) dataToEncrypt{    
    NSUInteger data_length= [dataToEncrypt length];
    uint8_t input_raw_data[data_length]; 

    //The [dataToEncrypt length] gives the number of chars present in the string.So say there are 10 chars.
    //Now,the getBytes needs to get the raw bytes from this i.e. binary NSData.But suppose the encoding was 
    //full 16 bit encoding then the number of bytes needed wd have been double- 20.But as we are using the
    //NSUTF8StringEncoding,the number of byes needed is 1 per char as the chars(even if originally unicode are
    //compressed into an 8 bit UTF8 encoding.)
    [dataToEncrypt getBytes:&input_raw_data maxLength:data_length usedLength:NULL encoding:NSUTF8StringEncoding options:0 range:NSMakeRange(0,data_length) remainingRange:NULL];

    //According to the doc: For block ciphers, the output size will always be less than or
    //equal to the input size plus the size of one block.
    //That's why we need to add the size of one block here
    size_t buffer_size           = data_length + kCCBlockSizeAES128;
    void* buffer                 = malloc(buffer_size);
    size_t num_bytes_encrypted   = 0;


    CCCryptorStatus crypt_status = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
                                           [self.symmetricKey bytes], kCCKeySizeAES256,
                                           NULL,
                                           input_raw_data, data_length,
                                           buffer, buffer_size,
                                           &num_bytes_encrypted);

    NSLog(@"~~num bytes encrypted: %d",num_bytes_encrypted);
    if (crypt_status == kCCSuccess){
        NSLog(@"~~Data encoded successfully...");
        return [NSData dataWithBytesNoCopy:buffer length:num_bytes_encrypted];
    }

    free(buffer); //free the buffer;
    return nil;

}


- (NSData *) decrypt:(NSData *) dataToDecrypt{
    NSUInteger data_length= [dataToDecrypt length];

    //See the doc: For block ciphers, the output size will always be less than or
    //equal to the input size plus the size of one block.
    //That's why we need to add the size of one block here
    size_t buffer_size           = data_length + kCCBlockSizeAES128;
    void* buffer                 = malloc(buffer_size);
    size_t num_bytes_decrypted   = 0;


    CCCryptorStatus crypt_status = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
                                           [self.symmetricKey bytes], kCCKeySizeAES256,
                                           NULL /* initialization vector (optional) */,
                                           [dataToDecrypt bytes], data_length, /* input */
                                           buffer, buffer_size, /* output */
                                           &num_bytes_decrypted);

    NSLog(@"~~num bytes decrypted: %d",num_bytes_decrypted);
    if (crypt_status == kCCSuccess){
        NSLog(@"~~Data decoded successfully...");
        return [NSData dataWithBytesNoCopy:buffer length:num_bytes_decrypted];
    }

    free(buffer); //free the buffer;
    return nil;

}

答案 1 :(得分:1)

上面的代码对我有用,但有一些变化。这些变化是我将moveBytes和bufferPtf作为实例变量进行了decelare并跟随chandge。

if (encryptOrDecrypt == kCCDecrypt) {
  plainTextBufferSize = movedBytes;
  vplainText = bufferPtr;
}
else {
  plainTextBufferSize = [plainText length];
  vplainText = (const void *)[plainText UTF8String];
}

而是base64encoding使用nsasciiencoding。