C# 正确存储电子邮件密码
C# Properly storing an E-mail Password
我正在创建一个将使用 outlook 帐户发送电子邮件的消息传递应用程序。但是,我不确定在用户计算机上存储电子邮件密码的正确步骤。假设我有以下代码:
SmtpClient SmtpServer = new SmtpClient("smtp.live.com");
var mail = new MailMessage();
mail.From = new MailAddress("youremail@hotmail.com");
mail.To.Add("to@gmail.com");
mail.Subject = "Test Mail - 1";
mail.IsBodyHtml = true;
string htmlBody;
htmlBody = "Write some HTML code here";
mail.Body = htmlBody;
SmtpServer.Port = 587;
SmtpServer.UseDefaultCredentials = false;
SmtpServer.Credentials = new System.Net.NetworkCredential("youremail@hotmail.com", "password");
SmtpServer.EnableSsl = true;
SmtpServer.Send(mail);
显然,我不希望 "password" 在我的应用程序中存储为字符串。 ideal/proper 将密码存储在用户计算机上以便我可以将其读入我的应用程序并将其传递给 NetworkCredential 构造函数的解决方案是什么?
我读完了 here, and here。第一个link建议将它存储在文件或注册表中,不知道如何将它存储在注册表中。我如何将其正确存储在文件中?
最好的方法是序列化凭据,然后对其进行加密,然后将加密的字节写入文件。反转该过程将有助于检索数据。
首先,创建一个classAES.cs:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace AES_Password_Storer
{
public static class AES
{
public static byte[] AES_Encrypt(byte[] bytesToBeEncrypted, byte[] passwordBytes)
{
byte[] encryptedBytes = null;
// Set your salt here, change it to meet your flavor:
// The salt bytes must be at least 8 bytes.
byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
using (MemoryStream ms = new MemoryStream())
{
using (RijndaelManaged AES = new RijndaelManaged())
{
AES.KeySize = 256;
AES.BlockSize = 128;
var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
AES.Key = key.GetBytes(AES.KeySize / 8);
AES.IV = key.GetBytes(AES.BlockSize / 8);
AES.Mode = CipherMode.CBC;
using (var cs = new CryptoStream(ms, AES.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(bytesToBeEncrypted, 0, bytesToBeEncrypted.Length);
cs.Close();
}
encryptedBytes = ms.ToArray();
}
}
return encryptedBytes;
}
public static byte[] AES_Decrypt(byte[] bytesToBeDecrypted, byte[] passwordBytes)
{
byte[] decryptedBytes = null;
// Set your salt here, change it to meet your flavor:
// The salt bytes must be at least 8 bytes.
byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
using (MemoryStream ms = new MemoryStream())
{
using (RijndaelManaged AES = new RijndaelManaged())
{
AES.KeySize = 256;
AES.BlockSize = 128;
var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
AES.Key = key.GetBytes(AES.KeySize / 8);
AES.IV = key.GetBytes(AES.BlockSize / 8);
AES.Mode = CipherMode.CBC;
using (var cs = new CryptoStream(ms, AES.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(bytesToBeDecrypted, 0, bytesToBeDecrypted.Length);
cs.Close();
}
decryptedBytes = ms.ToArray();
}
}
return decryptedBytes;
}
}
}
接下来,创建一个classCredentials.cs:N.B。 - 现在我创建了凭据 class 以仅保存一个用户的凭据。您可以通过创建列表来调整它以容纳多个。
[Serializable]
public class Credentials
{
public string Email { get; set; }
public string Password { get; set; }
}
接下来,进行加密(将数据写入文件):
XmlSerializer xs = new XmlSerializer(typeof(Credentials));
MemoryStream ms = new MemoryStream();
xs.Serialize(ms, new Credentials() { Email = "email@service.com", Password = "passworduser" });
byte[] encrypted = AES.AES_Encrypt(ms.ToArray(), Encoding.UTF8.GetBytes("encryptionkey")); //This is the key
File.WriteAllBytes("passwordfile.pwd", encrypted);
现在,解密:
MemoryStream ms = new MemoryStream(AES.AES_Decrypt(File.ReadAllBytes("passwordfile.pwd"), Encoding.UTF8.GetBytes("encryptionkey"))); //Here goes the key
XmlSerializer xs = new XmlSerializer(typeof(Credentials));
Credentials c = (Credentials)xs.Deserialize(ms);
// This 'c' contains your credentials.
现在加解密的代码中,有一个字符串"encryptionkey"。这是这一切的主要关键。您可以(事实上,应该)更改它并将其保存在安全的地方(在您的应用程序中)。
我正在创建一个将使用 outlook 帐户发送电子邮件的消息传递应用程序。但是,我不确定在用户计算机上存储电子邮件密码的正确步骤。假设我有以下代码:
SmtpClient SmtpServer = new SmtpClient("smtp.live.com");
var mail = new MailMessage();
mail.From = new MailAddress("youremail@hotmail.com");
mail.To.Add("to@gmail.com");
mail.Subject = "Test Mail - 1";
mail.IsBodyHtml = true;
string htmlBody;
htmlBody = "Write some HTML code here";
mail.Body = htmlBody;
SmtpServer.Port = 587;
SmtpServer.UseDefaultCredentials = false;
SmtpServer.Credentials = new System.Net.NetworkCredential("youremail@hotmail.com", "password");
SmtpServer.EnableSsl = true;
SmtpServer.Send(mail);
显然,我不希望 "password" 在我的应用程序中存储为字符串。 ideal/proper 将密码存储在用户计算机上以便我可以将其读入我的应用程序并将其传递给 NetworkCredential 构造函数的解决方案是什么?
我读完了 here, and here。第一个link建议将它存储在文件或注册表中,不知道如何将它存储在注册表中。我如何将其正确存储在文件中?
最好的方法是序列化凭据,然后对其进行加密,然后将加密的字节写入文件。反转该过程将有助于检索数据。
首先,创建一个classAES.cs:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace AES_Password_Storer
{
public static class AES
{
public static byte[] AES_Encrypt(byte[] bytesToBeEncrypted, byte[] passwordBytes)
{
byte[] encryptedBytes = null;
// Set your salt here, change it to meet your flavor:
// The salt bytes must be at least 8 bytes.
byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
using (MemoryStream ms = new MemoryStream())
{
using (RijndaelManaged AES = new RijndaelManaged())
{
AES.KeySize = 256;
AES.BlockSize = 128;
var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
AES.Key = key.GetBytes(AES.KeySize / 8);
AES.IV = key.GetBytes(AES.BlockSize / 8);
AES.Mode = CipherMode.CBC;
using (var cs = new CryptoStream(ms, AES.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(bytesToBeEncrypted, 0, bytesToBeEncrypted.Length);
cs.Close();
}
encryptedBytes = ms.ToArray();
}
}
return encryptedBytes;
}
public static byte[] AES_Decrypt(byte[] bytesToBeDecrypted, byte[] passwordBytes)
{
byte[] decryptedBytes = null;
// Set your salt here, change it to meet your flavor:
// The salt bytes must be at least 8 bytes.
byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
using (MemoryStream ms = new MemoryStream())
{
using (RijndaelManaged AES = new RijndaelManaged())
{
AES.KeySize = 256;
AES.BlockSize = 128;
var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
AES.Key = key.GetBytes(AES.KeySize / 8);
AES.IV = key.GetBytes(AES.BlockSize / 8);
AES.Mode = CipherMode.CBC;
using (var cs = new CryptoStream(ms, AES.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(bytesToBeDecrypted, 0, bytesToBeDecrypted.Length);
cs.Close();
}
decryptedBytes = ms.ToArray();
}
}
return decryptedBytes;
}
}
}
接下来,创建一个classCredentials.cs:N.B。 - 现在我创建了凭据 class 以仅保存一个用户的凭据。您可以通过创建列表来调整它以容纳多个。
[Serializable]
public class Credentials
{
public string Email { get; set; }
public string Password { get; set; }
}
接下来,进行加密(将数据写入文件):
XmlSerializer xs = new XmlSerializer(typeof(Credentials));
MemoryStream ms = new MemoryStream();
xs.Serialize(ms, new Credentials() { Email = "email@service.com", Password = "passworduser" });
byte[] encrypted = AES.AES_Encrypt(ms.ToArray(), Encoding.UTF8.GetBytes("encryptionkey")); //This is the key
File.WriteAllBytes("passwordfile.pwd", encrypted);
现在,解密:
MemoryStream ms = new MemoryStream(AES.AES_Decrypt(File.ReadAllBytes("passwordfile.pwd"), Encoding.UTF8.GetBytes("encryptionkey"))); //Here goes the key
XmlSerializer xs = new XmlSerializer(typeof(Credentials));
Credentials c = (Credentials)xs.Deserialize(ms);
// This 'c' contains your credentials.
现在加解密的代码中,有一个字符串"encryptionkey"。这是这一切的主要关键。您可以(事实上,应该)更改它并将其保存在安全的地方(在您的应用程序中)。