使用CryptoJS的base64密钥在iOS上进行AES加密

时间:2022-03-13 18:31:48

I'm generating and exporting a key with CryptoJS:

我正在使用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:

现在我正在尝试使用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:

到目前为止这一切都有效。尝试使用CryptoJS解密数据但是失败了:

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?

问题似乎在于将密钥从CryptoJS传递到iOS。传递给CCCrypt的正确格式是什么?

2 个解决方案

#1


1  

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

base64EncodedStringWithOptions的选项不正确,并将为Base64编码的iv和加密数据添加行结束字符。

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

您不需要行结尾选项,默认情况下,不会插入行结尾。只需指定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:

选项请注意,NSUTF8StringEncoding不是方法base64EncodedStringWithOptions的编码选项。选项是:

NSDataBase64Encoding64CharacterLineLength
NSDataBase64Encoding76CharacterLineLength
NSDataBase64EncodingEndLineWithCarriageReturn
NSDataBase64EncodingEndLineWithLineFeed`

which are all line separator options.

这些都是行分隔符选项。

#2


0  

My original code contained three errors.

我的原始代码包含三个错误。

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

    生成的字符串需要使用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,我使用此处提供的方法并将其调用如下:

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

    CryptoJS的解密函数需要这样的对象:

    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!

谢谢你的帮助!

#1


1  

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

base64EncodedStringWithOptions的选项不正确,并将为Base64编码的iv和加密数据添加行结束字符。

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

您不需要行结尾选项,默认情况下,不会插入行结尾。只需指定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:

选项请注意,NSUTF8StringEncoding不是方法base64EncodedStringWithOptions的编码选项。选项是:

NSDataBase64Encoding64CharacterLineLength
NSDataBase64Encoding76CharacterLineLength
NSDataBase64EncodingEndLineWithCarriageReturn
NSDataBase64EncodingEndLineWithLineFeed`

which are all line separator options.

这些都是行分隔符选项。

#2


0  

My original code contained three errors.

我的原始代码包含三个错误。

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

    生成的字符串需要使用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,我使用此处提供的方法并将其调用如下:

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

    CryptoJS的解密函数需要这样的对象:

    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!

谢谢你的帮助!