Search code examples
iosobjective-cnsstringnsdata

initWithData returns (null)


Well, I have a code that selects a text, and converts it to NSData then encrypts it with AES-256 and then converts this NSData to a NSString to be displayed the message encrypted, I'm doing this as follows:

 NSString *text = @"This is a simple text";

    NSData* data = [text dataUsingEncoding:NSUTF8StringEncoding];

    NSData *dataEnc = [data AES256EncryptWithKey:@"12556"];

    NSString *stringCrypt = [[NSString alloc] initWithData:dataEnc encoding:NSUTF8StringEncoding];

    NSData *dataDesc = [dataEnc AES256DecryptWithKey:@"12556"];

    NSString *string = [[NSString alloc] initWithData:dataDesc encoding:NSUTF8StringEncoding];

    NSLog(@"Text normal -> %@",text);

    NSLog(@"Text with AES -> %@",stringCrypt);

    NSLog(@"Text with AES decrypted -> %@",string);

The output of my NSLog is:

Text normal -> this is a simple text 
Text with AES -> (null) 
Text With AES decrypted -> this is a simple text

So the problem is with the code:

NSString *stringCrypt = [[NSString alloc] initWithData:dataEnc encoding:NSUTF8StringEncoding];

That return a null string, and in this case I need that string that will be inserted into a text file, how to solve this problem? why this returning a null value?

EDIT

The function to convert it to AES256 is:

- (NSData *)AES256EncryptWithKey:(NSString *)key {
    // 'key' should be 32 bytes for AES256, will be null-padded otherwise
    char keyPtr[kCCKeySizeAES256+1]; // room for terminator (unused)
    bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding)

    // fetch key data
    [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];

    NSUInteger dataLength = [self 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 bufferSize = dataLength + kCCBlockSizeAES128;
    void *buffer = malloc(bufferSize);

    size_t numBytesEncrypted = 0;
    CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
                                          keyPtr, kCCKeySizeAES256,
                                          NULL /* initialization vector (optional) */,
                                          [self bytes], dataLength, /* input */
                                          buffer, bufferSize, /* output */
                                          &numBytesEncrypted);
    if (cryptStatus == kCCSuccess) {
        //the returned NSData takes ownership of the buffer and will free it on deallocation
        return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
    }

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

Solved

As the user Zaph says, I need to use the -base64EncodedDataWithOptions, in my case I do as follows:

NSString *text = @"This is a simple text";

    NSData* data = [text dataUsingEncoding:NSUTF8StringEncoding];

    NSData *dataEnc = [data AES256EncryptWithKey:@"12556"];

    NSData *daes = [dataEnc base64EncodedDataWithOptions:NSDataBase64Encoding64CharacterLineLength];

    NSString *stringCrypt = [[NSString alloc] initWithData:daes encoding:NSUTF8StringEncoding];

    NSData *decodedData = [[NSData alloc] initWithBase64EncodedString:stringCrypt options:0];

    NSData *dataDesc = [decodedData AES256DecryptWithKey:@"12556"];

    NSString *string = [[NSString alloc] initWithData:dataDesc encoding:NSUTF8StringEncoding];

    NSLog(@"Text Normal -> %@",text);

    NSLog(@"Text with AES (BASE64) -> %@",stringCrypt);

    NSLog(@"Text with AES decrypted -> %@",string);

In this case I only need to convert it to a base64 string, and now I can store this values inside a text value, and other device can get this text and decrypt. Thanks for all.


Solution

  • Random bytes, and that is what encrypted looks like and can not be distinguished from, rarely is convertible to a string. This is why encrypted data is often Base64 encoded to produce printable characters.

    Use - base64EncodedStringWithOptions: to encode the encrypted data to a character string.