/// <summary> /// Encrypts and MACs some plaintext with a passphrase /// </summary> /// <param name="passphrase">Password to encrypt/MAC</param> /// <param name="plaintext">Text to protect</param> /// <returns>Base64 ciphertext blob</returns> public string EncryptAndMac(string passphrase, string plaintext) { if (passphrase.Length == 0 || plaintext.Length == 0) { throw new ArgumentException(); } // generate a salt from random data (24 bytes) + system tick count (8 bytes) byte[] ticks = BitConverter.GetBytes(DateTime.Now.Ticks); var tempSalt = new byte[_salt.Length - ticks.Length]; new RNGCryptoServiceProvider().GetBytes(tempSalt); Array.Copy(tempSalt, _salt, tempSalt.Length); Array.Copy(ticks, 0, _salt, tempSalt.Length, ticks.Length); // get PBKDF info and create object (salt is ignored from config file) string s = _configData[LinePbkdfsettings].Split(Delim)[1]; dynamic dp = new JavaScriptSerializer().DeserializeObject(s); int iter = int.Parse(dp["IterationCount"].ToString()); _pbkdf = new Rfc2898DeriveBytes(passphrase, _salt, iter); // get symmetric cipher info and create object _sym = SymmetricAlgorithm.Create(_configData[LineSymalgsettings].Split(Delim)[0]); dynamic ds = new JavaScriptSerializer(). DeserializeObject(_configData[LineSymalgsettings].Split(Delim)[1]); _sym.BlockSize = ds["BlockSize"]; _sym.KeySize = ds["KeySize"]; _sym.Mode = (CipherMode)ds["Mode"]; _sym.Padding = (PaddingMode)ds["Padding"]; // get HMAC settings and create object // TODO: currently uses default alg (SHA-256), need to make it configurable, too _hmac = HMAC.Create(_configData[LineHmacsettings].Split(Delim)[0]); // // Do the dirty work // // generate symmetric key and HMAC key _sym.Key = _pbkdf.GetBytes(_sym.KeySize >> 3); _hmac.Key = _pbkdf.GetBytes(_hmac.HashSize >> 3); // perform the crypto opertions string ciphertext = Encrypt(plaintext); // encrypt then MAC - this MACs the ciphertext string hmac = CalculateHmac(ciphertext); // serialize the symmetric alg, but strip out the key var oSerializer = new JavaScriptSerializer(); // clear all keys //_sym.Key = new byte[_sym.Key.Length]; //_hmac.Key = new byte[_hmac.Key.Length]; // serialize the ciphertext/HMAC/PKBDF string sJsonSym = RemoveJunkFromJson(oSerializer.Serialize(_sym)); string sJsonHmac = RemoveJunkFromJson(oSerializer.Serialize(_hmac)); string sJsonPbkdf = oSerializer.Serialize(_pbkdf); // build the resulting cipherblob string var sb = new StringBuilder(); sb.Append(_pbkdf.ToString() + Delim + sJsonPbkdf + Crlf); sb.Append(_sym.ToString() + Delim + sJsonSym + Crlf); sb.Append(_hmac.ToString() + Delim + sJsonHmac + Crlf); sb.Append(ciphertext + Crlf); sb.Append(hmac); return(sb.ToString()); }