Лучшие практики для сохранения конфиденциальных данных в Windows 8
Каков наилучший способ сохранения конфиденциальных данных в локальный файл в Windows 8? Я занимаюсь разработкой приложения на C#, которое должно хранить oAuth-токены / пароли. Я слышал, что в.NET было обычным делом шифровать / дешифровать данные, но у меня нет никакого опыта работы с этой механикой. Шифрование все еще рекомендуется / необходимо, учитывая, что приложения Windows 8 имеют собственную личную / защищенную область хранения, аналогичную Windows Phone?
Кроме того, не вызывает ли шифрование / дешифрование каждый раз, когда вы запрашиваете данные, проблемы с производительностью? (было бы лучше написать собственный / облегченный алгоритм?)
3 ответа
ОБНОВЛЕНИЕ: Пожалуйста, имейте в виду, что в то время как современные / метро приложения не могут соваться друг с другом, настольные приложения будут иметь неограниченный доступ ко всем данным, хранящимся через эти API. См. http://www.hanselman.com/blog/SavingAndRetrievingBrowserAndOtherPasswords.aspx котором содержится код, демонстрирующий это.
В Win8 появился новый API PasswordVault, предназначенный для решения всех этих сложных проблем. Действительно прост в использовании, безопасен и может быть настроен пользователями на перемещение между своими компьютерами, поэтому им нужно вводить учетные данные только один раз. Я успешно использовал это для токенов OAuth
Получение учетных данных (обратите внимание на глупое исключение, которое вызывает WinRT... они действительно должны просто возвращать ноль):
const string VAULT_RESOURCE = "[My App] Credentials";
string UserName { get; set; };
string Password { get; set; };
var vault = new PasswordVault();
try
{
var creds = vault.FindAllByResource(VAULT_RESOURCE).FirstOrDefault();
if (creds != null)
{
UserName = creds.UserName;
Password = vault.Retrieve(VAULT_RESOURCE, UserName).Password;
}
}
catch(COMException)
{
// this exception likely means that no credentials have been stored
}
Хранение учетных данных:
vault.Add(new PasswordCredential(VAULT_RESOURCE, UserName, Password));
Удаление учетных данных (когда пользователь нажимает кнопку выхода из приложения):
vault.Remove(_vault.Retrieve(VAULT_RESOURCE, UserName));
Это зависит от того, что вам нужно, если вам действительно нужно хранить пароли, вы должны использовать алгоритм двустороннего шифрования, такой как 3DES/RC2/Rijndael и т. Д.
Однако, если вам нужно только проверить правильность пароля, рекомендуется использовать одностороннюю функцию для хранения хэша.
При работе с конфиденциальными данными я действительно рекомендую шифровать / хэшировать их, даже если вы используете Windows 8. Шифрование означает дополнительные издержки, но в большинстве случаев вы не заметите разницу в скорости.
Было бы лучше написать свой собственный алгоритм Custom / Lite? Как охранник я советую против этого. Люди проводят годы, тестируя, совершенствуясь и пытаясь найти дыры в существующих алгоритмах. Те, что выжили, поэтому довольно хороши.
Вы можете зашифровать так:
public static string EncodePassword(string password)
{
byte[] bytes = Encoding.Unicode.GetBytes(password);
byte[] inArray = HashAlgorithm.Create("SHA1").ComputeHash(bytes);
return Convert.ToBase64String(inArray);
}
При проверке пользовательского ввода вы также добавляете его в этот метод и проверяете его на совпадение.
В случае данных, которые вы помещаете в XML (например), которые вы хотите зашифровать / расшифровать, вы можете использовать RijndaelManaged.
-Edit1-
Пример: если у вас есть маленький экран входа в систему (ShowDialog), вы можете сделать это следующим образом:
private void settings_Click(object sender, RoutedEventArgs e)
{
Login log = new Login(); //login window
log.ShowDialog(); //show the login window
string un = log.userName.Text; //the user input from the username field
string pw = log.passWord.Password; //the userinput from the password input
if (EncodePassword(un) == Properties.Settings.Default.adminUsername && EncodePassword(pw) == Properties.Settings.Default.adminPassword) //in my case, i stored it in the app settings, but this could also be somewhere else.
{
//login was correct
//do something
}
else
{
//login was not correct
}
}