C# 为什么.Net Framework的加密如此复杂?

C# 为什么.Net Framework的加密如此复杂?,c#,.net,cryptography,aes,C#,.net,Cryptography,Aes,在大多数情况下,我需要用密码加密字符串,然后将其发送/保存到某个地方。以后我想用密码解密它。我没有加密核导弹代码或医疗病人数据!理想情况下有两种功能: 字符串加密(字符串明文、字符串密码); 字符串解密(字符串密文、字符串密码); 我看了一下。。。哦,孩子!因此,我尝试自己编写上述调用()。我不是密码专家,为什么我要编写密码?我可能做错了什么 要从密码派生密钥,接口需要salt。我可以把密码用作salt吗?我可以重复使用静脉注射作为盐吗?也许不是,但我不想再添加一个参数 我能用固定静脉输液器吗

在大多数情况下,我需要用密码加密字符串,然后将其发送/保存到某个地方。以后我想用密码解密它。我没有加密核导弹代码或医疗病人数据!理想情况下有两种功能:

字符串加密(字符串明文、字符串密码);
字符串解密(字符串密文、字符串密码);
我看了一下。。。哦,孩子!因此,我尝试自己编写上述调用()。我不是密码专家,为什么我要编写密码?我可能做错了什么

  • 要从密码派生密钥,接口需要salt。我可以把密码用作salt吗?我可以重复使用静脉注射作为盐吗?也许不是,但我不想再添加一个参数
  • 我能用固定静脉输液器吗?相同的明文和密码应该会产生不同的密码文本,因此我必须在有效负载中提供用于解密的IV
  • 我可以用盐做钥匙并保持IV恒定吗?感觉不对
  • 创建一个nonce并从中派生IV和key salt是一种有效的方法吗
  • 如果.Net支持GCM模式,我还会有这个问题吗

  • NET crypto API公开了一个通用加密库,其中包含实现加密算法的面向对象方法。当然,要使用这些算法和算法实现,您需要很好地掌握密码学,这是您目前所缺乏的

    这个通用库需要实现现有的各种协议。通常单个算法不能满足特定的用例(在您的情况下,使用密码加密字符串,返回不同的字符串)。因此,需要选择或设计一个能够满足该用例的协议。例如,该协议可以定义一种容器格式,如CMS或PGP,可用于加密电子邮件(用例)

    您直接尝试应用加密算法来解决您的用例。那是行不通的。您需要一个预先制定的协议,最好是带有预先制定的API


    请注意,有许多不同的用例,许多不同的协议,甚至更多关于如何正确创建和实现这些的意见。例如,libnadium/NaCl定义了一种称为
    SecretBox
    的小型容器格式,它确实占用了您的一些工作

    然而,在NaCl之上实现TLS当然是不可能的,因为功能/算法并不存在。同样,.NET需要一个像.NET API一样的通用加密库,以便其他人实现他们的协议


    因此,要么你必须对项目符号进行字节运算,并尝试创建自己的协议,要么你使用一个现有的协议,并对其是否安全进行有根据的猜测(希望该协议已经被审查/更新了几次)。远离没有其他贡献者的单人项目(就像许多没有审查的示例代码)

    对于您自己的协议,是的,存在一些错误,例如不使用密文存储盐。您需要一个随机的(或者至少是唯一的)salt来确保安全,重复使用密码肯定是不安全的。不要让它自己变成一个单人项目,要么借用协议,要么让人审查


    好的,那么快:

  • 要从密码派生密钥,接口需要salt。我可以把密码用作salt吗?我可以重复使用静脉注射作为盐吗?也许不是,但我不想再添加一个参数
  • 不,盐必须是唯一的,最好是随机的;密码/salt组合应该是唯一的(它不应该重复,甚至不应该在时间上重复,也不应该在不同的域上重复)

  • 我能用固定静脉输液器吗?相同的明文和密码应该会产生不同的密码文本,因此我必须在有效负载中提供用于解密的IV
  • 否,除非该键每次都更改值(参见上文)。对于CBC,IV应该是不可预测的,除非每次都使用新密钥

  • 我可以用盐做钥匙并保持IV恒定吗?感觉不对
  • 这是可能的,只要你不重复盐

  • 创建一个nonce并从中派生IV和key salt是一种有效的方法吗
  • 这取决于非常具体的细节。换句话说,如果你不知道自己在做什么,我不会尝试

  • 如果.Net支持GCM模式,我还会有这个问题吗
  • 当然,从某种意义上说,如果你使用GCM,你的问题会更糟,因为使用同一把钥匙和IV的GCM是完全坏掉的



    记住,GCM只是一个算法,而不是一个协议,它不能单独解决您的用例。

    完全正确的问题。这些API将非常有用,我认为它们应该存在。加密API感觉有点恶心。1.0中的不同.NETAPI由不同的团队完成。大多数都很好,但框架的某些方面不是。您可以在corefx存储库中的GitHub上提出此建议。@MarcGravel固有的复杂性相当有限。例如,您可以使用AES-GCM制作一个非常安全和通用的身份验证加密原语。一次调用
    byte[]Encrypt(byte[]数据,byte[]密钥,byte[]authTag)
    就足够了。用户仍然必须了解一些事情,但误用的可能性相当有限。“没有理由.NET Framework会让事情变得如此困难。@MarcGravel还有类似的库,它们的目标是创建难以误用且具有非常简单API的原语。NET中的加密有很多人为的复杂性。这就像ADO.NET一样,在大多数情况下,您都需要EF或Dapper。要执行查询吗?呼叫查询。没有打开和配置很多对象,也没有运行读卡器。@usr同意,我听到了;在这里,您的ADO.NET比较可能是一个非常好的比较:必要的复杂性与不必要的复杂性;让步一点;但是(撇开不谈)。。。我认为你不能相信tho