0

I am developing an application which will send encrypted data to a server. The server uses 3des with CFB8 and no padding. I have read most of the related questions in stackoverflow but still unable to get it work. Been working on this for few days but still unable to get it to match with the server encryption. here is what i have tried-

 + (NSString*) doCipher:(NSString*)plainText operation:(CCOperation)encryptOrDecrypt {

        const void *vplainText;
        NSData* plainTextData;
        size_t plainTextBufferSize;

        if (encryptOrDecrypt == kCCDecrypt)
        {
           NSData *EncryptData =[NSData  dataWithBase64EncodedString:plainText];
        plainTextBufferSize = [EncryptData length];
        vplainText = [EncryptData bytes];
        }
        else
        {
             plainTextData = [plainText dataUsingEncoding:NSUTF8StringEncoding];
        plainTextBufferSize = [plainTextData length];
        }

        CCCryptorStatus ccStatus;
        uint8_t *bufferPtr = NULL;
        size_t bufferPtrSize = 0;
        size_t movedBytes = 0;
         uint8_t iv[kCCBlockSize3DES];

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

        const void *vkey = kPrivateKey;
        unsigned char IV[8]={0,0,0,0,0,0,0,0};

        ccStatus = CCCrypt(encryptOrDecrypt,
                       kCCAlgorithm3DES,
                       0,
                       [keyData bytes],
                       [key length],
                       IV,
                       [plainTextData bytes],
                       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];
        }
        else
        {
            NSData *myData = [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes];
            result = [myData base64EncodedString];
        }

        return result;
    }

It seems CCOptions currently supports kCCOptionPKCS7Padding and kCCOptionECBMode.How to achieve 3des with CFB8 and no padding.Any suggestion would be appreciated.

Bharat
  • 2,987
  • 2
  • 32
  • 48
  • as Rob's suggestions i've changed in my code but still no luck..please check updated question. – Bharat Jan 28 '14 at 08:38

1 Answers1

2

EDIT: Sorry; I overlooked a key point previously. You're never asking for CFB8 mode. The default is CBC mode.

You can't use CCCrypt() for this. You have to use CCCryptorCreateWithMode() so you can pass the mode. Then call CCCryptorUpdate() with the data and CCCryptorFinal() to finish.


If you don't want padding, why are you requesting padding? Remove kCCOptionPKCS7Padding. If you don't want any options (which you appear not to), just pass 0.

CFB-8 takes an initialization vector. You've set it to all 0's. Is this what the server is using? (This is a very poor IV; the IV for CFB should be random, not fixed.)

These lines are dangerous:

    plainTextBufferSize = [plainText length];
    vplainText = (const void *) [plainText UTF8String];

This will truncate any multi-byte strings. The better solution to this is to create an NSData:

plainTextData = [self.plainText dataUsingEncoding:NSUTF8StringEncoding];

You can then use bytes and length on plainTextData.

Rob Napier
  • 286,113
  • 34
  • 456
  • 610
  • Thanks rob for your advices, but it still not solve my problem, server use 0's as IV. should i use random IV? – Bharat Jan 28 '14 at 05:55
  • There is no standard way to encode 3DES data. How is the server encoding it? Your IV needs to match the server's IV. (Everything you do has to match the server.) If you have a specification from the server (exactly what they send and how they calculate it, not just "we encrypt it") then that's great. Otherwise, the server code is what you want. There are dozens of ways to implement this (most of them are wrong, but your server uses a NULL IV, so we already know it's at least partially wrong). – Rob Napier Jan 29 '14 at 00:30
  • I have also checked your library RNCryptor, but i need 3DES with CFB mode.. unfortunately i'm unable to do so. server uses 3DES with CFB mode and no padding(0's as IV) and it works on android. – Bharat Jan 29 '14 at 13:52
  • can I have the sample code for CCCryptorCreateWithMode() for CFB mode with 3DES encryption for iOS – Blios Jan 30 '14 at 14:03
  • Sorry Rob i didn't find method CCCryptorCreateWithMode(), can you please provide sample code. – Bharat Jan 30 '14 at 14:23
  • See performOperation:... in https://github.com/RNCryptor/RNCryptor/blob/df3fbeda0e604107eca72674a3bf7fbb9ff761c5/RNCryptor/RNCryptor.m. – Rob Napier Jan 30 '14 at 15:00