如何为加密算法创建加密密钥?

我想使用.Net Security命名空间中提供的加密算法,但是我试图了解如何生成密钥,例如AES算法需要256位,即16字节密钥,以及一些初始化向量,这也是几个字节。

  1. 我可以在Key和IV中使用任何值的组合吗? 例如Key和IV中的所有零都有效吗? 我知道算法的细节做了很多xors,所以零不会有任何好处,但这些算法是否有任何限制?

  2. 或者我是否必须使用某些程序生成密钥并将其永久保存在某处?

我希望在加密后将数据存储在数据库中,安全配置文件数据,如用户名,密码,电话号码等,密钥将仅供连接字符串中提到的数据库用户使用,并且可供管理员使用。

如果您使用加密来交换数据,那么您将需要一个密钥交换协议,但您不需要自己创建一个,而是使用一个现成的TLS或SSL。

如果使用加密来存储数据,则使用CryptGenRandom (或其.net等效的RandomNumberGenerator.GetBytes)生成IV 并将其保存在文档中(明确,无需保护IV)。 您永远不会记下密钥,密钥由用户提供。 通常,您使用CryptDeriveKey或其.Net等效PasswordDeriveKey.CryptDeriveKey从密码短语派生密钥。

更新

要在数据库中存储仅供用户和管理员使用的密钥,您需要使用3个密钥:

  • 一个用数据加密(称之为DK键)
  • 一个用户密钥加密DK密钥(称之为英国)
  • 一个管理员密钥加密DK密钥(称之为AK)

理论上,您使用DK加密数据,然后使用UK加密DK并保存,并使用AK加密DK并保存。 这样,用户可以再次使用UK来解密DK然后解密数据,并且管理员可以使用AK来解密DK然后解密数据。 最大的问题是系统始终是自动化的,因此系统需要访问管理员密钥,这意味着管理员不是真正的管理密钥,而是系统密钥(它不能用于非密钥的目的)例如,否认)。

作为一个提醒,了解IV是什么或如何使用C#中的AES以及加密算法如何工作将在解决此类问题时获得正确的0(零)牵引力。 问题永远不是IV和密钥使用,问题始终是关键配置。 对于实际的加密操作,只需使用数据库中的内置支持,请参阅SQL Server中的加密 。 我可以轻易地说,您需要的唯一设施是TDE( 透明数据加密 ),以防止意外丢失媒体。

你真的应该以正确的方式做到这一点:)

1)使用安全生成的随机IV
2)使用安全生成的随机密钥
3)不要使用ECB模式 – 永远

AesManaged aes = new AesManaged(); aes.GenerateKey(); aes.GenerateIV(); 

上面的代码将正确,安全地为您生成随机IV和随机密钥。

听起来你需要阅读Rfc2898DeriveBytes类。

 Rfc2898DeriveBytes.GetBytes(); 

它有一个方法(上面),允许你定制在对称加密算法上输入.Key和.IV属性的字节数组的大小,只需输入一个int值。 MS官方70-536书建议通过划分KeySize属性/ 8来以编程方式进行此操作。

即TripleDes或AESManaged。 无论您使用什么,算法本身都会有一些需要先满足的预先要求。 即满足关键尺寸条件。 RunTime会自动为您填充属性和字段等最佳和最强大的值。 但IV和Key需要来自你。 您可以通过以下方式执行以下操作:

 RijndaelManaged myAlg = new RiRijndaelManaged(); byte[] salt = Encoding.ASCII.GetBytes("Some salt value"); Rfc2898DeriveBytes key = new Rfc2898DeriveBytes("some password", salt); myAlg.Key = key.GetBytes( myAlg.KeySize / 8); myAlg.IV = key.GetBytes( myAlg.BlockSize / 8); // myAld should now fully set-up. 

上面你可以通过编程方式看到我的意思,因为它应该为你完成所有这一切,而你甚至不必为满足它的预先要求而睁着眼睛。

Microsoft 70-536一书指出.Key属性期望您提供的字节数组以字节为单位而不是位。 RFC类以字节为单位,其中算法KeySize属性以位为单位工作。 1字节= 8位。 你能看出这是怎么回事……? 这应该可以让您了解为什么上面的示例代码以它的方式完成! 我研究了它,它对我来说非常有意义!

上面的答案应该允许您使用提供的密码和两端都可以是硬代码的静态salt值创建算法对象。 您唯一需要做的就是担心如何确保将存储在.Key和.IV中的字节数组安全地传输到收件人,以便能够成功解密您加密的邮件。 通过安全地重建相同的算法对象。

OBTW:

AESManaged有一个keyize req’:128Bits = 16 Bytes !!! (8 * 8 = 64,64位/每字节8位= 8字节)因此

64 * 2 = 128Bit,8 * 2,==> 16bytes密钥大小!

256Bit = 32Bytes !!!!


根据70-536官方培训套件书,Aes仅限于128位大小的密钥。 例如,256位,192和128键大小可以与Rijndael类一起使用。


另一方面,您可以完全忘记所有废话并简单地使用.GenerateKey和GenerateIV方法来节省您解决预共享和约定密码和静态盐值的所有麻烦。 您唯一关心的是找出存储和检索密钥和IV字节数组的方法。 二进制格式化程序? 。

生成特定长度的随机字母/hex代码。

此函数(取自此处 )返回特定长度的随机密钥:

 private static string CreateSalt(int size) { //Generate a cryptographic random number. RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider(); byte[] buff = new byte[size]; rng.GetBytes(buff); // Return a Base64 string representation of the random number. return Convert.ToBase64String(buff); } 

使用System.Security.Cryptography.RandomNumberGenerator生成随机字节:

 var rnd = new System.Security.Cryptography.RandomNumberGenerator.Create(); var key = new byte[50]; rnd.GetBytes(key); 

这真的取决于你对钥匙的要求。

如果密钥是由计算机生成的(并且可以是任何随机值),我通常会使用几个GUID的SHA256。 这与你没有硬件随机数生成器的情况一样随机。

你可以使用全0的键,但显然它不会很安全。