Как я могу зашифровать пользовательские настройки (например, пароли) в моем приложении?
Я хочу предоставить пользователю возможность сохранять личные данные в зашифрованном виде. Это может быть тривиально или, возможно, уже было задано, но я не могу найти пример простого в использовании способа шифрования/дешифрования пароля.
Мне действительно не нужен супермагистральный нерушимый пароль. Мне просто нужно, чтобы пароль был как трудно сломать.
Я видел несколько вопросов msdn и SO, но не нашел что-то для использования.
Ответы
Ответ 1
David, я думал, что ваш ответ был отличным, но я думал, что это будет более методы расширения. Это позволит использовать такой синтаксис, как:
string cypherText;
string clearText;
using (var secureString = "Some string to encrypt".ToSecureString())
{
cypherText = secureString.EncryptString();
}
using (var secureString = cypherText.DecryptString())
{
clearText = secureString.ToInsecureString();
}
Здесь обновленный код:
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Security;
using System.Security.Cryptography;
using System.Text;
public static class SecureIt
{
private static readonly byte[] entropy = Encoding.Unicode.GetBytes("Salt Is Not A Password");
public static string EncryptString(this SecureString input)
{
if (input == null)
{
return null;
}
var encryptedData = ProtectedData.Protect(
Encoding.Unicode.GetBytes(input.ToInsecureString()),
entropy,
DataProtectionScope.CurrentUser);
return Convert.ToBase64String(encryptedData);
}
public static SecureString DecryptString(this string encryptedData)
{
if (encryptedData == null)
{
return null;
}
try
{
var decryptedData = ProtectedData.Unprotect(
Convert.FromBase64String(encryptedData),
entropy,
DataProtectionScope.CurrentUser);
return Encoding.Unicode.GetString(decryptedData).ToSecureString();
}
catch
{
return new SecureString();
}
}
public static SecureString ToSecureString(this IEnumerable<char> input)
{
if (input == null)
{
return null;
}
var secure = new SecureString();
foreach (var c in input)
{
secure.AppendChar(c);
}
secure.MakeReadOnly();
return secure;
}
public static string ToInsecureString(this SecureString input)
{
if (input == null)
{
return null;
}
var ptr = Marshal.SecureStringToBSTR(input);
try
{
return Marshal.PtrToStringBSTR(ptr);
}
finally
{
Marshal.ZeroFreeBSTR(ptr);
}
}
}
Ответ 2
Ниже приводится примерно так же просто, как и вы, предполагая, что вы действительно хотите, чтобы вы могли шифровать/расшифровывать строку и хранить ее на диске. Обратите внимание, что это не использует пароль, он использует контекст безопасности зарегистрированного пользователя System.Security.Cryptography.DataProtectionScope.CurrentUser для защиты данных.
public class SecureIt
{
static byte[] entropy = System.Text.Encoding.Unicode.GetBytes("Salt Is Not A Password");
public static string EncryptString(System.Security.SecureString input)
{
byte[] encryptedData = System.Security.Cryptography.ProtectedData.Protect(
System.Text.Encoding.Unicode.GetBytes(ToInsecureString(input)),
entropy,
System.Security.Cryptography.DataProtectionScope.CurrentUser);
return Convert.ToBase64String(encryptedData);
}
public static SecureString DecryptString(string encryptedData)
{
try
{
byte[] decryptedData = System.Security.Cryptography.ProtectedData.Unprotect(
Convert.FromBase64String(encryptedData),
entropy,
System.Security.Cryptography.DataProtectionScope.CurrentUser);
return ToSecureString(System.Text.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;
}
}
Затем для шифрования строки:
var clearText = "Some string to encrypt";
var cypherText = SecureIt.EncryptString( SecureIt.ToSecureString( clearText));
И чтобы впоследствии расшифровать:
var clearText = SecureIt.ToInsecureString( SecureIt.DecryptString(cypherText));
Ответ 3
Для моей цели я изменяю Jesse C. Slicer, чтобы не использовать SecureString
, поскольку для меня не важно защищать память. Мне просто нужно сериализовать зашифрованные строки. Чтобы этот рабочий проект должен был иметь ссылку на System.Security
(не только с использованием инструкции).
public static class StringSecurityHelper
{
private static readonly byte[] entropy = Encoding.Unicode.GetBytes("5ID'&mc %[email protected]%n!G^ fiVn8 *tNh3eB %rDaVijn!.c b");
public static string EncryptString(this string input)
{
if (input == null)
{
return null;
}
byte[] encryptedData = ProtectedData.Protect(Encoding.Unicode.GetBytes(input), entropy, DataProtectionScope.CurrentUser);
return Convert.ToBase64String(encryptedData);
}
public static string DecryptString(this string encryptedData)
{
if (encryptedData == null)
{
return null;
}
try
{
byte[] decryptedData = ProtectedData.Unprotect(Convert.FromBase64String(encryptedData), entropy, DataProtectionScope.CurrentUser);
return Encoding.Unicode.GetString(decryptedData);
}
catch
{
return null;
}
}
}
И использовать его:
string cypherText = "My string".EncryptString();
string clearText = cypherText.DecryptString();