0

我正在用 C# 开发一个集成,它将 Office365 分发列表同步到用 PHP 编写的 Sendy (sendy.co)。

在 PHP 应用程序中,一些 ID 被加密,我想在 C# 中实现相同的功能,这样我就可以使用他们的 API 进行通信,而无需查找“秘密”ID。

这是他们的应用程序中计算这些 ID 的 PHP 代码(我替换了密码):

$encrypted = openssl_encrypt($in, 'AES-256-CBC', 'API_KEY', 0, 'SECRET_PASSWORD');
$encrypted = str_replace('/', '892', $encrypted);
$encrypted = str_replace('+', '763', $encrypted);
$encrypted = str_replace('=', '', $encrypted);

我通过在某处托管 PHP 脚本并从我的 C# 应用程序中调用它来克服这个“问题”,但我想让它成为开源的,所以我希望将它集成到应用程序中。

我想我必须从 .NET 开始AesCryptoServiceProvider,但我似乎无法做到正确(我得到关于密钥长度和内容的例外情况)。

到目前为止,我试过这个:

    public static string Execute()
    {
        // openssl_encrypt ( string $data , string $method , string $password [, int $options = 0 [, string $iv = "" ]] )
        var aes = new AesCryptoServiceProvider();
        aes.KeySize = 256;

        // Fixed password in code
        aes.Key = Encoding.UTF8.GetBytes("FIXED PASSWORD");
        // API = IV
        aes.IV = Encoding.UTF8.GetBytes("SENDY API KEY");

        aes.Mode = CipherMode.CBC;

        // Trying to encrypt "36" in this case
        byte[] src = Encoding.Unicode.GetBytes("36");

        // Actual encryption
        using (var encrypt = aes.CreateEncryptor())
        {
            byte[] dest = encrypt.TransformFinalBlock(src, 0, src.Length);

            // Convert byte array to Base64 strings
            return Convert.ToBase64String(dest);
        }
    }

然而,这会引发一个异常,指出 IV 与算法的块大小不匹配。

我想 PHP 中的 openssl_encrypt 方法从示例中给定的 API KEY 派生出实际的 IV(因此 $password 参数),但我找不到太多关于它的文档以便能够在 C# 中实现相同的目标。

4

1 回答 1

0

iv 的大小必须等于块大小,对于 AES 是 16 字节,"SENDY API KEY"只有 13 字节。

iv 应该是每个加密的不同随机值,只需将其添加到加密数据之前,以便在解密期间使用。

接下来,您指定了 256 位的密钥大小,但密钥"FIXED PASSWORD"只有 14 字节,使它们相同,128、192 或 256 位(16、24 或 32 字节)。无需使用超过 128 位的密钥。

密码不应直接用于密钥,密钥应从具有 PBKFD2 等功能的密码中派生。

AES是一种分组密码,它是。输入的长度必须是块大小的倍数。为了完成输入的这种填充是必需的。通常使用 PKCS#7(née PKCS#5)填充,它可能是 OpenSSL 的默认值。加密/解密应自动添加/删除此填充。但这确实意味着加密的数据长度将比输入长 1 字节到 16 字节。例如,如果您加密"36"输出长度将为 16 字节。

将所有这些正确组合在一起可能很难正确,请考虑使用整体解决方案,例如RNCryptor-phpdefuse

于 2016-07-13T18:34:36.467 回答