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

C# 如何为加密算法创建加密密钥?,c#,.net,security,encryption,C#,.net,Security,Encryption,我想使用.Net安全命名空间中可用的加密算法,但我试图了解如何生成密钥,例如AES算法需要256位、16字节的密钥和一些初始化向量,也就是几个字节 我可以在Key和IV中使用任意值的组合吗?e、 g.键和IV中的所有零是否有效?我知道算法的细节,它执行大量的异或运算,所以零不会有任何好处,但是这些算法有任何限制吗 或者我必须使用某种程序生成密钥并将其永久保存在某个地方吗 我想在加密后将数据存储在数据库中,安全配置文件数据(如用户名、密码、电话号码等)和密钥将仅对连接字符串中提到的数据库用户和管理

我想使用.Net安全命名空间中可用的加密算法,但我试图了解如何生成密钥,例如AES算法需要256位、16字节的密钥和一些初始化向量,也就是几个字节

  • 我可以在Key和IV中使用任意值的组合吗?e、 g.键和IV中的所有零是否有效?我知道算法的细节,它执行大量的异或运算,所以零不会有任何好处,但是这些算法有任何限制吗

  • 或者我必须使用某种程序生成密钥并将其永久保存在某个地方吗


  • 我想在加密后将数据存储在数据库中,安全配置文件数据(如用户名、密码、电话号码等)和密钥将仅对连接字符串中提到的数据库用户和管理员可用。

    生成特定长度的随机字母/十六进制代码

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

    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);
    }
    

    这真的取决于你打算用钥匙做什么

    如果密钥是由计算机生成的(并且可以是任意随机值),我通常使用两个guid的SHA256。这大约是你在没有硬件随机数生成器的情况下得到的随机数


    您可以对所有0使用密钥,但显然它不会非常安全

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

    如果您使用加密来存储数据,那么您可以使用(或其.net等价物)生成IV,并将其保存在文档中(很明显,不需要保护IV)。您从不写下密钥,密钥由用户提供。通常使用或其.Net等效项从密码短语派生密钥

    更新

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

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


    作为提示,了解什么是IV或如何使用C#中的AES,以及密码算法如何工作,将使您在解决此类问题时获得0(零)的牵引力。问题永远不是使用什么IV和密钥,问题始终是密钥配置。对于实际的加密操作,只需使用数据库的内置支持,请参阅。我可以很容易地说,您需要的唯一功能是TDE(),以防止意外丢失介质。

    使用
    系统、安全、加密、随机数生成器来生成随机字节:

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

    你真的应该用正确的方法:)

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


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

    听起来您需要读入Rfc2898DeriveBytes类

    Rfc2898DeriveBytes.GetBytes();
    
    它有一个方法(如上所述),允许您通过输入一个int值来定制输入对称加密算法的.Key和.IV属性的字节数组的大小。MS官方的70-536手册建议按语法将KeySize属性/8分开

    即三倍或三倍。无论您使用什么,算法本身都会有一些需要先满足的预需求。即满足关键尺寸条件。运行时将自动为您填充属性和字段等最佳和最强的值。但是静脉注射和钥匙需要来自你。这说明了如何执行以下操作:

    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值创建算法对象,该静态salt值可以是两端的硬代码。您需要做的唯一一件事就是担心如何确保存储在.Key和.IV中的字节数组安全地传输到收件人,以便能够成功解密您加密的消息。通过安全地重建相同的算法对象

    OBTW:

    AESManaged有一个keysize请求:128位=16字节!!! (8*8=64,每字节64位/8位=8字节)因此

    64*2=128位,8*2,==>16字节密钥大小

    256Bit=32字节


    根据70-536官方培训工具包,Aes的密钥大小仅限于128位。例如,256位、192位和128位密钥大小可用于Rijndael类


    另一方面,你可以完全忘记那些废话,只需使用.GenerateKey和GenerateIV方法,就可以省去整理预先共享和约定的通行证的所有麻烦
    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.