c# - AesManaged 的​​密码学设置和 secret 管理

标签 c# .net security encryption aes

我正在实现一种共享 secret 加密方案,以实现适度安全的数据传输。当服务器配置客户端时,我可以生成一个或多个表示 key 的字符串。然后,客户端将使用此 secret 信息来加密数据,然后再将其发送到服务器。我希望确保共享 secret 尽可能强大且足以保证互操作性。

算法/类选择:似乎应该“坚持使用 AES,除非你有充分的理由不这样做”。 AesManaged 是一个不错的选择吗? Difference between symmetric crypto algorithms

设置和默认对象:我在系统的不同部分使用 .NET 4.0 和 .NET 4.5,并且可能会随着时间的推移进行升级。我找不到 KeySize 和 BlockSize 默认属性的文档,也找不到 IV 默认长度的文档。在 .NET 4.0 中,默认 key 大小为 32(字节,256 位),默认 IV 大小为 16(字节)。 BlockSize 和 FeedbackSize 均为 128(位)。模式为 CBC,填充为 PKCS7。我应该显式设置哪些属性,以及之后是否应该重新生成 key 和 IV?

[编辑:修复了 256 位以上和以下的问题。添加了问题。]

256 位 key 和 16 字节 IV 是否足以用于“非政府工作”?

我读到,256 位 key 容易受到某种攻击(我认为这不适用于我的情况)。有什么理由改用 128 位 key 吗?性能差异如何?

默认 key 大小大于 block 大小是否正常?

[编辑:完成。]

默认 key 和 IV 的强度:是否有任何理由使用 RNGCryptoServiceProvider.GetBytes() 或者 AesManaged 已经在这样做?

互操作性:我假设共享 key 由 key 和 IV(编码为 Base64 字符串)组成。从恢复的字节数组中设置 Key 和 IV 属性是否足以设置相关属性(例如 KeySize)?

是否可以推断出任何其他属性并保证一致,或者我应该为 key 生成、加密和解密显式设置它们?

key 生成代码:

AesManaged myAes = new AesManaged(); // use defaults
string keyString = Convert.ToBase64String(myAes.Key);
string ivString = Convert.ToBase64String(myAes.IV);

代码和上下文:我从这里借用了大量:http://msdn.microsoft.com/en-us/library/vstudio/system.security.cryptography.aesmanaged%28v=vs.100%29

最佳答案

AES(或 Rijndael)几乎是标准,在 Linux 上我想到的是河豚,但在 C# 中你想坚持使用免费的东西。

我建议设置这些值,而不是保留默认值。这保证了无声故障的可能性较小。当然,您必须确切知道您在做什么。但安全性在于了解您在做什么。

剩下的我只能说这些了。将 key 大小从 128 位增加到 192 或 256 位(或其他设置而不实际更改算法)相对容易,因此从通用值开始并使其发挥作用。但是,如果您可以使用相同的代码库获得更好的加密,为什么要满足于更少的加密呢?另一方面,安全性是一种妥协。没有什么是完全安全的,这完全取决于您愿意花多少钱。

我现在说的话不会让你高兴。共享的 secret 让你所有的努力都毫无用处。如果窃听者能够窃取 secret ,那么加密就完全没有用了。

对于存储的数据,这种选择可能没问题,只要您每次想要解密 block 时都要求提供 key ,并且永远不要将 secret 存储在磁盘上(就像 KeePassX 要求提供密码来打开 key 文件一样)。

对于移动数据(通过网络发送),非对称加密是必不可少的,除非您有其他方法来传达 secret 。也就是说,永远不要通过互联网发送 secret ,而是使用互联网外的方式(普通的旧邮件,可能是电话或面对面)。

如您所见,共享 secret 才是真正的问题。显而易见的解决方案是 SSL,但它是不对称的,并且 C# 实现非常不稳定,特别是对于可能在 mono/Linux/OpenSSL 上运行的多平台应用程序。如果你走那条路,请准备好迎接一 field 狱般的噩梦。

没有 SSL 或外部通信 channel 的互联网上真正可行的安全性?没有骰子。

根据您的用例,您可能希望避免将 secret 存储在字符串中。

如果涉及到生命或金钱,您想做的甚至不止这些。考虑用户可能将客户端安装在公共(public)计算机(例如网吧)上。查看SecureString以及增量散列字符的算法,但实际上从不将字符串存储在内存中。

编辑:

由于虚拟机管理内存和垃圾收集的方式以及虚拟内存的工作方式,您可能会面临公共(public) PC 上未使用的扇区可能包含纯文本密码的风险。当操作系统将虚拟内存交换到磁盘时,就会发生这种情况。 C# 中没有任何编程方法可以绝对确定它不会发生。在这些场景中,SecureString 和内存固定可帮助您保护 .NET 客户端(C# 和 VB)。

关于c# - AesManaged 的​​密码学设置和 secret 管理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25797405/

相关文章:

c# - Runspace Powershell 命令的 WSManConnectionInfo 和 PSCredential 作为另一个用户

.net - 通过cmd线或.NET的音频(标签?)信息?

php - 如何安全地存储我的用户密码?

javascript - 使用 AJAX 调用恢复 session

c# - 在 app.config 中获取 ConfigurationElement parent

c# - 通过objectset插入多条记录

c# - Entity Framework - 无法让 LEFT OUTER join 工作

.net - Ninject 的 NinjectHttpModule 导致 ASP.NET 数据绑定(bind)控件丢失数据

c# - WebBrowser.DrawToBitmap 留下白色像素

Linux 手动打开端口以及这样做的正当理由