我正在尝试创建一些包装并简单地使用.NET加密库类的类。
但如果我让呼叫者只提供密码,并且我自动生成盐和IV,那么我似乎需要将盐和IV与我的加密数据一起存储。 (这是因为我被告知我不应该使用重复的IV,如果调用者必须生成并跟踪不同的盐和IV,我的代码就不会很简单。)
理想情况下,我的加密数据会尽可能紧凑。但这会给我的加密结果增加相当多的字节,特别是如果我只加密少量数据,如单个字节。
我的问题是:
有没有办法减少加密数据的大小而不会让我的课程更多地使用?
任何人都可以在这里看到我的想法中的任何其他缺陷吗?
答案 0 :(得分:1)
您可以使用随机盐并从中生成密钥和IV。执行此操作的最佳方法是首先使用基于密码的密钥派生函数或PBKDF生成密钥种子。对于C#PBKDF2,在Rfc2898DeriveBytes
中实现可能是最简单的选择。你需要至少8个字节的盐和一个高迭代次数。
好的,所以现在你有一个密钥种子,你需要从中生成一个密钥。为此,您需要基于密钥的密钥派生函数或KBKDF。最新的一个是HKDF(在这种情况下,您只需要HKDF提取精确)。但是,KBKDF在加密库中非常罕见,因此您需要一些时间来实现它。
如果找不到足够好的图书馆,那么你可以选择KDF1 as specified on this page。只需将“密钥”和“IV”的ASCII编码字符串用作 OtherInfo ,并将计数器设置为设置为零的四个字节。结果是key = Hash(key seed | 00 00 00 00 | "key")
和IV = Hash(key seed | 00 00 00 00 | "IV")
。这里|
表示连接。如果你有太多的字节,只需使用结果中的最左边的。 SHA-1,SHA-256和SHA-512都可以,但我建议使用一个具有足够输出位的特定键 - SHA-256可能最有意义。
一旦有了密钥和IV,就可以使用任何一种加密方法。为了最小化开销,您可以使用基于CTR的加密。请注意,如果中间人是可能的(即任何传输协议),那么也需要有一个身份验证标记。
所以你有它:只有8个字节的开销,除非你也需要身份验证标签。你不应该做的是使用静态密钥或IV。静态密钥或IV都不被认为是安全的。