2010-03-15 165 views
4

我正在使用由Mark Brittingham編寫的以下類,用於我的應用程序中的雙向AES加密。我將如何去修改它來添加一個salt字符串?AES雙向加密加鹽

using System; 
using System.Data; 
using System.Security.Cryptography; 
using System.IO; 


public class SimpleAES 
{ 
    // Change these keys 
    private byte[] Key = { 123, 217, 19, 11, 24, 26, 85, 45, 114, 184, 27, 162, 37, 112, 222, 209, 241, 24, 175, 144, 173, 53, 196, 29, 24, 26, 17, 218, 131, 236, 53, 209 }; 
    private byte[] Vector = { 146, 64, 191, 111, 23, 3, 113, 119, 231, 121, 2521, 112, 79, 32, 114, 156 }; 


    private ICryptoTransform EncryptorTransform, DecryptorTransform; 
    private System.Text.UTF8Encoding UTFEncoder; 

    public SimpleAES() 
    { 
     //This is our encryption method 
     RijndaelManaged rm = new RijndaelManaged(); 

     //Create an encryptor and a decryptor using our encryption method, key, and vector. 
     EncryptorTransform = rm.CreateEncryptor(this.Key, this.Vector); 
     DecryptorTransform = rm.CreateDecryptor(this.Key, this.Vector); 

     //Used to translate bytes to text and vice versa 
     UTFEncoder = new System.Text.UTF8Encoding(); 
    } 

    /// -------------- Two Utility Methods (not used but may be useful) ----------- 
    /// Generates an encryption key. 
    static public byte[] GenerateEncryptionKey() 
    { 
     //Generate a Key. 
     RijndaelManaged rm = new RijndaelManaged(); 
     rm.GenerateKey(); 
     return rm.Key; 
    } 

    /// Generates a unique encryption vector 
    static public byte[] GenerateEncryptionVector() 
    { 
     //Generate a Vector 
     RijndaelManaged rm = new RijndaelManaged(); 
     rm.GenerateIV(); 
     return rm.IV; 
    } 


    /// ----------- The commonly used methods ------------------------------  
    /// Encrypt some text and return a string suitable for passing in a URL. 
    public string EncryptToString(string TextValue) 
    { 
     return ByteArrToString(Encrypt(TextValue)); 
    } 

    /// Encrypt some text and return an encrypted byte array. 
    public byte[] Encrypt(string TextValue) 
    { 
     //Translates our text value into a byte array. 
     Byte[] bytes = UTFEncoder.GetBytes(TextValue); 

     //Used to stream the data in and out of the CryptoStream. 
     MemoryStream memoryStream = new MemoryStream(); 

     /* 
     * We will have to write the unencrypted bytes to the stream, 
     * then read the encrypted result back from the stream. 
     */ 
     #region Write the decrypted value to the encryption stream 
     CryptoStream cs = new CryptoStream(memoryStream, EncryptorTransform, CryptoStreamMode.Write); 
     cs.Write(bytes, 0, bytes.Length); 
     cs.FlushFinalBlock(); 
     #endregion 

     #region Read encrypted value back out of the stream 
     memoryStream.Position = 0; 
     byte[] encrypted = new byte[memoryStream.Length]; 
     memoryStream.Read(encrypted, 0, encrypted.Length); 
     #endregion 

     //Clean up. 
     cs.Close(); 
     memoryStream.Close(); 

     return encrypted; 
    } 

    /// The other side: Decryption methods 
    public string DecryptString(string EncryptedString) 
    { 
     return Decrypt(StrToByteArray(EncryptedString)); 
    } 

    /// Decryption when working with byte arrays.  
    public string Decrypt(byte[] EncryptedValue) 
    { 
     #region Write the encrypted value to the decryption stream 
     MemoryStream encryptedStream = new MemoryStream(); 
     CryptoStream decryptStream = new CryptoStream(encryptedStream, DecryptorTransform, CryptoStreamMode.Write); 
     decryptStream.Write(EncryptedValue, 0, EncryptedValue.Length); 
     decryptStream.FlushFinalBlock(); 
     #endregion 

     #region Read the decrypted value from the stream. 
     encryptedStream.Position = 0; 
     Byte[] decryptedBytes = new Byte[encryptedStream.Length]; 
     encryptedStream.Read(decryptedBytes, 0, decryptedBytes.Length); 
     encryptedStream.Close(); 
     #endregion 
     return UTFEncoder.GetString(decryptedBytes); 
    } 

