在大多数情况下,我需要使用密码加密字符串,然后将其发送/保存到某个地方。后来我想用密码解密它。我不是在加密核导弹代码或医疗患者数据!理想的情况是有 2 个函数:
string Encrypt(string plainText, string password);
string Decrypt(string cipherText, string password);
我查看了 crypto documentation ... 好家伙!所以我尝试自己编写上述调用的代码( see a proof of concept using AES Managed and Base64 encoded payload )。我不是加密货币专家,为什么我必须编写代码?我可能做错了什么......
- 要从密码中派生 key ,接口(interface)需要加盐。我可以使用密码作为盐吗?我可以将静脉注入(inject)液作为盐重复使用吗?也许不是,但我不想添加另一个参数。
- 我可以使用固定 IV 吗?相同的明文和密码应该会产生不同的密文,因此我必须在有效负载中提供用于解密的 IV。
- 我可以使用盐作为 key 并保持 IV 恒定吗?感觉不对。
- 创建一个随机数并从中派生 IV 和 key 盐是一种有效的方法吗?
- 如果 .Net 支持 GCM 模式,我还会遇到这个问题吗?
最佳答案
.NET 加密 API 公开了一个通用加密库,其中包含实现加密算法的面向对象方法。当然,要使用这些算法和算法实现,您需要对密码学有很好的掌握,而这是您目前所缺乏的。
这个通用库需要实现现有的各种协议(protocol)。通常,单个算法不能满足特定的用例(在您的情况下使用密码加密字符串,返回不同的字符串)。因此,需要选择或设计一个能够满足该用例的协议(protocol)。该协议(protocol)可以例如定义容器格式,例如 CMS 或 PGP,例如可用于加密电子邮件(用例)。
您直接尝试应用加密算法来解决您的用例。那是行不通的。您需要一个预制的协议(protocol),最好带有预制的 API。
请注意,有许多不同的用例、许多不同的协议(protocol),甚至有更多关于如何正确创建和实现这些协议(protocol)的意见。例如,Libsodium/NaCl 定义了一种名为 SecretBox
的小型容器格式,它确实需要您完成一些工作。
但是,在 NaCl 之上实现 TLS 当然是相当不可能的,因为功能/算法不存在。同样,.NET 需要一个像 .NET API 这样的通用加密库,以便其他人实现他们的协议(protocol)。
因此,要么您必须硬着头皮尝试创建自己的协议(protocol),要么采用现有的协议(protocol)并根据有根据的猜测它是否安全(希望该协议(protocol)已被审查/更新了几次)。远离没有其他贡献者的单人项目(例如未经审查的许多示例代码)。
对于您自己的协议(protocol),是的,存在诸如未将盐与密文一起存储之类的错误。您需要一个随机的(或者至少是唯一的)盐来确保安全,因此重复使用密码肯定不安全。不要让它本身成为一个个人项目,要么借用协议(protocol),要么对其进行审查。
好的,那么快点:
- To derive the key from the password the interface requires a salt. Can I use the password as salt? Can I re-use the IV as salt? Maybe not, but I don't want to add another parameter.
不,盐必须是唯一的,最好是随机的;密码/盐组合应该是唯一的(它不应该重复,即使在时间上也不应该重复,或者在不同的域上也不应该重复)。
- Can I use a fixed IV? Same plaintext and password should result in different cipher text, so I have to supply the IV for decryption in the payload.
不可以,除非键每次都改变值(见上文)。对于 CBC,IV 应该是不可预测的,除非您每次都使用新的 key 。
- Can I use a salt for the key and keep the IV constant instead? Feels wrong.
这是可能的,只要你不重复加盐。
- Creating a nonce and deriving IV and key salt from it is a valid approach?
这取决于非常具体的细节。换句话说,如果您不完全知道自己在做什么,我就不会尝试。
- If .Net would support the GCM mode would I still have this problems?
当然,从某种意义上说,如果您使用 GCM,您的问题会更糟,因为使用具有相同 key 和 IV 的 GCM 完全被破坏了。
请记住,GCM 只是一种算法,而不是协议(protocol),它本身无法解决您的用例。
关于c# - 为什么 .Net Framework 的加密如此复杂?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56126016/