Как надежно сохранить логин / пароль (локальный)?
Я делаю приложение для Windows, в которое вы должны войти в первую очередь.
Данные учетной записи состоят из имени пользователя и пароля, и они должны быть сохранены локально.
Это просто вопрос безопасности, поэтому другие люди, использующие один и тот же компьютер, не могут видеть личные данные каждого.
Какой самый лучший / самый безопасный способ сохранить эти данные?
Я не хочу использовать базу данных, поэтому я попробовал кое-что с файлами ресурсов.
Но так как я немного новичок в этом, я не совсем уверен в том, что я делаю и где я должен искать решение.
6 ответов
Если вы просто собираетесь проверить / проверить введенные имя пользователя и пароль, используйте класс Rfc2898DerivedBytes (также известный как Функция получения ключа на основе пароля 2 или PBKDF2). Это более безопасно, чем использование шифрования, такого как Triple DES или AES, потому что нет практического способа перейти от результата RFC2898DerivedBytes к паролю. Вы можете перейти только от пароля к результату. См. Можно ли использовать хеш-пароль SHA1 в качестве соли при получении ключа шифрования и IV из строки пароля? для примера и обсуждения для.Net или String шифровать / дешифровать паролем C# Metro Style для WinRT/Metro.
Если вы храните пароль для повторного использования, например, для передачи его третьему лицу, используйте API защиты данных Windows (DPAPI). При этом используются сгенерированные и защищенные ключи операционной системы и алгоритм шифрования Triple DES для шифрования и дешифрования информации. Это означает, что вашему приложению не нужно беспокоиться о создании и защите ключей шифрования, что является серьезной проблемой при использовании криптографии.
В C# используйте класс System.Security.Cryptography.ProtectedData. Например, чтобы зашифровать часть данных, используйтеProtectedData.Protect()
:
// Data to protect. Convert a string to a byte[] using Encoding.UTF8.GetBytes().
byte[] plaintext;
// Generate additional entropy (will be used as the Initialization vector)
byte[] entropy = new byte[20];
using(RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider())
{
rng.GetBytes(entropy);
}
byte[] ciphertext = ProtectedData.Protect(plaintext, entropy,
DataProtectionScope.CurrentUser);
Надежно сохраняйте энтропию и зашифрованный текст, например, в файле или разделе реестра с установленными разрешениями, чтобы их мог прочитать только текущий пользователь. Чтобы получить доступ к исходным данным, используйтеProtectedData.Unprotect()
:
byte[] plaintext= ProtectedData.Unprotect(ciphertext, entropy,
DataProtectionScope.CurrentUser);
Обратите внимание, что существуют дополнительные соображения безопасности. Например, избегайте хранения таких секретов, как пароли, как string
, Строки являются неизменяемыми, поскольку они не могут быть уведомлены в памяти, так что кто-то, просматривающий память приложения или дамп памяти, может увидеть пароль. Вместо этого используйте SecureString или byte[] и не забудьте утилизировать или обнулить их, как только пароль больше не нужен.
Я хотел зашифровать и расшифровать строку как читаемую строку.
Вот очень простой быстрый пример в C# Visual Studio 2019 WinForms на основе ответа от @Pradip
.
Щелкните правой кнопкой мыши проект> свойства> настройки> создать username
а также password
настройка.
Теперь вы можете использовать только что созданные настройки. Здесь я сохраняюusername
а также password
но только зашифровать password
в поле респектабельного значения в user.config
файл.
Пример зашифрованной строки в user.config
файл.
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<userSettings>
<secure_password_store.Properties.Settings>
<setting name="username" serializeAs="String">
<value>admin</value>
</setting>
<setting name="password" serializeAs="String">
<value>AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAAQpgaPYIUq064U3o6xXkQOQAAAAACAAAAAAAQZgAAAAEAACAAAABlQQ8OcONYBr9qUhH7NeKF8bZB6uCJa5uKhk97NdH93AAAAAAOgAAAAAIAACAAAAC7yQicDYV5DiNp0fHXVEDZ7IhOXOrsRUbcY0ziYYTlKSAAAACVDQ+ICHWooDDaUywJeUOV9sRg5c8q6/vizdq8WtPVbkAAAADciZskoSw3g6N9EpX/8FOv+FeExZFxsm03i8vYdDHUVmJvX33K03rqiYF2qzpYCaldQnRxFH9wH2ZEHeSRPeiG</value>
</setting>
</secure_password_store.Properties.Settings>
</userSettings>
</configuration>
Полный код
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Security;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace secure_password_store
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Exit_Click(object sender, EventArgs e)
{
Application.Exit();
}
private void Login_Click(object sender, EventArgs e)
{
if (checkBox1.Checked == true)
{
Properties.Settings.Default.username = textBox1.Text;
Properties.Settings.Default.password = EncryptString(ToSecureString(textBox2.Text));
Properties.Settings.Default.Save();
}
else if (checkBox1.Checked == false)
{
Properties.Settings.Default.username = "";
Properties.Settings.Default.password = "";
Properties.Settings.Default.Save();
}
MessageBox.Show("{\"data\": \"some data\"}","Login Message Alert",MessageBoxButtons.OK, MessageBoxIcon.Information);
}
private void DecryptString_Click(object sender, EventArgs e)
{
SecureString password = DecryptString(Properties.Settings.Default.password);
string readable = ToInsecureString(password);
textBox4.AppendText(readable + Environment.NewLine);
}
private void Form_Load(object sender, EventArgs e)
{
//textBox1.Text = "UserName";
//textBox2.Text = "Password";
if (Properties.Settings.Default.username != string.Empty)
{
textBox1.Text = Properties.Settings.Default.username;
checkBox1.Checked = true;
SecureString password = DecryptString(Properties.Settings.Default.password);
string readable = ToInsecureString(password);
textBox2.Text = readable;
}
groupBox1.Select();
}
static byte[] entropy = Encoding.Unicode.GetBytes("SaLtY bOy 6970 ePiC");
public static string EncryptString(SecureString input)
{
byte[] encryptedData = ProtectedData.Protect(Encoding.Unicode.GetBytes(ToInsecureString(input)),entropy,DataProtectionScope.CurrentUser);
return Convert.ToBase64String(encryptedData);
}
public static SecureString DecryptString(string encryptedData)
{
try
{
byte[] decryptedData = ProtectedData.Unprotect(Convert.FromBase64String(encryptedData),entropy,DataProtectionScope.CurrentUser);
return ToSecureString(Encoding.Unicode.GetString(decryptedData));
}
catch
{
return new SecureString();
}
}
public static SecureString ToSecureString(string input)
{
SecureString secure = new SecureString();
foreach (char c in input)
{
secure.AppendChar(c);
}
secure.MakeReadOnly();
return secure;
}
public static string ToInsecureString(SecureString input)
{
string returnValue = string.Empty;
IntPtr ptr = System.Runtime.InteropServices.Marshal.SecureStringToBSTR(input);
try
{
returnValue = System.Runtime.InteropServices.Marshal.PtrToStringBSTR(ptr);
}
finally
{
System.Runtime.InteropServices.Marshal.ZeroFreeBSTR(ptr);
}
return returnValue;
}
private void EncryptString_Click(object sender, EventArgs e)
{
Properties.Settings.Default.password = EncryptString(ToSecureString(textBox2.Text));
textBox3.AppendText(Properties.Settings.Default.password.ToString() + Environment.NewLine);
}
}
}
Я использовал это раньше, и я думаю, чтобы убедиться, что учетные данные сохраняются и самым безопасным способом
- Вы можете записать их в файл конфигурации приложения, используя
ConfigurationManager
учебный класс - защита пароля с помощью
SecureString
учебный класс - затем шифровать его с помощью инструментов в
Cryptography
Пространство имен.
Надеюсь, эта ссылка очень поможет: нажмите здесь
DPAPI как раз для этого. Используйте DPAPI для шифрования пароля при первом вводе пользователем, сохраните его в безопасном месте (реестр пользователя, каталог данных приложения пользователя, некоторые варианты). Всякий раз, когда приложение запускается, проверьте местоположение, чтобы узнать, существует ли ваш ключ, использует ли он DPAPI для его дешифрования и разрешения доступа, в противном случае запретите его.
Это работает только в Windows, поэтому, если вы планируете использовать кроссплатформенное ядро dotnet, вам придется искать в другом месте. См. https://github.com/dotnet/corefx/blob/master/Documentation/architecture/cross-platform-cryptography.md
Для простых сценариев также можно использовать Windows Credential Management API с помощью оболочки C# CredentialManagement . Это дает единое место для хранения / извлечения паролей, которые легко изменить.
/questions/29609830/kak-hranit-i-poluchat-uchetnyie-dannyie-na-oknah-ispolzuya-c/29609839#29609839