在两个应用程序之间的通信中,我想在 JavaScript 中加密一条信息,并使用固定 key 从 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'
当消息被 CryptoJS 加密后,你会如何在 Objective-c 中解码和解密消息?
我尝试使用 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 位的 block 大小和 128、192 和 256 位的 key 大小。 CBC 模式(默认)的 IV 应为 128 位。
您的编码 key 由 32 个字符组成。在 CryptoJS 中,您将其解析为 Base64,这会产生 192 位 key ,但在 CocoaSecurity 中,您假设它是十六进制编码的。由于它仅包含数字和字母 a 到 f,因此它可能是 Hex 编码而不是 Base64 编码。如果假设它是十六进制编码的,那么将获得 128 位的有效 AES key 大小:
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 代码,那么您将需要
- 通过将 key 解码为 Base64 并将其编码为十六进制来重新编码 key ,
- 将 16 个“0”字符附加到 IV 十六进制字符串,因为 CryptoJS 使用 0x00 字节填充 IV 直到下一个有效 IV,
- 从 Base64 解码一次密文。
您应该始终验证密文。这可以通过 GCM 等身份验证模式或通过密文使用 HMAC 来完成。
关于javascript - 使用 CryptoJS 加密并使用 Objective-C 解密,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33279933/