使用 CryptoJS 加密并从 Objective-C 解密

Encrypt with CryptoJS and decrypt from Objective-C

在两个应用程序之间的通信中,我想加密 JavaScript 中的一条信息,并使用固定密钥(仅用于基本安全)解密来自 Objective-C 客户端的消息。

加密效果很好:

var command = "mjallo";
var crypto_key = CryptoJS.enc.Base64.parse('280f8bb8c43d532f389ef0e2a5321220');
var crypto_iv  = CryptoJS.enc.Base64.parse("CC0A69779E15780A");
// Encrypt and encode
var encrypted = CryptoJS.AES.encrypt(command, crypto_key, {iv: crypto_iv}).toString();
var encrypted_and_encoded = btoa(encrypted);
// encrypted_and_encoded => 'dFBQVDZZS3dGSktoa0J3Y1NQOElpZz09'

// Confirms that decrypt works with CryptoJS:
// Decode and decrypt
var decrypted = CryptoJS.AES.decrypt(atob(encrypted_and_encoded), crypto_key, {iv: crypto_iv});
// decrypted => 'mjallo'

Objective-c中的消息被CryptoJS加密后,你会如何解码和解密?

我尝试使用 CocoaSecurity 解密,但没有成功。以下是 RubyMotion 语法:

  begin
    res = CocoaSecurity.aesDecryptWithBase64('dFBQVDZZS3dGSktoa0J3Y1NQOElpZz09', hexKey: '280f8bb8c43d532f389ef0e2a5321220', hexIv: 'CC0A69779E15780A')
  rescue NSException => e
    p e.reason # => "Length of iv is wrong. Length of iv should be 16(128bits)"
  end

AES 支持 128 位的块大小和 128、192 和 256 位的密钥大小。 CBC 模式(默认)的 IV 应为 128 位。

您的编码密钥由 32 个字符组成。在 CryptoJS 中,您将其解析为 Base64,这会产生 192 位密钥,但在 CocoaSecurity 中,您假设它是十六进制编码的。因为它只包含数字和字母 af,所以它很可能是十六进制编码而不是 Base64 编码。如果假设它是十六进制编码的,那么将获得 128 位的有效 AES 密钥大小:

var crypto_key = CryptoJS.enc.Hex.parse('280f8bb8c43d532f389ef0e2a5321220');

另一方面,在相同的假设下,您的 IV 没有有效的大小。对于 CBC 模式下的 AES,IV 的长度应为 16 个字节。此外,IV 永远不应固定为静态值。您需要为每次加密生成一个随机 IV。由于 IV 不必保密,您可以将其与密文一起发送。

var crypto_iv  = CryptoJS.lib.WordArray.random(128/8);
console.log("IV: " + crypto_iv.toString()); // hex encoded

CryptoJS.<Cipher>.encrypt() 的结果是一个特殊的可格式化对象。如果您对该对象调用 toString(),您将获得 Base64 编码的密文(当使用基于密码的加密时,可以选择加盐)。但是随后您通过调用 btoa() 再次使用 Base64 对其进行编码。您不需要对其进行两次编码。

var encrypted = CryptoJS.AES.encrypt(command, crypto_key, {iv: crypto_iv}).toString();
console.log("Ciphertext (Base64): " + encrypted.toString());
console.log("Ciphertext (Hex): " + encrypted.ciphertext.toString());

据我判断,您的 RubyMotion 代码看起来不错。


如果您只能更改 CocoaSecurity 代码,那么您将需要

  • 通过将密钥解码为 Base64 并将其编码为 Hex 来重新编码密钥,
  • 将 16 个“0”字符附加到 IV 十六进制字符串,因为 CryptoJS 将 IV 填充到下一个有效 IV 为 0x00 字节,
  • 从Base64解码一次密文。

您应该始终验证密文。这可以通过像 GCM 这样的身份验证模式或通过密文的 HMAC 来完成。