【问题标题】:Encrypt with CryptoJS and decrypt from Objective-C使用 CryptoJS 加密并从 Objective-C 解密
【发布时间】:2016-01-21 16:01:06
【问题描述】:

在两个应用程序之间的通信中,我想在 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'

在被 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

【问题讨论】:

    标签: javascript objective-c encryption cryptography cryptojs


    【解决方案1】:

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

    您的编码密钥由 32 个字符组成。在 CryptoJS 中,您将其解析为 Base64,这会产生 192 位密钥,但在 CocoaSecurity 中,您假设它是十六进制编码的。由于它只包含数字和字母 af,因此它很可能是 Hex 编码的而不是 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 并将其编码为十六进制来重新编码密钥,
    • 将 16 个“0”字符附加到 IV 十六进制字符串,因为 CryptoJS 将 IV 填充到具有 0x00 字节的下一个有效 IV,
    • 从 Base64 解码一次密文。

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

    【讨论】:

    • 非常感谢@Arthom B. 非常周到的回答。我摆脱了双重编码,切换到十六进制键,通过了 IV,一切都很好。谢谢!
    • 能否分享使用 CryptoJS 进行加密和解密的目标 C 代码
    • @Chandni 不,我不能。你应该问 Jonas,或者更好的是,使用具有不同语言实现的 RNCryptor。
    • @JonasNielsen - 您能否分享使用 CryptoJS 进行加密和解密的目标 C 代码。谢谢
    猜你喜欢
    • 2016-10-05
    • 1970-01-01
    • 2023-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多