Update : found the solution. I will update this question soon with the actual working code and command.
A client is encrypting a file server-side with C++, and I need to decrypt it in an iPhone application.
My client can crypt and decrypt on his side, and so do I on the iPhone, but we can't decrypt the file encrypted by each other. I saw many related questions on SO, but none could help me find an implementation that works the same way on both side.
I want to output some sample values that we will accept as the common implementation.
I tried to crypt a file with openssl and decrypt it with cocoa, but couldn't.
Here is what I use for encryption:
echo "123456789ABCDEFG" | openssl enc -aes-128-ecb -nosalt -K "41414141414141414141414141414141" -iv 0 > hello.txt.bin
Adding the option -p to openssl call shows that the expected key and iv are used:
key=41414141414141414141414141414141
iv =00000000000000000000000000000000
And for cocoa decryption (in an NSData category):
- (NSData *)AESDecryptWithKey:(NSString *)key {
char keyPtr[kCCKeySizeAES128+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;
char iv[32];
for (int i = 0; i < 32; i++) {
iv[i] = 0;
}
CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionECBMode + kCCOptionPKCS7Padding,
keyPtr, kCCKeySizeAES128,
iv, //"00000000000000000000000000000000" /* 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;
}
called this way:
- (void)testBinaryFileDecryption {
NSString *databasePath = [[NSBundle mainBundle] pathForResource:@"hello" ofType:@"txt.bin"];
NSData *data = [NSData dataWithContentsOfFile:databasePath];
NSAssert(nil != data, @"Encrypted data, freshly loaded from file should not be nil");
NSData *plain = [data AESDecryptWithKey:@"AAAAAAAAAAAAAAAA"];
NSAssert(nil != plain, @"Decrypted plain data should not be nil");
NSLog(@"Result: '%@'", [[NSString alloc] initWithData:plain encoding:NSASCIIStringEncoding]);
}
Result logs:
Result: '4¨µ¢Ä½Pk£N
What option am I forgetting? Is the encoding of the NSData returned something else than NSASCIIStringEncoding ?