    /// Convert a string to a byte array. NOTE: Normally we'd create a Byte Array from a string using an ASCII encoding (like so). 
    //  System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding(); 
    //  return encoding.GetBytes(str); 
    // However, this results in character values that cannot be passed in a URL. So, instead, I just 
    // lay out all of the byte values in a long string of numbers (three per - must pad numbers less than 100). 
    public byte[] StrToByteArray(string str) 
    { 
     if (str.Length == 0) 
      throw new Exception("Invalid string value in StrToByteArray"); 

     byte val; 
     byte[] byteArr = new byte[str.Length/3]; 
     int i = 0; 
     int j = 0; 
     do 
     { 
      val = byte.Parse(str.Substring(i, 3)); 
      byteArr[j++] = val; 
      i += 3; 
     } 
     while (i < str.Length); 
     return byteArr; 
    } 

    // Same comment as above. Normally the conversion would use an ASCII encoding in the other direction: 
    //  System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding(); 
    //  return enc.GetString(byteArr);  
    public string ByteArrToString(byte[] byteArr) 
    { 
     byte val; 
     string tempStr = ""; 
     for (int i = 0; i <= byteArr.GetUpperBound(0); i++) 
     { 
      val = byteArr[i]; 
      if (val < (byte)10) 
       tempStr += "00" + val.ToString(); 
      else if (val < (byte)100) 
       tempStr += "0" + val.ToString(); 
      else 
       tempStr += val.ToString(); 
     } 
     return tempStr; 
    } 
} 

回答

3

我已經使用了帶有哈希密碼的salt字符串,但沒有使用雙向加密。所以,採取這個建議與穀物...

添加鹽字符串與您的密鑰和載體(這些應該真的存儲在其他地方,而不是硬編碼在你的班級,但現在,這將工作)。

private string salt = "[email protected]"; 

用它EncryptToString,添加到文本值:

return ByteArrToString(Encrypt(TextValue + salt)); 

然後在DecryptString其刪除:

return Decrypt(StrToByteArray(EncryptedString)).Replace(salt, string.Empty); 
3

我最近發現馬克的代碼稍加修改它。我通過在字節數組的開始和結尾添加密碼隨機數來放入一些鹽。鹽的大小可以用恆定的「鹽」來改變。所以相同的文本在加密時幾乎不會看起來相同。然而,正如雙向加密一樣,如果有人看到你的密碼,他就知道你的密鑰,你的載體和鹽在哪裏......

using System; 
using System.Security.Cryptography; 
using System.IO; 

public class SimpleAES 
{ 
    // Change these keys 
    private byte[] Key = { 123, 217, 19, 11, 24, 26, 85, 45, 114, 184, 27, 162, 37, 112, 222, 209, 241, 24, 175, 144, 173, 53, 196, 29, 24, 26, 17, 218, 131, 236, 53, 209 }; 
    private byte[] Vector = { 146, 64, 191, 111, 23, 3, 113, 119, 231, 121, 2521, 112, 79, 32, 114, 156 }; 
    private const int Salt = 8; 

    private ICryptoTransform EncryptorTransform, DecryptorTransform; 
    private System.Text.UTF8Encoding UTFEncoder; 

    public SimpleAES() 
    { 
     //This is our encryption method 
     RijndaelManaged rm = new RijndaelManaged(); 

     //Create an encryptor and a decryptor using our encryption method, key, and vector. 
     EncryptorTransform = rm.CreateEncryptor(this.Key, this.Vector); 
     DecryptorTransform = rm.CreateDecryptor(this.Key, this.Vector); 

     //Used to translate bytes to text and vice versa 
     UTFEncoder = new System.Text.UTF8Encoding(); 
    } 

