Search code examples
iosobjective-cencryptionrncryptor

Encrypt 8 byte string / base64 encode / max length 20 bytes


What is the best method/approach to encrypt and base64 encode a UTF String that has a max size of 20 bytes in objective-c? I'm leaning towards Blowfish because of the 8 byte block size.

Please provide some sample code? Thanks.


Solution

  • Yes.

    DES, 3DES and Blowfish have block sizes of 8-bytes so the encrypted output will be 8 bytes, Base64 encoding 8-bytes will result in 12 bytes.

    AES has a block size of 16 so 8-bytes + padding will be 16-bytes of data. Base64 encoding 16-bytes will result in 24-bytes so AES will not work.

    There are other issues such as CBC mode and an iv, a good scheme would use a random iv and transport it with the encrypted message. One could use the remaining bits in the Base64 to transmit a partial iv. But this is getting past the question.

    AES is the current preferred symmetric encryption algorithm. DES is not longer recommended for new work and has some known weak keys. Blowfish is also not recommended but a lot of people like it and it may be better than DES.

    Here is an example using 8-byte data with a 64-bit key and no iv. 3DES can be used by substitution of the Blowfish constants for 3DES and a 24-byte key. This is not a recommended solution, a good solution needs to consider usage, desired security, data value and potential attackers among other things such as iv and key.

    + (NSData *)doCipher:(NSData *)dataIn
                      iv:(NSData *)iv
                     key:(NSData *)symmetricKey
                 context:(CCOperation)encryptOrDecrypt
                   error:(NSError **)error
    {
        CCCryptorStatus ccStatus   = kCCSuccess;
        size_t          cryptBytes = 0;    // Number of bytes moved to buffer.
        NSMutableData  *dataOut    = [NSMutableData dataWithLength:dataIn.length];
    
        ccStatus = CCCrypt( encryptOrDecrypt,
                           kCCAlgorithmBlowfish,
                           0,
                           symmetricKey.bytes,
                           kCCKeySizeMinBlowfish,
                           nil,
                           dataIn.bytes, dataIn.length,
                           dataOut.mutableBytes, dataOut.length,
                           &cryptBytes);
    
        if (ccStatus == kCCSuccess) {
            dataOut.length = cryptBytes;
        }
        else {
            if (error) {
                *error = [NSError errorWithDomain:@"kEncryptionError"
                                             code:ccStatus
                                         userInfo:nil];
            }
            dataOut = nil;
        }
    
        return dataOut;
    }
    

    Test: I dropped the above method into a class names Test.

    uint8_t keyBytes[] = {0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18};
    NSData *key = [NSData dataWithBytes:keyBytes length:8];
    uint8_t dateBytes[] = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08};
    NSData *data = [NSData dataWithBytes:dateBytes length:8];
    NSLog(@"data:   %@", data);
    
    NSError *error;
    NSData *encryptData = [Test doCipher:data iv:nil key:key context:kCCEncrypt error:&error];
    NSString *encryptString = [encryptData base64EncodedStringWithOptions:0];
    NSLog(@"encryptData:   %@", encryptData);
    NSLog(@"encryptString: %@", encryptString);
    
    NSData *decryptData = [Test doCipher:encryptData iv:nil key:key context:kCCDecrypt error:&error];
    NSLog(@"decryptData:   %@", decryptData);
    

    Output:

    data:          01020304 05060708
    encryptData:   9e8ec0a8 71ab9d10
    encryptString: no7AqHGrnRA=
    decryptData    01020304 05060708