How to encrypt an NSString in Objective C with DES in ECB-Mode?

14,320

DES encryption in ECB mode uses an 8 byte block size, and encodes each blocks individually. The problem is that your input string doesn't divide into 8 bytes equally and the cryptor doesn't know what to do with the final non 8 byte block.

The fix is to allow the cryptor to pad the final block by adding kCCOptionPKCS7Padding to the options to CCCrypt. eg (snippet from an NSData encryption category):

CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, 
                                      kCCAlgorithmDES, 
                                      kCCOptionPKCS7Padding | kCCOptionECBMode,
                                      keyPtr, 
                                      kCCKeySizeDES,
                                      NULL, 
                                      [self bytes], 
                                      dataLength,
                                      buffer, 
                                      bufferSize
                                      &numBytesEncrypted);

Take a look at this post for more details regarding padding algorithms. Hope this helps.

Share:
14,320
Thomas Kekeisen
Author by

Thomas Kekeisen

Self employed app and web developer.

Updated on June 15, 2022

Comments

  • Thomas Kekeisen
    Thomas Kekeisen almost 2 years

    I am trying to encrypt an NSString in Objective C on the iPhone. At least I wan't to get a string like "TmsbDaNG64lI8wC6NLhXOGvfu2IjLGuEwc0CzoSHnrs=" when I encode "us=foo;pw=bar;pwAlg=false;" by using this key: "testtest".

    My problem for now is, that CCCrypt always returns "4300 - Parameter error" and I have no more idea why.

    This is my code (the result of 5 hours google and try'n'error):

    NSString *token = @"us=foo;pw=bar;pwAlg=false;";
    NSString *key = @"testtest";
    
    const void *vplainText;
    size_t plainTextBufferSize;
    
    plainTextBufferSize = [token length];
    vplainText = (const void *) [token UTF8String];
    
    CCCryptorStatus ccStatus;
    uint8_t *bufferPtr = NULL;
    size_t bufferPtrSize = 0;
    size_t *movedBytes;
    
    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 *initVec = @"init Vec";
    const void *vkey = (const void *) [key UTF8String];
    const void *vinitVec = (const void *) [initVec UTF8String];
    
    ccStatus = CCCrypt(kCCEncrypt,
                       kCCAlgorithmDES,
                       kCCOptionECBMode,
                       vkey, //"123456789012345678901234", //key
                       kCCKeySizeDES,
                       NULL,// vinitVec, //"init Vec", //iv,
                       vplainText, //"Your Name", //plainText,
                       plainTextBufferSize,
                       (void *)bufferPtr,
                       bufferPtrSize,
                       movedBytes);
    
    NSString *result;
    NSData *myData = [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes];
    result = [myData base64Encoding];
    
  • Thomas Kekeisen
    Thomas Kekeisen about 14 years
    Allright, this worked for me, thank you! Now I have the following result: "Tm==Da==64==8w==NL==OG==u2==LG==wc==zo==nrs=" but I want: "TmsbDaNG64lI8wC6NLhXOGvfu2IjLGuEwc0CzoSHnrs=" without all the equal signs. Do you have an idea how to fix this?
  • Thomas Kekeisen
    Thomas Kekeisen about 14 years
    Solved it. I am now using a base64-encoding-method from here which produces no "==" all the time: cocoadev.com/index.pl?BaseSixtyFour
  • Adhamox
    Adhamox over 12 years
    Thank you @crafterm. Saved my life!
  • Motti Shneor
    Motti Shneor about 6 years
    Thank you very much, the first real answer to my issues... however, could you PLEASE also explain how to use the other block-by-block APIs? not the one-shot CCCrypt ? I need to convert an old ntlm authentication code that uses openSSL DES_ecb_encrypt after DES_set_key etc.