简体   繁体   English

使用 BouncyCastle 在 C# 中使用 OpenSSL 使用 AES256-GCM 解密由 PHP 加密的字符串

[英]Decrypting a string encrypted by PHP with AES256-GCM using OpenSSL in C# using BouncyCastle

SOLUTION解决方案

Note: I've replaced the simple SHA256 derivation key with PBKDF2-SHA512 (with 20K iterations) to improve the security.注意:我已将简单的 SHA256 派生密钥替换为 PBKDF2-SHA512(具有 20K 次迭代)以提高安全性。

PHP functions: PHP 功能:

function str_encryptaesgcm($plaintext, $password, $encoding = null) {
    $keysalt = openssl_random_pseudo_bytes(16);
    $key = hash_pbkdf2("sha512", $password, $keysalt, 20000, 32, true);
    $iv = openssl_random_pseudo_bytes(openssl_cipher_iv_length("aes-256-gcm"));
    $tag = "";
    $encryptedstring = openssl_encrypt($plaintext, "aes-256-gcm", $key, OPENSSL_RAW_DATA, $iv, $tag, "", 16);
    return $encoding == "hex" ? bin2hex($keysalt.$iv.$encryptedstring.$tag) : ($encoding == "base64" ? base64_encode($keysalt.$iv.$encryptedstring.$tag) : $keysalt.$iv.$encryptedstring.$tag);
}

function str_decryptaesgcm($encryptedstring, $password, $encoding = null) {
    $encryptedstring = $encoding == "hex" ? hex2bin($encryptedstring) : ($encoding == "base64" ? base64_decode($encryptedstring) : $encryptedstring);
    $keysalt = substr($encryptedstring, 0, 16);
    $key = hash_pbkdf2("sha512", $password, $keysalt, 20000, 32, true);
    $ivlength = openssl_cipher_iv_length("aes-256-gcm");
    $iv = substr($encryptedstring, 16, $ivlength);
    $tag = substr($encryptedstring, -16);
    return openssl_decrypt(substr($encryptedstring, 16 + $ivlength, -16), "aes-256-gcm", $key, OPENSSL_RAW_DATA, $iv, $tag);
}

C# Class: C# Class:

using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Parameters;
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace PoGORaidEngine.Crypto
{
    internal static class AESGCM
    {
        private const int MAC_BIT_SIZE = 128;
        private const int SALTKEY_BIT_SIZE = 128;
        private const int NONCE_BIT_SIZE = 96;

        internal static string DecryptString(string EncryptedString, string Password)
        {
            if (string.IsNullOrEmpty(EncryptedString))
                return string.Empty;

            byte[] EncryptedData = Convert.FromBase64String(EncryptedString);
            byte[] SaltKey;
            byte[] Key;
            byte[] IV;
            byte[] CipherText;
            byte[] Tag;

            using (MemoryStream MStream = new MemoryStream(EncryptedData))
            using (BinaryReader Binary = new BinaryReader(MStream))
            {
                SaltKey = Binary.ReadBytes(SALTKEY_BIT_SIZE / 8);
                Key = PBKDF2DerivateKey(Password, HashAlgorithmName.SHA512, SaltKey, 20000, 32);
                IV = Binary.ReadBytes(NONCE_BIT_SIZE / 8);
                CipherText = Binary.ReadBytes(EncryptedData.Length - SaltKey.Length - IV.Length - (MAC_BIT_SIZE / 8));
                Tag = Binary.ReadBytes(MAC_BIT_SIZE / 8);
            }

            byte[] DecryptedData = new byte[CipherText.Length];
            byte[] CipherTextTag = new byte[CipherText.Length + Tag.Length];
            Buffer.BlockCopy(CipherText, 0, CipherTextTag, 0, CipherText.Length);
            Buffer.BlockCopy(Tag, 0, CipherTextTag, CipherText.Length, Tag.Length);

            GcmBlockCipher Cipher = new GcmBlockCipher(new AesEngine());
            Cipher.Init(false, new AeadParameters(new KeyParameter(Key), MAC_BIT_SIZE, IV));
            int Length = Cipher.ProcessBytes(CipherTextTag, 0, CipherTextTag.Length, DecryptedData, 0);
            Cipher.DoFinal(DecryptedData, Length);

            return Encoding.UTF8.GetString(DecryptedData);
        }

        private static byte[] PBKDF2DerivateKey(string Password, HashAlgorithmName Algorithm, byte[] Salt, int Iterations, int Length)
        {
            using (Rfc2898DeriveBytes DeriveBytes = new Rfc2898DeriveBytes(Password, Salt, Iterations, Algorithm))
                return DeriveBytes.GetBytes(Length);
        }
    }
}

I'm using openssl to encrypt/decrypt strings in PHP:我正在使用 openssl 加密/解密 PHP 中的字符串:

function str_encryptaesgcm($plaintext, $password, $encoding = null) {
    $aes = array("key" => substr(hash("sha256", $password, true), 0, 32), "cipher" => "aes-256-gcm", "iv" => openssl_random_pseudo_bytes(openssl_cipher_iv_length("aes-256-gcm")));
    $encryptedstring = openssl_encrypt($plaintext, $aes["cipher"], $aes["key"], OPENSSL_RAW_DATA, $aes["iv"], $aes["tag"], "", 16);
    return $encoding == "hex" ? bin2hex($aes["iv"].$encryptedstring.$aes["tag"]) : ($encoding == "base64" ? base64_encode($aes["iv"].$encryptedstring.$aes["tag"]) : $aes["iv"].$encryptedstring.$aes["tag"]);
}

function str_decryptaesgcm($encryptedstring, $password, $encoding = null) {
    $encryptedstring = $encoding == "hex" ? hex2bin($encryptedstring) : ($encoding == "base64" ? base64_decode($encryptedstring) : $encryptedstring);
    $aes = array("key" => substr(hash("sha256", $password, true), 0, 32), "cipher" => "aes-256-gcm", "ivlength" => openssl_cipher_iv_length("aes-256-gcm"), "iv" => substr($encryptedstring, 0, openssl_cipher_iv_length("aes-256-gcm")), "tag" => substr($encryptedstring, -16));
    return openssl_decrypt(substr($encryptedstring, $aes["ivlength"], -16), $aes["cipher"], $aes["key"], OPENSSL_RAW_DATA, $aes["iv"], $aes["tag"]);
}

and everything works correctly, in fact I get:一切正常,事实上我得到:

$text = "Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit...";
$pass = "A random password to encrypt";
$enc = str_encryptaesgcm($text, $pass, "base64"); // OUTPUT: TrbntVEj8GEGeLE6ZYJnDIXnqSese5biWn604NePb2r6jsFhuzJsNHnN2GCizrGfhP4W39tahrGj0tORxvUbDpGT76WHr/v2wmnHHHiDGyjeKlWLu9/gfeualYvhsNF/N9inSpqxE2lQ+/vwpUJKYJw3bfo7DoGPDNk=
$dec = str_decryptaesgcm($enc, $pass, "base64"); // OUTPUT: Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit...

Unfortunately though, I need to decrypt the string from C#, therefore I'm using BouncyCastle to do this, and this is the class that I'm using:不幸的是,我需要从 C# 中解密字符串,因此我使用 BouncyCastle 来执行此操作,这就是我正在使用的 class:

using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Parameters;
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace PoGORaidEngine.Crypto
{
    internal static class AESGCM
    {
        private const int KEY_BIT_SIZE = 256;
        private const int MAC_BIT_SIZE = 128;
        private const int NONCE_BIT_SIZE = 96; // 12 bytes (openssl)

        internal static string DecryptString(string EncryptedString, string Password)
        {
            if (string.IsNullOrEmpty(EncryptedString))
                return string.Empty;

            byte[] Key = Encoding.UTF8.GetBytes(SHA256String(Password).Substring(0, 32));
            byte[] EncryptedData = Convert.FromBase64String(EncryptedString);

            if (Key == null || Key.Length != KEY_BIT_SIZE / 8)
                throw new ArgumentException(string.Format("Key needs to be {0} bit.", KEY_BIT_SIZE), "Key");

            using (MemoryStream MStream = new MemoryStream(EncryptedData))
            using (BinaryReader Binary = new BinaryReader(MStream))
            {
                byte[] IV = Binary.ReadBytes(NONCE_BIT_SIZE / 8);
                GcmBlockCipher Cipher = new GcmBlockCipher(new AesEngine());
                Cipher.Init(false, new AeadParameters(new KeyParameter(Key), MAC_BIT_SIZE, IV));

                byte[] CipherText = Binary.ReadBytes(EncryptedData.Length - IV.Length);
                byte[] PlainText = new byte[Cipher.GetOutputSize(CipherText.Length)];

                int Length = Cipher.ProcessBytes(CipherText, 0, CipherText.Length, PlainText, 0);
                Cipher.DoFinal(PlainText, Length);

                return Encoding.UTF8.GetString(PlainText);
            }
        }

        private static string SHA256String(string Password)
        {
            using (SHA256 Hash = SHA256.Create())
            {
                byte[] PasswordBytes = Hash.ComputeHash(Encoding.UTF8.GetBytes(Password));
                StringBuilder SB = new StringBuilder();

                for (int i = 0; i < PasswordBytes.Length; i++)
                    SB.Append(PasswordBytes[i].ToString("X2"));

                return SB.ToString();
            }
        }
    }
}

but when I call the method to decrypt the following exception is thrown:但是当我调用该方法来解密时,会引发以下异常:

Org.BouncyCastle.Crypto.InvalidCipherTextException: mac check in GCM failed

I wasted several hours trying to figure out the problem but without success, I also tried to search here, on Stackoverflow, but nothing I found answers my question, not even this answer .我浪费了几个小时试图找出问题,但没有成功,我也尝试在 Stackoverflow 上搜索这里,但我没有找到任何答案,甚至没有回答我的问题。 Is there anyone who has tested and tried to decrypt from PHP (openssl) to C# with BouncyCastle using AES256-GCM?有没有人使用 AES256-GCM 使用 BouncyCastle 测试并尝试从 PHP(openssl)解密到 C#? Thanks in advance for any help.提前感谢您的帮助。

UPDATE更新

I've tried to update the PHP method to encrypt in order to see if data is ok:我尝试更新 PHP 方法进行加密,以查看数据是否正常:

function str_encryptaesgcm($plaintext, $password, $encoding = null) {
    $aes = array("key" => substr(hash("sha256", $password, true), 0, 32), "cipher" => "aes-256-gcm", "iv" => openssl_random_pseudo_bytes(openssl_cipher_iv_length("aes-256-gcm")));
    $encryptedstring = openssl_encrypt($plaintext, $aes["cipher"], $aes["key"], OPENSSL_RAW_DATA, $aes["iv"], $aes["tag"], "", 16);

    switch ($encoding) {
        case "base64":
            return array("encrypteddata" => base64_encode($aes["iv"].$encryptedstring.$aes["tag"]), "iv" => base64_encode($aes["iv"]), "encryptedstring" => base64_encode($encryptedstring), "tag" => base64_encode($aes["tag"]));
        case "hex":
            return array("encrypteddata" => bin2hex($aes["iv"].$encryptedstring.$aes["tag"]), "iv" => bin2hex($aes["iv"]), "encryptedstring" => bin2hex($encryptedstring), "tag" => bin2hex($aes["tag"]));
        default:
            return array("encrypteddata" => $aes["iv"].$encryptedstring.$aes["tag"], "iv" => $aes["iv"], "encryptedstring" => $encryptedstring, "tag" => $aes["tag"]);
    }
}

So I get:所以我得到:

{"encrypteddata":"w2eUXD41sCgTBvN7PtKlhzHB0lodPohnOh8V1lWsATvRujwsV18DDftGqJLqpsWxatYUX7C0jxjLcPQUoazIfiVdRmAsbGAKuvXYSsNjQ6ahGY4AxowAp0p\/IGDuYWbCrof6GZHUyoxv9Ry8NP1yxNItnBlUhGS8ua0=","iv":"w2eUXD41sCgTBvN7","encryptedstring":"PtKlhzHB0lodPohnOh8V1lWsATvRujwsV18DDftGqJLqpsWxatYUX7C0jxjLcPQUoazIfiVdRmAsbGAKuvXYSsNjQ6ahGY4AxowAp0p\/IGDuYWbCrof6GZHUyoxv9Q==","tag":"HLw0\/XLE0i2cGVSEZLy5rQ=="}

This makes me understand that on the PHP side everything is ok, also because when I perform the decryption from PHP everything works correctly.这让我明白,在 PHP 方面一切正常,还因为当我从 PHP 执行解密时,一切正常。 I tried to update the class on the C# code as proposed by Micheal Fehr , however I get a new exception: Org.BouncyCastle.Crypto.InvalidCipherTextException: data too short :我尝试按照Micheal Fehr的建议更新 C# 代码上的 class ,但是我得到了一个新的异常: Org.BouncyCastle.Crypto.InvalidCipherTextException: data too short

using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Parameters;
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace PoGORaidEngine.Crypto
{
    internal static class AESGCM
    {
        private const int MAC_BIT_SIZE = 128;
        private const int NONCE_BIT_SIZE = 96;

        internal static string DecryptString(string EncryptedString, string Password)
        {
            if (string.IsNullOrEmpty(EncryptedString))
                return string.Empty;

            byte[] EncryptedData = Convert.FromBase64String(EncryptedString);
            byte[] Key = DerivateKey(Password);
            byte[] IV;
            byte[] CipherText;
            byte[] Tag;

            using (MemoryStream MStream = new MemoryStream(EncryptedData))
            using (BinaryReader Binary = new BinaryReader(MStream))
            {
                IV = Binary.ReadBytes(NONCE_BIT_SIZE / 8);
                CipherText = Binary.ReadBytes(EncryptedData.Length - IV.Length - (MAC_BIT_SIZE / 8));
                Tag = Binary.ReadBytes(MAC_BIT_SIZE / 8);
            }

            byte[] AAED = new byte[0];
            byte[] DecryptedData = new byte[CipherText.Length];

            GcmBlockCipher Cipher = new GcmBlockCipher(new AesEngine());
            Cipher.Init(false, new AeadParameters(new KeyParameter(Key), MAC_BIT_SIZE, IV, AAED));
            int Length = Cipher.ProcessBytes(CipherText, 0, CipherText.Length, DecryptedData, 0);
            Cipher.DoFinal(DecryptedData, Length);

            return Encoding.UTF8.GetString(DecryptedData);
        }

        private static byte[] DerivateKey(string Password)
        {
            using (SHA256 Hash = SHA256.Create())
                return Hash.ComputeHash(Encoding.UTF8.GetBytes(Password));
        }
    }
}

As a counter test I tried to get in base64 IV, clean encrypted string and tag and the data match perfectly, as in PHP.作为反测试,我尝试进入 base64 IV,清理加密字符串和标签,并且数据完美匹配,如 PHP。 I'm sure the solution is very close.我确信解决方案非常接近。 The problem arises on: Cipher.DoFinal(DecryptedData, Length);问题出现在: Cipher.DoFinal(DecryptedData, Length); ( new byte[CipherText.Length] ). new byte[CipherText.Length] )。

I'm not for sure that your "key derivation" on C# is working as on PHP, so I used my own one.我不确定您在 C# 上的“密钥派生”是否与在 PHP 上一样工作,所以我使用了自己的。 As well, I used an own decryption function that runs without Bouncy Castle , and it could be a good basis for your work with Bouncy Castle.同样,我使用了自己的解密 function ,它在没有 Bouncy Castle的情况下运行,它可能是您使用 Bouncy Castle 工作的良好基础。

Kindly note that a key derivation using SHA-hashes is UNSECURE and you should use something like PBKDF2 for this task.请注意,使用 SHA 哈希的密钥派生是不安全的,您应该使用 PBKDF2 之类的东西来完成此任务。

I'm using the sample output我正在使用样品 output

TrbntVEj8GEGeLE6ZYJnDIXnqSese5biWn604NePb2r6jsFhuzJsNHnN2GCizrGfhP4W39tahrGj0tORxvUbDpGT76WHr/v2wmnHHHiDGyjeKlWLu9/gfeualYvhsNF/N9inSpqxE2lQ+/vwpUJKYJw3bfo7DoGPDNk=

as input for the decryption function in C# - this is the result:作为 C# 中解密 function 的输入 - 这是结果:

AES GCM 256 String decryption
* * * Decryption * * *
ciphertext (Base64): TrbntVEj8GEGeLE6ZYJnDIXnqSese5biWn604NePb2r6jsFhuzJsNHnN2GCizrGfhP4W39tahrGj0tORxvUbDpGT76WHr/v2wmnHHHiDGyjeKlWLu9/gfeualYvhsNF/N9inSpqxE2lQ+/vwpUJKYJw3bfo7DoGPDNk=
plaintext: Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit...

