Как передать SecureString (или аналогичный) по сети, не раскрывая открытый текст?

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

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

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

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

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

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

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


person Jon Story    schedule 09.04.2019    source источник
comment
Просто: вы не можете этого сделать. SecureString защищен с помощью DPAPI с областью пользователя, поэтому только текущий пользователь Windows на текущем ПК может расшифровать его, и это сделано специально.   -  person Camilo Terevinto    schedule 09.04.2019
comment
Почему бы не хранить зашифрованный пароль на сервере и не расшифровывать его локально в приложении?   -  person Robert H    schedule 09.04.2019
comment
@RobertH Пароль никогда не должен быть зашифрован и никогда не может быть преобразован в обычный текст.   -  person Camilo Terevinto    schedule 09.04.2019
comment
Шифрование с открытым/закрытым ключом RSA кажется возможным способом сделать это? Попросите клиента зашифровать пароль с помощью открытого ключа сервера и передать зашифрованную строку. Сервер может расшифровать его своим закрытым ключом.   -  person Thomas N    schedule 09.04.2019
comment
@CamiloTerevinto Что ты предлагаешь? Если шифрование невозможно, а пароль не является локальным и не может быть простым текстом, я заинтригован решением здесь   -  person Robert H    schedule 09.04.2019
comment
@RobertH Фактический ответ заключается в том, что нет безопасного способа добиться этого. Серверу нужен обычный текст, а это неправильно с самого начала. RSA можно использовать, как прокомментировал ThomasN, но сервер все равно будет столь же небезопасным. У нас недостаточно информации, чтобы понять, почему это так беспокоит ОП, что память может быть сброшена и проверена.   -  person Camilo Terevinto    schedule 09.04.2019
comment
@CamiloTerevinto RSA - это правильное шифрование?   -  person Robert H    schedule 09.04.2019
comment
@ РобертХ Точно. Это укрепит безопасность на стороне клиента, но не на стороне сервера. Но мы не знаем, заботится ли ОП и о серверной части...   -  person Camilo Terevinto    schedule 09.04.2019
comment
RSA — это шифрование с открытым ключом. Клиентская программа генерирует ключ RSA (пару открытый/закрытый) и отправляет свой открытый ключ на сервер. Сервер шифрует пароль, используя это, и отправляет зашифрованную версию обратно. Только клиентская программа может расшифровать его, так как для этого требуется закрытая часть ключа. Защитите ссылку и в памяти, пока не расшифруете ее.   -  person Steve Todd    schedule 09.04.2019
comment
Меня не особенно волнует северная сторона здесь - если сервер скомпрометирован, у нас гораздо большие проблемы (сам сервер содержит более безопасную систему, чем та, доступ к которой осуществляется с помощью пароля). Этот вопрос полностью посвящен тому, чтобы не раскрывать пароль (насколько это возможно) на стороне клиента. Это внутреннее приложение в нашей организации, поэтому для пользователя не будет конца света, если он сможет получить доступ к паролю, но я все же предпочел бы избегать этого, насколько это возможно.   -  person Jon Story    schedule 09.04.2019


Ответы (1)


Вот рабочий пример использования шифрования 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));
    }
}
person Thomas N    schedule 09.04.2019
comment
Спасибо за это, не заметил этот метод. Хороший. Я думаю, он в первую очередь заботится о безопасной передаче? Он может легко конвертировать в/из SecureString на любом конце, если это необходимо. - person Thomas N; 09.04.2019