2016年4月20日 星期三

C# RFC 2898 加密

使用 Security 類別中的 RFC 2898 規範之加密:



說明:

  1. Salt 加鹽 (RNGCrypto Services Provider) 系統自動產生
  2. Iterator 迭代次數 (增加加密次數,增加複雜度,同時也增加運算效能時間)
  3. Password (你手中掌握的加密Password)
  4. Data (要加密的資料)
  5. TripleDES (Data Encryption Standard) 進行三次對稱加密
  6. IV 向量 (矩陣)

先取得系統的鹽 (Salt):

// Create a byte array to hold the random value. 
byte[] salt = new byte[8];
using (RNGCryptoServiceProvider rngCsp = new RNGCryptoServiceProvider()){
    // Fill the array with a random value.
    rngCsp.GetBytes(salt);
}

//要顯示出來可以使用 StringBuilder
StringBuilder SALT_STRING = new StringBuilder();
foreach(byte v in salt){
    SALT_STRING.Append(v);
}

要進行加密,將獲得的鹽、自己的密碼加入以下變數中:

private void doEncrypt(object sender, EventArgs e){
    int Iterations = 1000; //迭代次數
    string EncryptData = "你要加密的資料";
    string KEY_PASSWORD = "你的密碼 (用於加密)";

    Rfc2898DeriveBytes k1 = new Rfc2898DeriveBytes(KEY_PASSWORD, EncryptSalt, Iterations);
    TripleDES encAlg = TripleDES.Create();
    encAlg.Key = k1.GetBytes(16);

    MemoryStream encryptionStream = new MemoryStream();
    CryptoStream encrypt = new CryptoStream(encryptionStream, encAlg.CreateEncryptor(), CryptoStreamMode.Write);

    byte[] EncryptDataToUTF8 = new System.Text.UTF8Encoding(false).GetBytes(EncryptData);
    encrypt.Write(EncryptDataToUTF8, 0, EncryptDataToUTF8.Length);
    encrypt.FlushFinalBlock();
    encrypt.Close();
    byte[] encryptedData = encryptionStream.ToArray();
    EncryptedData4Decrypt = encryptedData;
    k1.Reset();

    //EncryptIV = encAlg.IV; 這個 encAlg.IV 要用來解密的。

    StringBuilder ENCRYPTED_DATA_STRING = new StringBuilder();
    foreach (byte v in encryptedData){
        ENCRYPTED_DATA_STRING.Append(v);
    }
    richTextBox2.Text = ENCRYPTED_DATA_STRING.ToString(); //顯示加密後的資料
}

 要進行解密,要將你所使用的鹽和密碼對應,否則解密失敗會跳Exception:

private void doDecrypt(object sender, EventArgs e){
    string ENCRYPT_DATA = textBox3.Text; //要解密的資料
    string KEY_PASSWORD = textBox2.Text; //你的密碼
    string ENCRYPT_SALT = EncryptSalt; //要用原本的鹽來解密,這裡的 EncryptSalt是設定在全域變數,以拿到剛剛加密的鹽。
    Rfc2898DeriveBytes k2 = new Rfc2898DeriveBytes(KEY_PASSWORD, ENCRYPT_SALT);
    TripleDES decAlg = TripleDES.Create();
    decAlg.Key = k2.GetBytes(16);
    decAlg.IV = EncryptIV; //這個 IV 就是剛剛加密時的IV, 這裡的 EncryptIV 也是設定在全域變數,已拿到剛剛加密的IV。
    MemoryStream decryptionStreamBacking = new MemoryStream();
    CryptoStream decrypt = new CryptoStream(decryptionStreamBacking, decAlg.CreateDecryptor(), CryptoStreamMode.Write);
            
    byte[] ENCRYPT_DATA_TO_BYTE = EncryptedData4Decrypt;

    decrypt.Write(ENCRYPT_DATA_TO_BYTE, 0, ENCRYPT_DATA_TO_BYTE.Length);
    decrypt.Flush();
    decrypt.Close();
    k2.Reset();

    string data2 = new UTF8Encoding(false).GetString(decryptionStreamBacking.ToArray());
    richTextBox3.Text = data2; //顯示解密的資料
}




Reference:

沒有留言:

張貼留言

© ERIC RILEY , 自由無須告知轉貼
Background Japanese Sayagata by Olga Libby