Шифрование между настольным приложением и сервером - С# в PHP

У меня есть приложение, которое создано на С#. Простыми словами приложение отправляет данные и изображение на мой веб-сервер, который принимает все данные $_POST и обрабатывает его. Признаюсь, я не понимаю, как работает безопасность. Я буду использовать кого-то с соответствующим опытом, чтобы сделать это, но я даже не знаю, что спросить их на этом этапе, как в некоторых принятых методах.

Я предполагаю, что это не так просто, как только base64 кодирует/декодирует данные и требует более высокого уровня шифрования. В течение следующих нескольких недель веб-сервер получит сертификацию HTTPS SSL (OV), но мое ограниченное понимание заключается в том, что мне по-прежнему нужна какая-то защита/шифрование при передаче данных с ПК пользователей на мой веб-сервер, чтобы кто-то не слушал передача данных или что-то в этом роде.

Простыми словами, если я хочу, чтобы данные были защищены между пользователями и моим веб-сервером, какие из наиболее распространенных или принятых методов для С# для PHP?

Данные поступают непосредственно из приложения на ПК пользователей на мой сервер, я управляю исходным кодом для обоих, но я сам, а не разработчик, поэтому у меня нет технических знаний по этой проблеме.

Один разработчик С# говорил с предложенным симметричным/асимметричным алгоритмом, но он не является разработчиком PHP, поэтому он не знает, может ли php взять эти данные и расшифровать его.

Ответы

Ответ 1

Чтобы ответить на ваши дальнейшие вопросы, когда сервер выпущен и правильно настроен с хорошим сертификатом, вам больше не нужно ничего делать.

Использование HTTPS

HTTPS работает, проверяя сертификаты SSL с центром сертификации (CA) во время первоначального рукопожатия. Органы сертификации, которые по существу являются списком подписей, которые используются для проверки указанных сертификатов, обычно поставляются с предустановленной производителем ОС.

Предполагая, что у вашего сервера есть сертификат, выданный CA, все, что вам нужно будет сделать, это изменить с использованием HTTP на HTTPS при подключении. Библиотека, которую вы используете, должна иметь метод проверки SSL-сертификата серверов, если он автоматически не сделает это для вас.

Нет никаких технических причин, по которым вам нужно будет шифровать все, что будет отправлено через HTTPS, если сертификат сильно зашифрован.

Кроме того, если вы хотите углубиться в подробные подробности о том, как работает HTTPS, этот очень хороший пост в отношении информационной безопасности, который немного проливает свет на внутреннюю работу протокола.

Чтобы ответить на ваш первоначальный вопрос

Для полноты.

