使用 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 中,您假设它是十六进制编码的。因为它只包含数字和字母 a 到 f,所以它很可能是十六进制编码而不是 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 来完成。
在两个应用程序之间的通信中,我想加密 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 中,您假设它是十六进制编码的。因为它只包含数字和字母 a 到 f,所以它很可能是十六进制编码而不是 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 来完成。