使用私匙加密文件

来源:互联网 发布:淘宝联盟有部分退款 编辑:程序博客网 时间:2024/05/16 00:47

.Net提供了很多已经实现好的加密类,详见这篇文章。

下面的代码生成一个key file,这个key file在加密解密时使用,解密时如果没有key file,或者key file 不是加密时用的key file,将不能解密。虽然可以把key写死在程序中,但是保密性就太低了。

用私匙(也叫对称加密)加密文件速度很快。

 

第一次贴的代码有点问题,晚23点更新正确代码,请往后看

 

using System;

using System.IO;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Security.Cryptography;

 

namespace MyCryptography

{

    class Cryptography

    {

        private const int KEYSIZE = 128;

        private const int KEYSIZEINBYTE = KEYSIZE / 8;

 

        ///

        /// Save key file to the specified path

        ///

        /// The key file path

        internal void CreateKeyFile(string path)

        {

            TripleDESCryptoServiceProvider tDESalg = new TripleDESCryptoServiceProvider();

 

            //KeySize is in bit

            tDESalg.KeySize = KEYSIZE;

            tDESalg.GenerateIV();

            tDESalg.GenerateKey();

 

            using (FileStream fs = new FileStream(path, FileMode.Create))

            {

                fs.Write(tDESalg.Key, 0, tDESalg.Key.Length);

                fs.Write(tDESalg.IV, 0, tDESalg.IV.Length);

            }

 

            //Release all resouse used by the algorithm.

            //CLR won't dispose the memory untill Clear() is called.

            tDESalg.Clear();

        }

 

        ///

        /// Read IV and Key from the specified file path

        ///

        /// The key file path

        /// byte array list. The first array is key. The second is IV.

        private List<byte[]> ReadIVKey(string keypath)

        {

            List<byte[]> list = new List<byte[]>(2);

 

            if (File.Exists(keypath))

            {

                byte[] ivkey = File.ReadAllBytes(keypath);

 

                byte[] key = new byte[KEYSIZEINBYTE];

                byte[] iv = new byte[ivkey.Length - KEYSIZEINBYTE];

 

                for (int i = 0; i < KEYSIZEINBYTE; i++)

                {

                    key[i] = ivkey[i];

                }

 

                for (int i = 0; i < iv.Length; i++)

                {

                    iv[i] = ivkey[KEYSIZEINBYTE + i];

                }

 

                list.Add(key);

                list.Add(iv);

            }

 

            return list;

        }

 

        ///

        /// Use the specified key to encrypt the given file.

        ///

        /// The file to be encrypted.

        /// Key file path

        /// The output encrypted file path.

        internal void Encrypt(string filepath, string keypath, string savepath)

        {

            List<byte[]> ivkey = ReadIVKey(keypath);

      

            using (FileStream fs = new FileStream(savepath, FileMode.Create))

            {

                using (MemoryStream ms = new MemoryStream())

                {

                    using (CryptoStream cs = new CryptoStream(ms,

                           new TripleDESCryptoServiceProvider().CreateEncryptor(ivkey[0], ivkey[1]),

                           CryptoStreamMode.Write))

                    {

                        byte[] content = File.ReadAllBytes(filepath);

                        cs.Write(content, 0, content.Length);

                        cs.FlushFinalBlock();

                    }

                    fs.Write(ms.ToArray(), 0, ms.ToArray().Length);

                }

            }

        }

 

        ///

        /// Use the specified key to decrypt the given file.

        ///

        /// The file to be decrypted.

        /// Key file path

        /// The output decrypted file path.

        internal void Decrypt(string filepath, string keypath, string savepath)

        {

            List<byte[]> ivkey = ReadIVKey(keypath);

 

            using (FileStream fs = new FileStream(savepath, FileMode.Create))

            {

                byte[] content = File.ReadAllBytes(filepath);

                using (MemoryStream ms = new MemoryStream(content))

                {

                    using (CryptoStream cs = new CryptoStream(ms,

                           new TripleDESCryptoServiceProvider().CreateDecryptor(ivkey[0], ivkey[1]),

                           CryptoStreamMode.Read))

                    {

                        byte[] fromEncrypt = new byte[content.Length];

                        cs.Read(fromEncrypt, 0, fromEncrypt.Length);

                        fs.Write(fromEncrypt.ToArray(), 0, fromEncrypt.ToArray().Length);

                    }

                }

            }

        }

 

    }

}

