Пример #1
0
        /// <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());
        }