    /// -------------- Two Utility Methods (not used but may be useful) ----------- 
    /// Generates an encryption key. 
    static public byte[] GenerateEncryptionKey() 
    { 
     //Generate a Key. 
     RijndaelManaged rm = new RijndaelManaged(); 
     rm.GenerateKey(); 
     return rm.Key; 
    } 

    /// Generates a unique encryption vector 
    static public byte[] GenerateEncryptionVector() 
    { 
     //Generate a Vector 
     RijndaelManaged rm = new RijndaelManaged(); 
     rm.GenerateIV(); 
     return rm.IV; 
    } 


    /// ----------- The commonly used methods ------------------------------ 
    /// Encrypt some text and return a string suitable for passing in a URL. 
    public string EncryptString(string TextValue) 
    { 
     return (TextValue != "") ? Convert.ToBase64String(Encrypt(TextValue)) : ""; 
    } 

    /// Encrypt some text and return an encrypted byte array. 
    public byte[] Encrypt(string TextValue) 
    { 
     //Translates our text value into a byte array. 
     Byte[] pepper = UTFEncoder.GetBytes(TextValue); 
     // add salt 
     Byte[] salt = new byte[Salt]; 
     RNGCryptoServiceProvider crypto = new RNGCryptoServiceProvider(); 
     crypto.GetNonZeroBytes(salt); 
     Byte[] bytes = new byte[2 * Salt + pepper.Length]; 
     System.Buffer.BlockCopy(salt, 0, bytes, 0, Salt); 
     System.Buffer.BlockCopy(pepper, 0, bytes, Salt, pepper.Length); 
     crypto.GetNonZeroBytes(salt); 
     System.Buffer.BlockCopy(salt, 0, bytes, Salt + pepper.Length, Salt); 

     //Used to stream the data in and out of the CryptoStream. 
     MemoryStream memoryStream = new MemoryStream(); 

     /* 
     * We will have to write the unencrypted bytes to the stream, 
     * then read the encrypted result back from the stream. 
     */ 
     #region Write the decrypted value to the encryption stream 
     CryptoStream cs = new CryptoStream(memoryStream, EncryptorTransform, CryptoStreamMode.Write); 
     cs.Write(bytes, 0, bytes.Length); 
     cs.FlushFinalBlock(); 
     #endregion 

     #region Read encrypted value back out of the stream 
     memoryStream.Position = 0; 
     byte[] encrypted = new byte[memoryStream.Length]; 
     memoryStream.Read(encrypted, 0, encrypted.Length); 
     #endregion 

     //Clean up. 
     cs.Close(); 
     memoryStream.Close(); 

     return encrypted; 
    } 

    /// The other side: Decryption methods 
    public string DecryptString(string EncryptedString) 
    { 
     return (EncryptedString != "") ? Decrypt(Convert.FromBase64String(EncryptedString)) : ""; 
    } 

    /// Decryption when working with byte arrays.  
    public string Decrypt(byte[] EncryptedValue) 
    { 
     #region Write the encrypted value to the decryption stream 
     MemoryStream encryptedStream = new MemoryStream(); 
     CryptoStream decryptStream = new CryptoStream(encryptedStream, DecryptorTransform, CryptoStreamMode.Write); 
     decryptStream.Write(EncryptedValue, 0, EncryptedValue.Length); 
     decryptStream.FlushFinalBlock(); 
     #endregion 

     #region Read the decrypted value from the stream. 
     encryptedStream.Position = 0; 
     Byte[] decryptedBytes = new Byte[encryptedStream.Length]; 
     encryptedStream.Read(decryptedBytes, 0, decryptedBytes.Length); 
     encryptedStream.Close(); 
     #endregion 
     // remove salt 
     int len = decryptedBytes.Length - 2 * Salt; 
     Byte[] pepper = new Byte[len]; 
     System.Buffer.BlockCopy(decryptedBytes, Salt, pepper, 0, len); 
     return UTFEncoder.GetString(pepper); 
    } 
}