Как передать SecureString (или аналогичную) по сети, не раскрывая открытый текст? - PullRequest
0 голосов
/ 09 апреля 2019

У меня есть приложение с «секретом» (например, пароль)

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

Я также не хочу, чтобы он был виден в памяти (например, из журнала сбоев) по понятным причинам, поэтому я храню секрет в SecureString

Однако, когда я сериализую SecureString, результат просто показывает длину строки открытого текста, например, {"Length":4}

Если я передам пароль в виде открытого текста, то он будет виден в извлеченном JSON в памяти, даже если впоследствии сохранит его в SecureString

Есть ли способ сериализации SecureString или получения JSON и преобразования строки открытого текста в SecureString без необходимости использования промежуточной обычной строки, которая будет храниться в памяти?

В этом сценарии мне нужно хранить / отправлять действительный пароль, а не, например, ключ одноразового использования, как я бы предпочел: это здесь вне моего контроля. Мне нужен пароль в виде обычного текста для доступа к другому сервису, поэтому обычное «Хэш, а затем сравните хэш» не применимо либо

1 Ответ

0 голосов
/ 09 апреля 2019

Вот рабочий пример использования шифрования RSA для отправки строки кому-то, чей открытый ключ у вас есть. В вашем вопросе вы хотите, чтобы сервер отправил сообщение (пароль) клиенту, а клиент мог безопасно использовать этот пароль, не беспокоясь о регистрации и т. Д. В середине. Чтобы это работало, вам нужно, чтобы клиент создал файл закрытого ключа и отправил файл открытого ключа на сервер, который затем сможет безопасно вернуться обратно.

Возможно, есть библиотеки, которые облегчают этот процесс.

[Test]
public void TestEncryption()
{
    /////////////// Create Key Files ////////////////
    RSACryptoServiceProvider provider = new RSACryptoServiceProvider(4096);

    //Create the key files on disk and distribute them to sender / reciever
    var publicKey =  provider.ToXmlString(false);
    var privateKey =  provider.ToXmlString(true);

    /////////////// Actual Test ////////////////

    //send with the public key
    byte[] sent = Send("hey",publicKey);

    //cannot receive with public key
    var ex = Assert.Throws<CryptographicException>(()=>Receive(sent, publicKey));
    StringAssert.Contains("Key does not exist",ex.Message);

    //but can with private key
    Assert.AreEqual("hey", Receive(sent,privateKey));
}

private Byte[] Send(string send, string publicKey)
{
    using (RSACryptoServiceProvider rsaSender = new RSACryptoServiceProvider())
    {
        rsaSender.FromXmlString(publicKey);
        return rsaSender.Encrypt(Encoding.ASCII.GetBytes(send), false);
    }
}

private object Receive(byte[] sent, string privateKey)
{
    using (RSACryptoServiceProvider rsaReceiver = new RSACryptoServiceProvider())
    {
        rsaReceiver.FromXmlString(privateKey);
        return Encoding.ASCII.GetString(rsaReceiver.Decrypt(sent, false));
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...