Kindly note that my code has no exception handling and is for educational purpose only, the code is running with .net 5 in an online compiler ( https://dotnetfiddle.net/WvUkXf ):请注意,我的代码没有异常处理,仅用于教育目的,代码在在线编译器( https://dotnetfiddle.net/WvUkXf )中使用 .net 5 运行:

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

public class Program {
    public static void Main() {
        Console.WriteLine("AES GCM 256 String decryption");

        // decryption
        Console.WriteLine("\n* * * Decryption * * *");

        string password = "A random password to encrypt";
        //generate hash of password # # # this is UNSECURE # # #
        SHA256 mySHA256 = SHA256.Create();
        byte[] Key = mySHA256.ComputeHash(Encoding.UTF8.GetBytes(password));
        // ciphertext taken from encryption function in PHP
        string soCiphertextBase64 = "TrbntVEj8GEGeLE6ZYJnDIXnqSese5biWn604NePb2r6jsFhuzJsNHnN2GCizrGfhP4W39tahrGj0tORxvUbDpGT76WHr/v2wmnHHHiDGyjeKlWLu9/gfeualYvhsNF/N9inSpqxE2lQ+/vwpUJKYJw3bfo7DoGPDNk=";
        Console.WriteLine("ciphertext (Base64): " + soCiphertextBase64);
        string soDecryptedtext = soAesGcmDecryptFromBase64(Key, soCiphertextBase64);
        Console.WriteLine("plaintext: " + soDecryptedtext);
    }

    static string soAesGcmDecryptFromBase64(byte[] key, string data) {
        const int MAC_BIT_SIZE = 128;
        const int NONCE_BIT_SIZE = 96; // 12 bytes (openssl)
        byte[] EncryptedData = Convert.FromBase64String(data);
        byte[] IV;
        byte[] CipherText;
        byte[] Tag;
        using (MemoryStream MStream = new MemoryStream(EncryptedData))
        using (BinaryReader Binary = new BinaryReader(MStream)) {
            IV = Binary.ReadBytes(NONCE_BIT_SIZE / 8);
            CipherText = Binary.ReadBytes(EncryptedData.Length - IV.Length - (MAC_BIT_SIZE / 8));
            Tag = Binary.ReadBytes((MAC_BIT_SIZE / 8));
        }
        string decryptedtext;
        byte[] associatedData = new byte[0];
        byte[] decryptedData = new byte[CipherText.Length];
        using(var cipher = new AesGcm(key)) {
            cipher.Decrypt(IV, CipherText, Tag, decryptedData, associatedData);
            decryptedtext = Encoding.UTF8.GetString(decryptedData, 0, decryptedData.Length);
            return decryptedtext;
        }
    }
}

Edit: Did you notice that the GCM-Tag is never used in your updated decryption function?编辑:您是否注意到 GCM-Tag 从未在您更新的解密 function 中使用?

Bouncy Castle's GCM function works similar to the Java-pendant and needs a ciphertext that has the tag appended to the ciphertext. Bouncy Castle 的 GCM function 的工作方式与 Java 挂件类似,需要一个将标签附加到密文的密文。

In the end you need to do some byte array copy operations:最后你需要做一些字节数组复制操作:

byte[] CipherTextTag = new byte[CipherText.Length + Tag.Length];
System.Buffer.BlockCopy(CipherText, 0, CipherTextTag, 0, CipherText.Length);
System.Buffer.BlockCopy(Tag, 0, CipherTextTag, CipherText.Length, Tag.Length);
int Length = Cipher.ProcessBytes(CipherTextTag, 0, CipherTextTag.Length, DecryptedData, 0);

Using this "complete ciphertext" you get it to run with the original PHP code:使用此“完整密文”,您可以使用原始 PHP 代码运行它:

AES GCM 256 String decryption
* * * Decryption * * *
ciphertext (Base64): aV+gDmSBbi9PjOT9FD8LcuISbEQ5F3q0X8qzf3MKiDzxo12WQVirsnltbApLMMG9JScVfTXx7PJw7EVFoKz8JLMYLMu/JsRGcfvihSK+d/yeRTBEuJHL74Hv2Zr7b4CoMJhEUmYF3KT2Onlj4lI5ChOjmgXvpSev/xc=
plaintext: Neque porro quisquam est qui dolorem ipsum quia dolor sit amet, consectetur, adipisci velit...

The complete code:完整代码:

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Parameters;

public class Program {
    public static void Main() {
        Console.WriteLine("AES GCM 256 String decryption");

        // decryption
        Console.WriteLine("\n* * * Decryption * * *");
        
        string password = "A random password to encrypt";
        //generate hash of password # # # this is UNSECURE # # #

        string soCiphertextBase64 = "aV+gDmSBbi9PjOT9FD8LcuISbEQ5F3q0X8qzf3MKiDzxo12WQVirsnltbApLMMG9JScVfTXx7PJw7EVFoKz8JLMYLMu/JsRGcfvihSK+d/yeRTBEuJHL74Hv2Zr7b4CoMJhEUmYF3KT2Onlj4lI5ChOjmgXvpSev/xc=";
        Console.WriteLine("ciphertext (Base64): " + soCiphertextBase64);
        string soDecryptedtextAsk = DecryptString(soCiphertextBase64, password);
        Console.WriteLine("plaintext: " + soDecryptedtextAsk);
    }
    
    static string DecryptString(string EncryptedString, string Password)
        {
            const int MAC_BIT_SIZE = 128;
            const int NONCE_BIT_SIZE = 96;
            if (string.IsNullOrEmpty(EncryptedString))
                return string.Empty;
            byte[] EncryptedData = Convert.FromBase64String(EncryptedString);
            byte[] Key = DerivateKey(Password);
            byte[] IV;
            byte[] CipherText;
            byte[] Tag;
            using (MemoryStream MStream = new MemoryStream(EncryptedData))
            using (BinaryReader Binary = new BinaryReader(MStream))
            {
                IV = Binary.ReadBytes(NONCE_BIT_SIZE / 8);
                CipherText = Binary.ReadBytes(EncryptedData.Length - IV.Length - (MAC_BIT_SIZE / 8));
                Tag = Binary.ReadBytes(MAC_BIT_SIZE / 8);
            }
            byte[] AAED = new byte[0];
            byte[] DecryptedData = new byte[CipherText.Length];
            GcmBlockCipher Cipher = new GcmBlockCipher(new AesEngine());
            Cipher.Init(false, new AeadParameters(new KeyParameter(Key), MAC_BIT_SIZE, IV, AAED));
            // combine ciphertext + tag
            byte[] CipherTextTag = new byte[CipherText.Length + Tag.Length];
            System.Buffer.BlockCopy(CipherText, 0, CipherTextTag, 0, CipherText.Length);
            System.Buffer.BlockCopy(Tag, 0, CipherTextTag, CipherText.Length, Tag.Length);
            int Length = Cipher.ProcessBytes(CipherTextTag, 0, CipherTextTag.Length, DecryptedData, 0);
            //int Length = Cipher.ProcessBytes(CipherText, 0, CipherText.Length, DecryptedData, 0);
            Cipher.DoFinal(DecryptedData, Length);
            return Encoding.UTF8.GetString(DecryptedData);
        }

        private static byte[] DerivateKey(string Password)
        {
            using (SHA256 Hash = SHA256.Create())
                return Hash.ComputeHash(Encoding.UTF8.GetBytes(Password));
        }
}

Marco - I'm curious - Are these the only two languages you are using (PHP & C#)? Marco - 我很好奇 - 这是您使用的仅有的两种语言(PHP 和 C#)吗? we have written some cross language / libraries for GCM (128 & 256) using Java, C#, Go, Python, Ruby, C, with Openssl, bouncycastle, and others and have not run into any problems like you have but we are handling key management a little differently. we have written some cross language / libraries for GCM (128 & 256) using Java, C#, Go, Python, Ruby, C, with Openssl, bouncycastle, and others and have not run into any problems like you have but we are handling key管理略有不同。 We have not added PHP yet but have seen some differences in some of the PHP interfaces with OpenSSL compared to C.我们尚未添加 PHP,但我们发现 PHP 与 OpenSSL 接口与 Z0D61F8370CAD1D3DE1125D78 相比存在一些差异

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM