C# 如何安全地处理 AES“密钥”和“IV”值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18324149/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to securely handle AES “Key” and “IV” values
提问by ChiYoung
If I use AES (System.Security.Cryptography) to simply encrypt and decrypt blob or memo fields in a SQL server, then where do I store the “Key” and “IV” values on the server? (File, Regkey, Dbase,...)
如果我使用 AES (System.Security.Cryptography) 来简单地加密和解密 SQL 服务器中的 blob 或 memo 字段,那么我应该将“密钥”和“IV”值存储在服务器上的什么位置?(文件、注册码、数据库、...)
And what with the protection of those AES “Key” and “IV” values?
那么如何保护这些 AES“密钥”和“IV”值呢?
The background question is more : If “they” hack the server and get the dbase... then probably they can get to the program that do the encryption stuff also (It's on the same server, can't help it)... and if "they" are very good, then they will notice where the “Key” and “IV” values are stored...(.NET 4.5 ILSPY) and everything can be decrypted again.
背景问题更多:如果“他们”入侵服务器并获得数据库……那么他们可能也可以访问执行加密工作的程序(它在同一台服务器上,无法帮助)……如果“他们”非常好,那么他们会注意到“密钥”和“IV”值的存储位置......(.NET 4.5 ILSPY)并且所有内容都可以再次解密。
Please advice? How do you all handle AES “Key” and “IV” value's?
请指教?你们都是如何处理AES“Key”和“IV”值的?
Ps: This is not about pwd fields... so, it's not about hashing... its pure data cryptography.
Ps:这不是关于密码字段......所以,它不是关于散列......它的纯数据密码学。
采纳答案by Syon
The IV has been thoroughly covered by the other answers, so I'll focus just on storing the key.
其他答案已经完全涵盖了 IV,因此我将只专注于存储密钥。
First...
第一的...
I can't except it could not be done on a single server at software level.
我不能除非它不能在软件级别的单个服务器上完成。
Anything done in software can be undone in software. You can encrypt, hide, and lock it in as many safes as you want, but your application still needs to be able to get access to the key. If your application has access, then someone with the same level of access as your application is able to get to it as well.
在软件中完成的任何事情都可以在软件中撤消。您可以根据需要将其加密、隐藏和锁定在任意数量的保险箱中,但您的应用程序仍然需要能够访问密钥。如果您的应用程序具有访问权限,那么与您的应用程序具有相同访问级别的人也可以访问它。
Developers have been dealing with this problem for a very long time and there is no silver bullet.
开发人员处理这个问题已经很长时间了,没有灵丹妙药。
This all is setup in a single server environment (application plus dbase), so I'm not able to send/retrieve the key to a second server. Also, in this “special” case I'm not able to encrypt the key by a machine-level or user-level RSA key container.
这一切都是在单个服务器环境(应用程序加 dbase)中设置的,因此我无法将密钥发送/检索到第二台服务器。此外,在这种“特殊”情况下,我无法通过机器级或用户级 RSA 密钥容器对密钥进行加密。
I can think of two possible solutions.
我可以想到两种可能的解决方案。
Option 1:
选项1:
Store the key on disk and, at the OS level, configure file access so that only the account your application is running under can read the file the key is contained in. The file could be a flat file, or an encrypted container that's protected by a password which your application knows (up to you to decide, but an encrypted container is better).
将密钥存储在磁盘上,并在操作系统级别配置文件访问权限,以便只有运行应用程序的帐户才能读取包含密钥的文件。该文件可以是平面文件,也可以是受保护的加密容器您的应用程序知道的密码(由您决定,但加密容器更好)。
Pros:
优点:
- Restarts without human intervention.
- 无需人工干预即可重新启动。
Cons:
缺点:
- You have to do OS security right and there is no room for error.
- An attacker with administrator access can get to the key.
- 您必须正确执行操作系统安全性,并且不允许出错。
- 具有管理员访问权限的攻击者可以获得密钥。
Another similar option to this would be to use DPAPIinstead of files for storing the key (as long as you're able to do this given your "special case"). This is an API built in to windows that utilizes the password for whatever windows account you (or your application) is running under to securely store data. Only the windows account that stored the data is able to retrieve it.
另一个类似的选择是使用DPAPI而不是文件来存储密钥(只要您能够在“特殊情况”下执行此操作)。这是一个内置于 Windows 的 API,它利用您(或您的应用程序)运行的任何 Windows 帐户的密码来安全地存储数据。只有存储数据的 Windows 帐户才能检索它。
One particularly nice feature of DPAPI is that, if an administrator resets a users password (via computer management), access to that users DPAPI data is lost. An attacker would need to compromise the actual account that was used to store the data in the first place without resetting the password.
DPAPI 的一个特别好的功能是,如果管理员重置用户密码(通过计算机管理),则无法访问该用户的 DPAPI 数据。攻击者首先需要破坏用于存储数据的实际帐户,而无需重置密码。
Option 2:
选项 2:
Require that a pass phrase be entered by a person at application start up and derive an encryption key from that pass phrase. Once you have the key, discard the pass phrase and retain the key in memory only.
要求用户在应用程序启动时输入通行短语并从该通行短语派生出加密密钥。获得密钥后,丢弃密码短语并将密钥仅保留在内存中。
Pros:
优点:
- The key is never on disk.
- Even if the server is rooted, getting to the key is not a simple task.
- 密钥永远不会在磁盘上。
- 即使服务器已root,获取密钥也不是一项简单的任务。
Cons:
缺点:
- Automated reboots are not possible.
- You'll likely have to share the pass phrase with anyone handling support.
- You need to keep in mind that data stored in memory maytransparently be written to disk in certain situations.
- 无法自动重新启动。
- 您可能必须与处理支持的任何人共享密码短语。
- 您需要记住,在某些情况下,存储在内存中的数据可能会透明地写入磁盘。
Or you could do a compromise between these two systems where, a pass phrase is initially used to derive the encryption key which is held in memory, and the key is temporarily written to disk or encrypted container whenever the application is gracefully restarted. When the restart is complete the application loads the key and then deletes it from temporary storage (and if necessary, be sure to overwrite the disk location where the key was stored so that it can't be recovered).
或者您可以在这两个系统之间进行折衷,其中,最初使用密码短语来派生保存在内存中的加密密钥,每当应用程序正常重新启动时,密钥就会临时写入磁盘或加密容器。重新启动完成后,应用程序加载密钥,然后将其从临时存储中删除(如有必要,请确保覆盖存储密钥的磁盘位置,以便无法恢复)。
回答by DavidN
Segregating your web server and db server would be helpful here. You want to lock down access (permissions-wise) to your encryption keys, and keep them in memory as SecureString. Can't do much more than that. Choose strong passwords and follow up-to-date security practices.
在这里隔离您的 Web 服务器和数据库服务器会有所帮助。您想锁定对加密密钥的访问(权限方面),并将它们作为 SecureString 保存在内存中。不能做更多。选择强密码并遵循最新的安全实践。
Here's a good post as well Where to Store Encryption Keys MVC Application
回答by Scott Chamberlain
The IV does not need to be kept as secret as the key, the only thing it serves to do is to make sure two of the exact same blobs encrypted with the same key produce two outputs that are totally different from each other (so you can't tell the same message was sent twice). Many encryption systems just make the IV the first bytes of the message.
IV 不需要像密钥一样保密,它唯一要做的就是确保使用相同密钥加密的两个完全相同的 blob 产生两个完全不同的输出(因此您可以'不要告诉同一个消息发送了两次)。许多加密系统只是将 IV 作为消息的第一个字节。
Encryption keys are a harder thing to manage, the best thing you can do is keep the database itself and the application separate so "If “they” hack the server and get the dbase" (Say a SQL injection attack lets them do a dump of the database's tables) they still can't decrypt the fields themselves.
加密密钥是一件更难管理的事情,你能做的最好的事情就是将数据库本身和应用程序分开,这样“如果“他们”入侵服务器并获取数据库”(假设 SQL 注入攻击让他们转储数据库的表)他们仍然无法自己解密字段。
回答by DarkWanderer
Rules of thumb are:
经验法则是:
- Key must be secret at all times (must not be anywhere near the database)
- IV must be different for each record.
- IV must be "indistinguishable from random" and unpredictable, preferably it must come from the same source as your AES keys; other option is to encrypt some value (different for each record) with a secret key.
- IV needs not to be secret
- 密钥必须始终保密(不得位于数据库附近的任何地方)
- 每条记录的 IV 必须不同。
- IV 必须“与随机无法区分”且不可预测,最好它必须与您的 AES 密钥来自同一来源;另一种选择是用密钥加密一些值(每条记录不同)。
- IV不需要保密
Hence, one scheme you can use is:
因此,您可以使用的一种方案是:
- Create a table with fields ID (unique, int), IV (unique, 16 bytes), Encrypted(variable bytes, NULLable)
- To write a new record into the database, create new unique IV and create a new record in the database with empty encrypted data (to prevent collisions)
- Encrypt the data with your secretkey and IV from step 2 (CBC or CTR mode - CTR is better) and update the record.
- 创建一个包含字段 ID(唯一,整数),IV(唯一,16 字节),加密(可变字节,可空)的表
- 要将新记录写入数据库,请创建新的唯一IV并在数据库中使用空加密数据创建新记录(以防止冲突)
- 与您的数据进行加密的秘密步骤2密钥和IV(CBC或CTR模式- CTR是更好),并更新记录。
Step two may be performed by taking the IV from previous record and encrypting it with the same secret key - AES's properties will make this an effectively random IV.
可以通过从先前记录中获取 IV 并使用相同的密钥对其进行加密来执行第二步 - AES 的属性将使其成为有效的随机 IV。
This will be as secure as you can get with AES - meaning CCA/CPA secure. The only thing it does not prevent is tampering
这将与 AES 一样安全 - 意味着 CCA/CPA 安全。它唯一不能防止的是篡改
回答by victorpacheco3107
If it is not much the encrypted information, periodically update the password and information from the records encrypted, it can be every day or every hour, for example.
如果加密信息不多,则从加密记录中定期更新密码和信息,例如可以每天或每小时。