简体   繁体   中英

AES encryption on iOS with base64 key from CryptoJS

I'm generating and exporting a key with CryptoJS:

const password = crypto.lib.WordArray.random(128 / 8);
const salt = crypto.lib.WordArray.random(128 / 8);
const encryptionKey = crypto.PBKDF2(password, salt, {keySize: 128 / 32});
return encryptionKey.toString();

Now I'm trying to encrypt some data with the key on iOS:

const char *s = [encryptionKey cStringUsingEncoding:NSASCIIStringEncoding];
NSData *keyData= [NSData dataWithBytes:s length:strlen(s)];

NSMutableData *ivData = [NSMutableData dataWithLength:kCCBlockSizeAES128];
SecRandomCopyBytes(kSecRandomDefault, kCCBlockSizeAES128, ivData.mutableBytes);
NSData *iv = [NSData dataWithData:ivData];

size_t outLength;

NSMutableData *cipherData = [NSMutableData dataWithLength:dataString.length + kCCBlockSizeAES128];
CCCrypt(kCCEncrypt, // operation
    kCCAlgorithmAES128, // Algorithm
    kCCOptionPKCS7Padding, // options
    keyData.bytes, // key
    keyData.length, // keylength
    iv.bytes,// iv
    jsonData.bytes, // dataIn
    jsonData.length, // dataInLength,
    cipherData.mutableBytes, // dataOut
    cipherData.length, // dataOutAvailable
    &outLength); // dataOutMoved

    cipherData.length = outLength;

NSString *cipherText = [cipherData base64EncodedStringWithOptions:NSUTF8StringEncoding];
NSString *ivText = [iv base64EncodedStringWithOptions:NSUTF8StringEncoding];

return [ivText stringByAppendingString:cipherText]

This all works so far. Trying to decrypt the data with CryptoJS however fails:

const iv = crypto.enc.Base64.parse(message.substr(0, 24));
const encrypted = crypto.enc.Base64.parse(message.substring(24));

const decrypted = crypto.AES.decrypt(encrypted, encryptionKey, {
  iv: iv,
  padding: crypto.pad.Pkcs7,
  mode: crypto.mode.CBC
});
console.log(decrypted.toString(crypto.enc.Utf8))

The problem seems to be in the passing of the key from CryptoJS to iOS. What is the correct format to pass to CCCrypt?

The option to base64EncodedStringWithOptions is incorrect and will add line ending characters to the Base64 encoded iv and encrypted data.

You do not want line endings options, by default, no line endings are inserted. Just specify 0 :

NSString *cipherText = [cipherData base64EncodedStringWithOptions:0];
NSString *ivText = [iv base64EncodedStringWithOptions:0];

The option Note that NSUTF8StringEncoding is not an encoding option for the method base64EncodedStringWithOptions . The options are:

NSDataBase64Encoding64CharacterLineLength
NSDataBase64Encoding76CharacterLineLength
NSDataBase64EncodingEndLineWithCarriageReturn
NSDataBase64EncodingEndLineWithLineFeed`

which are all line separator options.

My original code contained three errors.

  1. The resulting strings need to be encoded using no parameter as suggested by zaph:

     NSString *cipherText = [cipherData base64EncodedStringWithOptions:0]; NSString *ivText = [iv base64EncodedStringWithOptions:0]; 
  2. To correctly convert the encryption key to NSData , I use the method provided here and call it like this:

     NSData *keyData= [self dataFromHexString:encryptionKey]; 
  3. The decrypt function of CryptoJS requires an object like this:

     const encrypted = crypto.enc.Base64.parse(message.substring(24)); const params = { ciphertext: encrypted, salt: '' }; const decrypted = crypto.AES.decrypt(params, crypto.enc.Hex.parse(this.encryptionKey.toString()), { iv: iv, padding: crypto.pad.Pkcs7, mode: crypto.mode.CBC }); return decrypted.toString(crypto.enc.Utf8); 

Thanks for your help!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM