我正在编写C#应用程序来管理密码。目前,我的数据库是.txt
文件,但我想创建几种方法来存储它。 .mdf
提交一个好方法吗?
我知道如何在.mdf
文件中管理sql数据库,但我不知道如何将Save As存储到用户选择的位置或如何再次加载到程序。
当然,它可以是任何不同的文件类型。我寻找最安全的方式来做到这一点。将来我将创建asp.net应用程序和Xamarin android应用程序来在几个平台上管理它。
@Edit 我将再次尝试解释这一点。检查一下:
用户执行程序。可以选择创建新数据库或加载现有数据库。 在创建模式下,用户可以设置数据库的类型。现在我只有一个和它的txt。 我想知道其他的,f.e。 .mdf,但我不知道如何在用户选择的位置保存.mdf文件。关于可能的扩展以及如何保护它的任何其他建议都表示赞赏。
我想将其存储如下:
登录|密码| linkForWebsite |
当然我会哈希所有内容,所以如果any1打开.txt文件,他什么都看不见。
对这个字符串进行散列的建议(不是md5。它必须是2路)也欢迎。
答案 0 :(得分:2)
根据我上面的评论,这里你可以做什么
您的应用程序将从List<SiteDetail>
网站详细信息
[Serializable()]
public class SiteDetail
{
public string Login{get; set;}
public string Password{get; set;}
public string Url{get; set;}
}
然后当您想要存储数据(保存)时,执行以下操作
public void Save(string filePath,List<SiteDetail> data)
{
Stream stream= File.Create(filePath);
BinaryFormatter serializer = new BinaryFormatter();
serializer.Serialize(stream, data);
stream.Close();
}
当您想要检索数据(阅读)时,请执行以下操作
public List<SiteDetail> Read(string filePath)
{
if (File.Exists(FileName))
{
Stream stream= File.OpenRead(filePath);
BinaryFormatter deserializer = new BinaryFormatter();
var details= (List<SiteDetail>)deserializer.Deserialize(stream);
stream.Close();
return details;
}
return null; // file not exists
}
用于加密您的数据,请查看本文Encrypting and Decrypting Data
如果您还有任何疑问,请继续
<强>被修改强>
如您在评论中提到的那样保存有关数据的元信息,您可以创建另一个名为meta.dat的文件(将存储另一个类[Version,Culture,.... etc]),或者您可以轻松地添加另一个名为SiteVersion
的类,如下所示
[Serializable()]
public class SiteVersion : SiteDetail // inherited from SiteDetail to store backup
{
public int Version{get; set;}
public string Culture{get; set;}
public DateTime CreatedOn{get; set;}
}
并且在SiteDetail
课程中,您可以添加List<SiteVersion>
属性,并且可以在进行任何更改时填写它,这样您就可以在文件中存储其版本历史记录的详细信息
[Serializable()]
public class SiteDetail
{
public string Login{get; set;}
public string Password{get; set;}
public string Url {get;set;}
public List<SiteVersion> Versions {get; set;}
}
希望它会帮助你
答案 1 :(得分:0)
如果您想在.txt文件中保存数据库,请遵循:
在特定路径上创建文本文件,例如(C:\ bkpDB.txt)
右键单击On(数据库名称) - &gt;选择(&#34;任务&#34;) - &gt;选择(&#34;导出数据&#34;) - &gt;选择&#34;下一步&#34; for&#34;欢迎页面&#34; - &GT;页面&#34;选择数据源&#34;:不要更改任何内容并转到下一页 - &gt;
Page&#34;选择一个目的地&#34;:[目的地:&#34;平面文件目的地&#34; ],[文件名:&#34; C:\ bkpDB.txt&#34; ],[检查&#34;第一个数据行中的列名称&#34; ]并且不要改变任何其他内容,选择&#34;下一步&#34;
Page&#34;指定表格复制或查询&#34;选择:&#34;从一个或多个表中复制数据&#34;选择&#34;下一步&#34;
Page&#34;配置平面文件目的地&#34;:选择表格和行和列分隔符选择&#34;下一步&#34;最后&#34;芬兰&#34;
如果您想从.txt文件加载数据库,请遵循:
使用您之前步骤填写的特定路径中的文本文件,例如(C:\ bkpDB.txt)
右键单击On(数据库名称) - &gt;选择(&#34;任务&#34;) - &gt;选择(&#34;导入数据&#34;) - &gt;选择&#34;下一步&#34; for&#34;欢迎页面&#34; - &GT;并转到下一页 - &gt;
Page&#34;选择一个数据源&#34;:[数据来源:&#34;平面文件来源&#34; ],[文件名:&#34; C:\ bkpDB.txt&#34; ],[检查&#34;第一个数据行中的列名称&#34; ]并且不要改变任何其他内容,选择&#34;下一步&#34;
Page&#34;选择目的地&#34;选择:选择您的数据库并选择&#34;下一步&#34;和&#34;芬兰&#34;
如果您想使用加密和解密密码,我建议您使用高级加密标准AES算法
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Web;
using System.Web.Mvc;
namespace MvcWebRole1.Controllers
{
public class AESController : Controller
{
//
// GET: /AES/
public ActionResult Index()
{
ViewData["Encrypted"] = TempData["TEncrypted"];
ViewData["Decrypted"] = TempData["TDecrypted"];
return View();
}
//Text is PlainText
//Key is Public Secret Key
[HttpPost]
public ActionResult Encryption(string Text, string Key)
{
// Convert String to Byte
byte[] MsgBytes = Encoding.UTF8.GetBytes(Text);
byte[] KeyBytes = Encoding.UTF8.GetBytes(Key);
// Hash the password with SHA256
//Secure Hash Algorithm
//Operation And, Xor, Rot,Add (mod 232),Or, Shr
//block size 1024
//Rounds 80
//rotation operator , rotates point1 to point2 by theta1=> p2=rot(t1)p1
//SHR shift to right
KeyBytes = SHA256.Create().ComputeHash(KeyBytes);
byte[] bytesEncrypted = AES_Encryption(MsgBytes, KeyBytes);
string encryptionText = Convert.ToBase64String(bytesEncrypted);
TempData["TEncrypted"] = encryptionText;
return RedirectToAction("Index");
}
public byte[] AES_Encryption(byte[] Msg, byte[] Key)
{
byte[] encryptedBytes = null;
//salt is generated randomly as an additional number to hash password or message in order o dictionary attack
//against pre computed rainbow table
//dictionary attack is a systematic way to test all of possibilities words in dictionary wheather or not is true?
//to find decryption key
//rainbow table is precomputed key for cracking password
// Set your salt here, change it to meet your flavor:
// The salt bytes must be at least 8 bytes. == 16 bits
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(Key, 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(Msg, 0, Msg.Length);
cs.Close();
}
encryptedBytes = ms.ToArray();
}
}
return encryptedBytes;
}
[HttpPost]
public ActionResult Decryption(string Text2, string Key2)
{
// Convert String to Byte
byte[] MsgBytes = Convert.FromBase64String(Text2);
byte[] KeyBytes = Encoding.UTF8.GetBytes(Key2);
KeyBytes = SHA256.Create().ComputeHash(KeyBytes);
byte[] bytesDecrypted = AES_Decryption(MsgBytes, KeyBytes);
string decryptionText = Encoding.UTF8.GetString(bytesDecrypted);
TempData["TDecrypted"] = decryptionText;
return RedirectToAction("Index");
}
public byte[] AES_Decryption(byte[] Msg, byte[] Key)
{
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(Key, 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(Msg, 0, Msg.Length);
cs.Close();
}
decryptedBytes = ms.ToArray();
}
}
return decryptedBytes;
}
}
}
&#13;
在视图部分(&#34;索引&#34;):
@{
ViewBag.Title = "Index";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>Encryption And Decryption</h2>
<div style="color:red;" id="EncryptedText">Encrypted Message: @ViewData["Encrypted"]</div>
<br />
<div style="color:red;" id="DecryptedText">Decrypted Message: @ViewData["Decrypted"]</div>
<br />
@using(Html.BeginForm("Encryption", "AES", FormMethod.Post))
{
<label id="lbk1">Key:</label><input name="Key" id="Key" type="text" />
<br />
<label id="lbk2">Message:</label><input name="Text" id="Text" type="text" />
<br />
<input id="btnEncryption" type="submit" value="Encryption" />
<br />
<br />
}
@using(Html.BeginForm("Decryption", "AES", FormMethod.Post))
{
<label id="lbk4">Enter Same Key:</label><input name="Key2" id="Key2" type="text" />
<br />
<label id="lbk5">Enter Encrypted Message:</label><input name="Text2" id="Text2" type="text" />
<br />
<input id="btnDecryption" type="submit" value="Decryption" />
}
<br />
&#13;
编辑:(按用户从应用程序创建数据库(&#34; .mdf&#34;)
要在应用程序内创建数据库,您可以使用其他数据库中的存储过程,并在用户想要创建数据库(.mdf)并传递数据库名称等值时调用此sp。
CREATE PROC dbo.dbbase
AS
DECLARE @db varchar(50), @sql varchar(1000)
IF DB_ID(@db) IS NULL
SELECT @SQL = 'CREATE DATABASE ' + @db +
' ON (NAME = ' + @db + '_Data, FILENAME = ''C:\UserName\' + @db + '.mdf'')' +
' LOG ON (NAME = ' + @db + '_Log, FILENAME = ''C:\UserName\' + @db + '.mdf'')'
EXEC(@sql)
GO
&#13;
我希望它适合你。