I've been working on this for a long time, but am stuck.
I'm writing an iOS app that takes AES encrypted data form a Go server-side application and decrypts it. I'm using CCCryptor for the decryption on the iOS side. However, I cannot, for the life of me, get plaintext out. There is a working Java/Android implementation, and it decrypts fine on the Go side, so I'm pretty sure it's to do with my CCCryptor settings.
I'm actually getting a 0 success status on decryption, but taking the output and doing a NSString initWithBytes gives me a null string.
Note: I'm only writing the iOS side.
Go code that encrypts:
func encrypt(key, text []byte) []byte {
block, err := aes.NewCipher(key)
if err != nil {
panic(err)
}
b := encodeBase64(text)
ciphertext := make([]byte, aes.BlockSize+len(b))
iv := ciphertext[:aes.BlockSize]
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
panic(err)
}
cfb := cipher.NewCFBEncrypter(block, iv)
cfb.XORKeyStream(ciphertext[aes.BlockSize:], []byte(b))
return ciphertext
}
Objective-C code that decrypts
+ (NSData *)decrypt:(NSData*)data withPassword:(NSString*)password{
NSData * key = [password dataUsingEncoding:NSUTF8StringEncoding];
size_t dataLength = [data length] - kCCBlockSizeAES128;
NSData *iv = [data subdataWithRange:NSMakeRange(0, kCCBlockSizeAES128)];
NSData *encrypted = [data subdataWithRange:NSMakeRange(kCCBlockSizeAES128, dataLength)];
//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(dataLength);
NSMutableData *ret = [NSMutableData dataWithLength:dataLength + kCCBlockSizeAES128];
size_t numBytesDecrypted = 0;
CCCryptorStatus status = CCCrypt(kCCDecrypt, kCCAlgorithmAES,
0x0000, // change to 0 solve the problem
[key bytes],
kCCKeySizeAES256,
[iv bytes],
[encrypted bytes], dataLength, /* input */
[ret mutableBytes], [ret length], /* output */
&numBytesDecrypted
);
NSLog(@"err: %d", status);
NSLog(@"dataLength: %d, num: %d", (int)dataLength, (int)numBytesDecrypted);
if (status == kCCSuccess) {
//the returned NSData takes ownership of the buffer and will free it on deallocation
return ret;
}
// free(buffer); //free the buffer;
return nil;
}