开发者

iPhone SDK CCCrypt 3DES and ECB mode always returns PARAM ERROR

I've seen quite a lot of posts about CCCrypt and 3DES on the iPhone at various places around the Net, but there does not seem to be a working example of using it with ECB mode, always with PKCS7Padding.

Does anyone have any working code to encrypt and decrypt a passed string using 3DES and ECB mode using the CCCrypt function?

开发者_JAVA技巧

Currently my code (which I admit came from a site somewhere, I think it was Apple's own developer forums) is as follows:

+ (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; }

The above ALWAYS fails with PARAM ERROR.


- (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;

}


The above code worked for me, with some changes. The changes are i decelare the moveBytes and bufferPtf as instance variable and did following chandge.

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

instead base64encoding use nsasciiencoding.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