因为私匙加密需要生成IV和Key,我把他们写在一个file里,加密解密时调用ReadIVKey把IV和Key分析出来。
CryptoStream是加密解密要使用的类,这点很关键。

 


要注意,加密后的文件通常会比原文件多些字节,上面代码解密的文件会比原文件多出几个字节,原因应该是byte[] fromEncrypt = new byte[content.Length];,content是读加密后文件的所有字节,然后用 fromEncrypt 写到文件流时,就把多出的字节也写了进去。

 

其实可以不经过MemoryStream这一步,直接把byte[]写入文件流中,这样解密的文件大小和原文件是一样。若要对内存中的流加密,需要用MemoryStream,对文件加密,用FileStream。更新Encrypt和Decrypt代码:

 

        /// <summary>

        /// Use the specified key to encrypt the given file.

        /// </summary>

        /// <param name="filepath">The file to be encrypted.</param>

        /// <param name="keypath">Key file path</param>

        /// <param name="savepath">The output encrypted file path.</param>

        internal void Encrypt(string filepath, string keypath, string savepath)

        {

            List<byte[]> ivkey = ReadIVKey(keypath);

 

            using (FileStream fsSave = new FileStream(savepath, FileMode.Create))

            {               

                using (CryptoStream cs = new CryptoStream(fsSave,

                       new TripleDESCryptoServiceProvider().CreateEncryptor(ivkey[0], ivkey[1]),

                       CryptoStreamMode.Write))

                {

                    using (FileStream fs = new FileStream(filepath, FileMode.Open))

                    {

                        int bufferLen = 4096;

                        byte[] buffer = new byte[bufferLen];

                        int bytesRead;

                        do

                        {

                            bytesRead = fs.Read(buffer, 0, bufferLen);

                            cs.Write(buffer, 0, bytesRead);

 

                        } while (bytesRead != 0);

 

                        cs.FlushFinalBlock();

                    }

                }

            }

        }

 

        /// <summary>

        /// Use the specified key to decrypt the given file.

        /// </summary>

        /// <param name="filepath">The file to be decrypted.</param>

        /// <param name="keypath">Key file path</param>

        /// <param name="savepath">The output decrypted file path.</param>

        internal void Decrypt(string filepath, string keypath, string savepath)

        {

            List<byte[]> ivkey = ReadIVKey(keypath);

 

            using (FileStream fs = new FileStream(filepath, FileMode.Open))

            {

                using (FileStream fsSave = new FileStream(savepath, FileMode.Create))

                {

                    using (CryptoStream cs = new CryptoStream(fsSave,

                           new TripleDESCryptoServiceProvider().CreateDecryptor(ivkey[0], ivkey[1]),

                           CryptoStreamMode.Write))

                    {

 

                        int bufferLen = 4096;

                        byte[] buffer = new byte[bufferLen];

                        int bytesRead;

                        do

                        {

                            bytesRead = fs.Read(buffer, 0, bufferLen);

                            cs.Write(buffer, 0, bytesRead);

 

                        } while (bytesRead != 0);

 

                        cs.FlushFinalBlock();

                    }

                }

            }

        }

 

附网上找的,根据给定密码生成Key和IV的方法示例,可用于根据密码加密文件

private void GenerateKey(string SecretPhrase)

        {

            // Initialize internal values

            this._Key = new byte[24];

            this._IV = new byte[16];

 

            // Perform a hash operation using the phrase.  This will

            // generate a unique 32 character value to be used as the key.

            byte[] bytePhrase = Encoding.ASCII.GetBytes(SecretPhrase);

            SHA384Managed sha384 = new SHA384Managed();

            sha384.ComputeHash(bytePhrase);

            byte[] result = sha384.Hash;

 

            // Transfer the first 24 characters of the hashed value to the key

            // and the remaining 8 characters to the intialization vector.

            for (int loop = 0; loop < 24; loop++) this._Key[loop] = result[loop];

            for (int loop = 24; loop < 40; loop++) this._IV[loop - 24] = result[loop];

        }

原创粉丝点击