我正在研究一个简单的实用程序来加密文件作为学习体验。 一切似乎工作正常,但我想知道如果我已安全地设置密钥/ IV /盐数据。Rijndael加密功能 - 密钥/ IV /盐设置
我注意到,当涉及到密码术时,大多数人似乎设想到一个工作环境,加载了一个恶意软件,该恶意软件由远程向导远程准备通过正在运行的应用程序/页面文件的内存来获取这些安全文件。
让我们假装你在一台干净的机器上,然后加密一些文件并关闭计算机。 我想知道的是,某人是否可以拿走你的硬盘,并使用我提出的代码检索文件的内容。
我最关心的攻击矢量是确保页面文件/文件缓存不可访问。 我也想确保使用的Key/IV系统不会使基于彩虹表/散列的攻击变得可行。
输入密码:使用设置为true的passwordchar值的文本框中输入
的密码。
只要在加密后正确删除字符串,我并不关心字符串在内存中。我读到使用SecureString在这一点上是毫无意义的,因为如果您的计算机上已经存在恶意软件,那么您可以轻松地在其上放置一个键盘记录器,这会导致其他一切无用。
private static string salt = "02341235XadfaDADFexA8932F7Dz3J3X";
我使用硬编码的32个字符的字符串给密码加盐。 (上面的字符串只是一个例子)
为了解决这个问题,它需要有人用十六进制编辑器反编译/查看.exe文件本身(我知道的东西很容易做到,但是额外的步骤)。
我曾考虑过这种盐是可编辑的,但我不知道如何安全地存储它。我认为加密你的盐有点荒谬,因为那样你就会遇到同样的问题,所以把它作为一个硬编码的字符串放在exe文件中看起来对我来说最有意义。
这种方式的工作方式是,如果你决定让你的密码“密码”,它实际上保存为“thepasswordfaDADFexA8932F7Dz3J3X”。
这里的主要关键是你总是有一个32个字符的密码,而不管你输入什么。
密钥和IV:
密钥和IV也盐腌如下。 这是我希望得到一些意见,因为说实话,我不是很确定它在做什么:
UnicodeEncoding UE = new UnicodeEncoding();
byte[] keysalt = UE.GetBytes("Xjafe231x42X423XadXCadfkhjeAdS"); //Another string of random characters hard coded in the exe
byte[] IVSodium = UE.GetBytes("83Xkda7l78Dkx85KdJazppoqq6SaxDs"); //Another string of random characters hard coded in the exe
byte[] key = new Rfc2898DeriveBytes(password, keysalt).GetBytes(32); //Derive the key using the password and salt
byte[] IV = new Rfc2898DeriveBytes(password, IVSodium).GetBytes(16); //Derive the IV using the password and salt
我主要在这里担心的是,IV基于关键。再次,我不确定这是否会导致任何问题,我希望你们可以让我知道是否有问题,它们是什么。
此外,这是另一种情况下,硬编码盐是一种不好的做法?这应该存储在加密文件中,如果是这样,它是否真的使它更安全?我应该让这个可编辑吗?
的加密流是使用使用关键字的设置:
using (FileStream fsCrypt = new FileStream(cryptFile, FileMode.Create))
{
using (RijndaelManaged RMCrypto = new RijndaelManaged())
{
using (CryptoStream cs = new CryptoStream(fsCrypt, RMCrypto.CreateEncryptor(key, IV), CryptoStreamMode.Write))
{
using (FileStream fsIn = new FileStream(inputFile, FileMode.Open))
{
byte[] buffer = new byte[4096]; //4096 is kind of arbitrary - better idea?
int data;
long bytesRead = 0;
while((data = fsIn.Read(buffer, 0, buffer.Length)) > 0)
{
bytesRead += data;
/////////////////////////////////////////
// Handle Aborts and Update Progress Bar
/////////////////////////////////////////
if (!caller.isClosing)
caller.Invoke((MethodInvoker)delegate {
caller.fileProgressBar.Value = ((int)(((double)bytesRead/totalBytes) * 100));
});
else
return false; //Encryption Aborted
/////////////////////////////////////////
cs.Write(buffer, 0, data);
fsIn.Close();
cs.Close();
fsCrypt.Close();
return true;
}
}
}
}
}
感谢您的时间和请让我知道,如果有设置键/ IV /盐更好的办法。 我认为,只要没有包含类似字符的IV和Key的数学问题,它就很可能足够安全。如果是这样,我是否也应该使用硬编码的IV?这似乎很奇怪。
请注意,我没有保存密码或任何类似的散列。密码不保存在任何地方。它只是用来生成密钥和IV。
谢谢你的时间。
编辑:下面是对未来的任何人推荐的更改。
请注意,这不是用胡椒 - 只是一个随机的盐,虽然这将是很容易的添加
byte[] salt = new byte[32]; //Create a 32 byte salt
rand.NextBytes(salt); //Fill it with random values (use RandomNumberGenerator rand = new RNGCryptoServiceProvider(); to be safe
byte[] IV = new byte[16]; //Create a 16 byte IV
rand.NextBytes(IV); //Fill it with random numbers
byte[] key = new Rfc2898DeriveBytes(password, salt).GetBytes(32); //Derive our Key by mixing our password with the salt
using (FileStream fsCrypt = new FileStream(cryptFile, FileMode.Create))
{
using (RijndaelManaged RMCrypto = new RijndaelManaged())
{
using (CryptoStream cs = new CryptoStream(fsCrypt, RMCrypto.CreateEncryptor(key, IV), CryptoStreamMode.Write))
{
using (FileStream fsIn = new FileStream(inputFile, FileMode.Open))
{
fsCrypt.Write(salt, 0, salt.Length); //Write our salt to the file
fsCrypt.Write(IV, 0, IV.Length); //Write our IV to the file
fsIn.CopyTo(cs); //Encrypt and Write
}
}
}
}
不要使用固定盐,盐的一点是如果密码重用,你不能说它被重用。盐不需要保密,只需将其附加到正在加密的文件的前面。 –
好的,那么直接把盐写入被加密文件的开始处?此外,盐在这里真的有必要吗?我没有散列任何东西。没有存储的密码。我想确保密码可以是任意长度,并且仍然可以使用算法,所以我知道它需要一定数量的字符长度。缺少硬编码或将随机字符附加到文件的开头(基本上是同一个东西,不是?)会影响任何内容吗?基本上,我可能会错误地将它称为盐来解释它。 – user1274820