2017-04-06 98 views
1
public string Encrypt(string Code) 
{ 
    string result = string.Empty; 
    byte[] encryptResult = null; 
    var CodeInByte = Encoding.ASCII.GetBytes(Code); 

    try 
    { 
     using (MemoryStream memo = new MemoryStream()) 
     { 
      using (RijndaelManaged AES = new RijndaelManaged()) 
      { 
       AES.KeySize = KeySize; 
       AES.BlockSize = BlockSize; 

       var key = new Rfc2898DeriveBytes(CodeInByte, salt, 1000); 
       AES.Key = key.GetBytes(AES.KeySize/8); 
       AES.IV = key.GetBytes(AES.BlockSize/8); 

       AES.Mode = CipherMode.CBC; 

       using (var encrypt = new CryptoStream(memo, AES.CreateEncryptor(), CryptoStreamMode.Write)) 
       { 
        encrypt.Write(CodeInByte, 0, CodeInByte.Length); 
        encrypt.Close(); 
       } 

       encryptResult = memo.ToArray(); 
      } 
     } 

     result = Convert.ToBase64String(encryptResult); 
     return result; 
    } 
    catch (Exception err) 
    { 
     MsgCode = 99; 
     MsgDesc = err.Message; 
     return string.Empty; 
    }    
} 

这只是一个简单的AES从字符串Rfc2898DeriveBytes的输出取决于什么以及应如何处理盐?

我想问点加密方法,生成密钥,在

var key = new Rfc2898DeriveBytes(CodeInByte, salt, 1000); 

当从输入字符串生成的密钥,或者它只是一个随机生成的字节数组?

和,是盐需要是静态的或不

+1

密钥是从字符串和salt生成的,迭代计数也是影响结果和运行时间的算法的参数。盐不需要是静态的,但是如果你使用不同的盐,你会得到一个不同的密钥,所以在解密方面需要和给定的加密方法相同。 –

+1

盐必须是随机的。不要使用静态盐,因为这会使密码具有确定性,因此不会在语义上安全。观察密文的攻击者可以确定何时之前发送了相同的消息前缀。盐不是秘密的,所以你可以把它和密文一起发送。通常,它只是在密文前面加上,然后在解密之前切掉。应该按照与初始化载体(IV)完全相同的方式处理盐。 –

回答

3

作为documentation on MSDN表明:

Rfc2898DeriveBytes通过调用需要密码,其盐,和迭代计数,然后产生密钥GetBytes方法。

换句话说,它将使用您提供的输入参数来导出字节。如果你给它不同的参数,派生的密钥将会不同。如果你给它相同的参数,它会产生相同的字节。

对称加密算法(如AES)需要一个固定长度的密钥 - 在这种情况下,AES128需要16个字节。但是,您不希望强制密码的长度是固定的,因为这样可以更容易地进行攻击。例如,您也可能需要比可行密码长得多的密钥 - 例如,AES256需要32字节密钥。最后,密码通常是字母数字的,可能有一些符号,而加密密钥由字节组成,范围可以从0x00-0xFF,如果您使加密密钥为32个字符的ASCII密码,那么您会相当小的范围因为可打印的ASCII字符范围远小于0x00-0xFF。

由于这个原因,您想要从给定的密码派生出加密密钥,这样您就可以获得所需确切长度的强密钥。这就是Rfc2898DeriveBytes进来的地方。

相关问题