Rijndael 密码功能 - Key/IV/Salt 设置 [英] Rijndael Cryptography Function - Key/IV/Salt Setup

查看:84
本文介绍了Rijndael 密码功能 - Key/IV/Salt 设置的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个简单的实用程序来加密文件,作为一种学习体验.似乎一切正常,但我想知道我是否安全地设置了 Key/IV/Salt 数据.

I'm working on a simple utility to encrypt files as a learning experience. Everything seems to be working fine, but I'm wondering if I have setup the Key/IV/Salt data securely.

我注意到,在谈到密码学时,大多数人似乎都在设想一个装有恶意软件的工作环境,该环境由远程向导操纵,准备潜入正在运行的应用程序/页面文件的内存中以获取这些安全文件.

I have noticed that when it comes to cryptography most people seem to envision a working environment that is loaded with malware manned by a wizard remotely ready to dive through the memory of a running application/page file to get at these secure files.

让我们假设您在一台干净的机器上,您加密了一些文件并关闭了计算机.我想知道的是,是否有人可以使用我提出的代码获取您的硬盘驱动器并检索文件的内容.

Let's pretend that you're on a clean machine and you encrypt some files and turn off your computer. What I want to know is whether or not someone can take your hard drive and retrieve the contents of the files using the code I have proposed.

我最关心的攻击媒介是确保页面文件/文件缓存不可访问.我还想确保所使用的 Key/IV 系统不会使基于彩虹表/哈希的攻击变得可行.

The attack vector I am most concerned with is ensuring that the page files/file caches are inaccessible. I also want to make sure that the Key/IV system used is not going to make a rainbow table/hash based attack feasible.

输入密码:

密码是使用文本框输入的,passwordchar 值设置为 true.

The password is entered using a text box with the passwordchar value set to true.

我并不真正关心字符串是否在内存中,只要它在加密后被正确删除即可.我读到在这一点上使用 SecureString 有点毫无意义,因为如果您的计算机上已经有恶意软件,那么您可以轻松地在那里安装一个键盘记录器,从而使其他所有内容都变得无用.

I'm not really concerned with the string being in memory as long as it is properly removed after the encryption. I read that using SecureString is kind of pointless at this point because if you have malware on your computer already, you could just as easily have a keylogger on there which renders everything else useless.

private static string salt = "02341235XadfaDADFexA8932F7Dz3J3X";

我使用硬编码的 32 个字符的字符串添加密码.(上面的字符串只是一个例子.)

I salt the password using a hard coded 32 character string. (The above string is just an example.)

要解决这个问题,需要有人使用十六进制编辑器反编译/查看 .exe 文件本身(我知道这很容易做到,但仍然需要一个额外的步骤).

To get at it, it will require someone to decompile/view the .exe file itself with a hex editor (something that I know if very easy to do, but an extra step nonetheless).

我已经考虑过将此盐设为可编辑,但我不确定如何安全地存储它.我认为加密你的盐有点荒谬,因为那样你会遇到同样的问题等,所以将它作为硬编码字符串留在 exe 本身似乎对我来说最有意义.

I have considered making this salt editable, but I'm not sure how I could securely store it. I think it's a little ridiculous to encrypt your salt because then you will have the same issue etc, so just leaving it as a hard coded string inside the exe itself seems to make the most sense to me.

这种工作方式是,如果您决定将密码设为thepassword",它实际上会保存为thepasswordfaDADFexA8932F7Dz3J3X".

The way this works is if you decide to make your password "thepassword", it is actually saved as "thepasswordfaDADFexA8932F7Dz3J3X".

这里的主要关键是,无论您输入什么,您始终都有一个 32 个字符的密码.

The main key here is that you always have a 32 character password, regardless of what you enter.

钥匙和 IV:

Key 和 IV 也加盐如下.这就是我想要得到的一些意见,因为老实说我不完全确定它在做什么:

The Key and IV are also salted as follows. This is what I wanted to get some input on, because to be honest I'm not entirely sure what it's doing:

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 是基于密钥的.同样,我不确定这是否会导致任何问题,我希望你们可以让我知道是否有问题,它们是什么.

My main concern here is that the IV is based on the key. Again, I'm not sure if this will cause any issues and I was hoping you guys could let me know if there are issues, what they are.

此外,这是另一种对盐进行硬编码是不好的做法的情况吗?是否应该将其存储在加密文件中,如果是,是否真的使其更安全?我也应该将其设为可编辑吗?

Also, is this another scenario where hard coding the salt is a bad practice? Should this be stored in the encrypted file, and if so, does it really make it more secure? Should I make this editable as well?

使用 using 关键字设置加密流:

The crypto streams are setup using the using keyword:

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;
                }
            }
        }
    }
}

感谢您的时间,如果有更好的方法来设置 Key/IV/Salt,请告诉我.我认为只要包含相似字符的 IV 和 Key 没有数学问题,它很可能是足够安全的.如果是这样,我是否也应该使用硬编码的 IV?这看起来很奇怪.

Thanks for your time and please let me know if there is a better way to setup the Key/IV/Salt. I think that it is most likely secure enough as long as there is not a mathematical issue with the IV and Key containing similar characters. If so, should I use a hard coded IV as well? That seems weird.

请注意,我没有保存密码的哈希值或类似的内容.密码不会保存在任何地方.它只是用来生成Key和IV.

Note that I'm not saving a hash of the password or anything like that. The password is not saved anywhere. It is just used to generate the Key and the 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
            }
        }
    }
}

推荐答案

盐有两个用途:

  1. 防止彩虹表攻击(如果应用正确,它确实);
  2. 防止相同的密码生成相同的密码哈希.

要做到这一点,盐需要是 8 到 16 个字节(不是字符)的随机数据,与密码哈希一起存储.像您一样使用静态散列会破坏散列的两个目的.

To do this the salt needs to be 8 to 16 bytes (not characters) of random data, stored with the password hash. Using a static hash as you do defeats both purposes of the hash.

如果您需要字符串,请使用 base 64 对盐和密码哈希进行编码.如果需要,您可以在调用密码哈希函数之前将静态数据(有时称为胡椒")添加到盐中.如果攻击者无法轻易读取程序数据,这可能会增加一些安全性.

If you need strings, use base 64 to encode the salt and password hash. If you want you can add static data (sometimes called "pepper") to the salt before calling the password hash function. This may add some security if the program data cannot be easily read by an attacker.

你永远不应该自己直接混合盐和密码;Rfc2898DeriveBytes(它是 PBKDF2 的实现)已经混合了两者.您也不应该存储密码,也不应该向其附加任何数据.PBKDF2 可以处理任何大小的输入,因此它不添加任何功能.

You should never directly mix the salt and the password yourself; the Rfc2898DeriveBytes (which is an implementation of PBKDF2) already mixes the two. You should also never store the password, nor should you have to append any data to it. PBKDF2 can handle any size of input, so it doesn't add any functionality.

现在可以从 PBKDF2 函数中获取 IV(使用 GetBytes).但是有一个问题,这很可能会使 PBKDF2 函数的初始迭代次数加倍,这会消耗 CPU 时间并降低对攻击者的优势.最好只生成一个随机 IV 并将其作为密文的前缀.

Now the IV can be taken from the PBKDF2 function (using GetBytes). There is however a problem, it's likely that this will double the initial amount of iterations of PBKDF2 function, which costs CPU time and reduces the advantage over an attacker. It's probably better to just generate a random IV and prefix it to the ciphertext.

所以最后你应该存储 salt |四 |密文,然后使用salt |胡椒作为盐并计算您的密钥,然后使用计算的密钥和IV进行加密/解密.

So in the end you should store salt | IV | ciphertext, then use salt | pepper as salt and calculate your key, then encrypt/decrypt using the calculated key and IV.

这篇关于Rijndael 密码功能 - Key/IV/Salt 设置的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