C# AES的密码设置和秘密管理

C# AES的密码设置和秘密管理,c#,.net,security,encryption,aes,C#,.net,Security,Encryption,Aes,我正在为适度安全的数据传输实现一个共享秘密加密方案。当服务器设置客户端时,我可以生成一个或多个表示秘密的字符串。然后,客户端将使用此机密信息对数据进行加密,然后再将其发送到服务器。我希望确保共享秘密尽可能强,并且足以保证互操作性 算法/类选择:似乎应该“坚持AES,除非你有充分的理由不这么做。”AES管理是一个好的选择吗? 设置和默认对象:我在系统的不同部分使用.NET 4.0和.NET 4.5,可能会随着时间的推移而升级。我找不到KeySize和BlockSize的默认属性的文档,也找不到I

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

算法/类选择:似乎应该“坚持AES,除非你有充分的理由不这么做。”AES管理是一个好的选择吗?

设置和默认对象:我在系统的不同部分使用.NET 4.0和.NET 4.5,可能会随着时间的推移而升级。我找不到KeySize和BlockSize的默认属性的文档,也找不到IV的默认长度。在.NET 4.0中,默认密钥大小似乎是32(字节,256位),默认IV大小是16(字节)。块大小和反馈大小为128(位)。模式为CBC,填充为PKCS7。我应该显式地设置哪些属性,然后应该重新生成密钥和IV吗

[编辑:固定了256位上下。添加了问题。]

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

我已经读到256位密钥容易受到某种攻击(我认为这不适用于我的情况)。是否有理由改用128位密钥?性能差异是什么

默认密钥大小大于块大小是否正常

[编辑:完成。]

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

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

是否可以推断并保证同意任何其他属性,或者是否应该为密钥生成、加密和解密显式设置它们

密钥生成代码

AesManaged myAes = new AesManaged(); // use defaults
string keyString = Convert.ToBase64String(myAes.Key);
string ivString = Convert.ToBase64String(myAes.IV);
代码和上下文:我从这里大量借用:

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

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

剩下的我只能这样说。将密钥大小从128位增加到192位或256位(或者在不改变算法的情况下增加其他设置)相对容易,因此从通用值开始并使其工作。但是,如果您可以在相同的代码基础上实现更好的加密,为什么还要满足于更少的加密?另一方面,安全是一种妥协。没有什么是完全安全的,这完全取决于你愿意花多少钱

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

对于存储的数据,这种选择可能是可以的,只要您每次想要解密块时都要求密钥,并且从不将密钥存储在磁盘上(就像KeePassX要求密码来打开密钥文件一样)

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

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

在没有SSL或外部通信通道的情况下,通过Internet实现真正可行的安全性?没有骰子

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

如果涉及到生命或金钱,你想做的甚至不止这些。考虑用户可能将客户端安装在诸如网吧之类的公共计算机上。研究以增量方式散列字符而从不将字符串实际存储在内存中的算法

编辑:


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

32(字节,128位)
这是错误的。32字节=256位。16字节=128位。我想这种混乱是因为128位用32个十六进制字符表示。Oops。很抱歉。修正。如果我错了,请纠正我,@pid,但是如果你使用diffie-hellman密钥交换,你可以通过互联网发送秘密。它将防止攻击者在不逆转离散对数问题的情况下确定秘密。如果素数模较大,这是不可行的。Oh和AES不接受1024位密钥。可接受的AES密钥大小为128位、192位和256位。@SpencerGrantDoak是的,你说得对。我从未使用过ECDH,因此如果不建议您给出另一个答案,我必须同意您的意见,这将非常好。关于AES:是的,同样存在这些特定的键大小限制,但我打算传达一种通用的思维方式,而不是精确的实现。一如既往,欢迎所有帮助,感谢您的贡献: