代码之家  ›  专栏  ›  技术社区  ›  Shuyi

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

  •  1
  • Shuyi  · 技术社区  · 9 年前

    因此,我用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#密码文本转换为PHP,解密结果是:bool(False) (加密失败)

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

    _XGmNSlZx

    我可以收集到的是,密钥和IV在两者上都是相同的(都是BASE64字符串),加密的结果具有相同的长度(这解释了密码文本末尾的两个==的原因)。我是否遗漏了什么,或者我需要为openssl库做一些特殊的事情?谢谢。

    1 回复  |  直到 9 年前
        1
  •  1
  •   Narf    9 年前

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

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

    推荐文章