无法在C#bouncycastle和PHP openssl之间交换AES-256-CBC / PKCS7

时间:2016-12-06 21:33:53

标签: c# php bouncycastle php-openssl

所以我在C#和PHP中有以下代码,到目前为止,双方的结果并不一致。对于C#,我使用的是bouncy castle API,对于PHP,我使用的是openSSL。可以肯定的是,我还使用Microsoft Crypto Library在C#中加密了同样的东西,我得到了相同的密文,但是当它们与PHP交换时却没有。

C#

    public const string AES_ALGORITHM = "AES/CBC/PKCS7";
    public const string CRYPTO_ALGORITHM = "AES";
    public AESController(string key) {
        encryptionKey = Convert.FromBase64String(key);
    }
    public string encrypt(string plainText, byte[] iv) {
        string cipherText = "";
        //setting up AES Key
        KeyParameter aesKeyParam = ParameterUtilities.CreateKeyParameter(CRYPTO_ALGORITHM, encryptionKey);

        // Setting up the Initialization Vector. IV is used for encrypting the first block of input message
        ParametersWithIV aesIVKeyParam = new ParametersWithIV(aesKeyParam, iv);

        // Create the cipher object for AES algorithm using GCM mode and NO padding
        IBufferedCipher cipher = CipherUtilities.GetCipher(AES_ALGORITHM);
        cipher.Init(true, aesIVKeyParam);

        byte[] output = cipher.DoFinal(Encoding.UTF8.GetBytes(plainText));

        cipherText = Convert.ToBase64String(output);
        return cipherText;
    }

    public string decrypt(string cipherText, byte[] iv) {
        string plainText = "";
        //setting up AES Key
        KeyParameter aesKeyParam = ParameterUtilities.CreateKeyParameter(CRYPTO_ALGORITHM, encryptionKey);

        // Setting up the Initialization Vector. IV is used for encrypting the first block of input message
        ParametersWithIV aesIVKeyParam = new ParametersWithIV(aesKeyParam, iv);

        // Create the cipher object for AES algorithm using GCM mode and NO padding
        IBufferedCipher cipher = CipherUtilities.GetCipher(AES_ALGORITHM);
        cipher.Init(false, aesIVKeyParam);


        byte[] output = cipher.DoFinal(Convert.FromBase64String(cipherText));

        plainText = Encoding.UTF8.GetString(output);
        return plainText;
    }

     static void Main(string[] args) {
        AESController aes = new AESController("OXzN4fxHHgcKtAt/SJ4UWtNiQlzno7II1gIBs24CWpY=");
        byte[] iv = Base64.Decode("fdL8sKmhC8YIrYHMzoJJvQ==");
        string encryptedText = "TESTING123";

        string cipherText = aes.encrypt(encryptedText, iv);
        Console.Out.WriteLine("IV: " + Encoding.UTF8.GetString(Base64.Encode(iv)));
        Console.Out.WriteLine("Plain Text:"+aes.decrypt(cipherText, iv));
        Console.Out.WriteLine("Cipher Text:" + cipherText);

        Console.In.ReadLine();
    }

然后是PHP:

    $key = "OXzN4fxHHgcKtAt/SJ4UWtNiQlzno7II1gIBs24CWpY=";
    $iv = base64_decode("fdL8sKmhC8YIrYHMzoJJvQ==");
    //$iv = openssl_random_pseudo_bytes(16);
    //$cipherText = "YMdJ0mdWZ+p50krLzhyI0Q==";
    $plainText = "TESTING123";
    $decrypted = openssl_encrypt($plainText, "aes-256-cbc", $key, 0, $iv);

    var_dump($decrypted);

因此,来自C#bouncycastle的密文是:

  

EnOtpv4fOGiAKMzXXJMYBA ==

来自PHP的密文是:

  

CS + F7A / DBEGma7iQ / PQVLw ==

如果我将c#cipher文本带到PHP,则解密结果为:bool(False) (加密失败)

最后,如果在PHP中,我将填充更改为OPENSSL_ZERO_PADDING,并从C#解密密文,结果是:

  

_XGmNSlZx

对于我可以收集的内容,密钥和IV在两者上都是相同的(都是BASE64字符串),加密结果具有相同的长度(这解释了密文末尾的两个==。有什么我想念,或者我需要为openssl库做一些特别的事情?谢谢。

1 个答案:

答案 0 :(得分:1)

与OpenSSL命令行工具不同,PHP的openssl函数需要原始输入,而不是Base64编码的。

在您的PHP代码中,您还没有对该密钥进行Base64解码。