2

I am encrypting an NSString in iOS like this which encodes and decodes fine:

NSString *stringtoEncrypt = @"This string is to be encrypted";
NSString *key = @"12345678901234567890123456789012";

// Encode
NSData *plain = [stringtoEncrypt dataUsingEncoding:NSUTF8StringEncoding];
NSData *cipher = [plain AES256EncryptWithKey:key];

NSString *cipherBase64 = [cipher base64EncodedString];
NSLog(@"ciphered base64: %@", cipherBase64);

// Decode
NSData *decipheredData = [cipherBase64 base64DecodedData];
NSString *decoded = [[NSString alloc] initWithData:[decipheredData AES256DecryptWithKey:key] encoding:NSUTF8StringEncoding];
NSLog(@"%@", decoded);

NSData extension:

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

Now I am wanting to pass the Base64 encoded string to Node.js and have it decode. I am using this method:

var crypto = require('crypto');

password = '12345678901234567890123456789012';
var cryptoStr = 'q6SIYHKospVNzk5ZsW8S5CURQ8qRPyDhv1TqALXhOVM=';
var iv = "0000000000000000";

var decipher = crypto.createDecipheriv('aes-256-cbc', password, iv);
var dec = decipher.update(cryptoStr,'base64','utf-8');
dec += decipher.final('utf-8'); 

console.log('Decrypted content: ' + dec);

However the results is:

Decrypted content: dXYCCDBY^WYCDo be encrypted

Any idea's what's going on?

1 Answer 1

3

In Objective-C you're not defining the IV which defaults to a zero filled IV. Node.js says that

key and iv must be 'binary' encoded strings or buffers.

The character 0 in your IV string is not the same as the byte \0. You're not passing a zero filled IV, but an IV filled with 0x30 bytes.

Fill the IV like this:

var iv = new Buffer(16);
iv.fill(0);
Sign up to request clarification or add additional context in comments.

1 Comment

I am also trying to get it to match in Javascript. If you could take a quick look stackoverflow.com/questions/31896441/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.