В PHP есть расширение криптографии mcrypt, которое поддерживает различные алгоритмы и режимы работы шифрования. Я собрал простой пример, используя дешифрование ключа AES 256/PBKDF-SHA1 (вместе с кодом С# для выполнения шифрования).

EDIT: Я хотел бы указать, что hash_pbkdf2 доступен только в PHP 5.5 и выше. Поддержка до 5.3 может быть добавлена ​​с этот отличный трюк.

PHP

function decode_aes($data, $key) // Decrypt custom format data string
{
    $iv_size = mcrypt_get_iv_size(MCRYPT_RIJNDAEL_128, MCRYPT_MODE_CBC);
    $salt_size = 16;

    $iv = substr($data, 0, $iv_size); // Init vector
    $salt = substr($data, $iv_size, $salt_size); // The salt
    $extact = substr($data, $iv_size + $salt_size); // This is the encrypted data

    $key = hash_pbkdf2("sha1", $key, $salt, 1000, 32, true); // Sets to use PBKDF-SHA1

    return mcrypt_decrypt(MCRYPT_RIJNDAEL_128, $key, $extact, MCRYPT_MODE_CBC, $iv); // Perform the decryption with the extracted sections
}

// As an example, I've included this.
$encryped = "zgCp2sSDs32Y8SOn8MYFCEjOJDeM4E3Y8Wx52A+iTFRk/1TJwMzkqmrB06bFu8dK";
echo decode_aes(base64_decode($encryped), "password");

С#

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

namespace AESExample
{
    class Program
    {
        static void Main(string[] args)
        {
            byte[] toEncrypt = Encoding.UTF8.GetBytes("Encrypted Text");
            byte[] key = Encoding.UTF8.GetBytes("password");
            String encrypted = Convert.ToBase64String(EncryptAES(toEncrypt, key));
        }

        public static byte[] EncryptAES(byte[] data, byte[] key)
        {
            using(RijndaelManaged algo = new RijndaelManaged())
            {
                algo.GenerateIV();
                algo.Mode = CipherMode.CBC;
                algo.Padding = PaddingMode.Zeros;

                byte[] saltBuffer = new byte[16];
                RNGCryptoServiceProvider saltGenerator = new RNGCryptoServiceProvider();
                saltGenerator.GetBytes(saltBuffer);

                Rfc2898DeriveBytes PBKDF2 = new Rfc2898DeriveBytes(key, saltBuffer, 1000);
                key = PBKDF2.GetBytes(32);

                ICryptoTransform cipher = algo.CreateEncryptor(key, algo.IV);

                using(MemoryStream ms = new MemoryStream())
                {
                    ms.Write(algo.IV, 0, algo.IV.Length);
                    ms.Write(saltBuffer, 0, saltBuffer.Length);
                    using(CryptoStream cs = new CryptoStream(ms, cipher, CryptoStreamMode.Write))
                    {
                        using(StreamWriter sw = new StreamWriter(cs))
                        {
                            sw.Write(Encoding.UTF8.GetString(data).ToCharArray());
                        }
                    }
                    return ms.ToArray();
                }
            }
        }
    }
}

Ответ 2

Кажется, вы обеспокоены безопасностью данных при передаче из клиентского приложения на сервер и наоборот. Как уже упоминалось в комментариях, в этом отношении достаточно HTTPS-соединения. Он автоматически выполняет шифрование/дешифрование для вас.

Чтобы получить соединение HTTPS, вы приобретете сертификат SSL (Namecheap - это один веб-сайт, на котором вы можете его купить) и установите его на свой веб-сервер. Сертификат автоматически устанавливается на локальном компьютере пользователя при первом подключении к серверу, и каждое последующее соединение выполняет проверку действительного сертификата. Таким образом, в основном, вы просто устанавливаете сертификат на сервер и не должны беспокоиться об этом, пока вам не потребуется обновлять сертификат. Просто убедитесь, что ваше клиентское приложение пытается подключиться к HTTPS-адресу вместо HTTP.

Если вы должны были реализовать симметричное/асимметричное шифрование, это помогло бы с шифрованием и расшифровкой до и после передачи данных. Если вы зашифруете данные в своем клиентском приложении, вам придется расшифровать его на стороне сервера, когда вы его получите, и наоборот. Это обеспечит вам еще более высокую безопасность; однако, в зависимости от характера вашего приложения, HTTPS-соединение может быть достаточно.

Один из моих личных проектов - клиентское приложение С#, которое подключается к веб-серверу Ruby, который я также написал. Я установил SSL-сертификат на моем веб-сервере Ruby, чтобы данные были зашифрованы во время транзита. В моем случае передаваемые данные не содержат никаких пользовательских данных или PII (личная идентификационная информация) и, следовательно, не представляют угрозы безопасности, если внешняя сторона получает доступ к этой информации. Таким образом, я чувствовал, что использование шифрования до и после транзита не стоит и не будет давать никаких преимуществ конечному пользователю. Опять же, это зависит от характера вашего приложения и ожиданий ваших пользователей.

EDIT:

Как mine, упомянутый в комментариях, StartSSL предлагает бесплатные сертификаты SSL.