Вопрос

I have these two methods which are pretty much copy+pastes from http://support.microsoft.com/kb/307010.

When I decrypt the files, if they are any type of text file such as .txt, .xml, .html, etc. I can open them up and everything is fine. Any type of file not just text, such as .exe, .jpg, .pdf, etc. all break when decrypted. Is there anything I am doing wrong? Are these methods using binary to encrypt/decrypt the files? If not is there a way I can make it binary?

Any help is greatly appreciated!

public static void EncryptFile(string sInputFilename,
       string sOutputFilename,
       string sKey)
    {
        FileStream fsInput = new FileStream(sInputFilename,
           FileMode.Open,
           FileAccess.Read);

        FileStream fsEncrypted = new FileStream(sOutputFilename,
           FileMode.Create,
           FileAccess.Write);
        DESCryptoServiceProvider DES = new DESCryptoServiceProvider();
        DES.Key = ASCIIEncoding.ASCII.GetBytes(sKey);
        DES.IV = ASCIIEncoding.ASCII.GetBytes(sKey);
        ICryptoTransform desencrypt = DES.CreateEncryptor();
        CryptoStream cryptostream = new CryptoStream(fsEncrypted,
           desencrypt,
           CryptoStreamMode.Write);

        byte[] bytearrayinput = new byte[fsInput.Length];
        fsInput.Read(bytearrayinput, 0, bytearrayinput.Length);
        cryptostream.Write(bytearrayinput, 0, bytearrayinput.Length);
        cryptostream.Close();
        fsInput.Close();
        fsEncrypted.Close();
    }

    public static void DecryptFile(string sInputFilename,
       string sOutputFilename,
       string sKey)
    {
        DESCryptoServiceProvider DES = new DESCryptoServiceProvider();
        //A 64 bit key and IV is required for this provider.
        //Set secret key For DES algorithm.
        DES.Key = ASCIIEncoding.ASCII.GetBytes(sKey);
        //Set initialization vector.
        DES.IV = ASCIIEncoding.ASCII.GetBytes(sKey);

        //Create a file stream to read the encrypted file back.
        FileStream fsread = new FileStream(sInputFilename,
           FileMode.Open,
           FileAccess.Read);
        //Create a DES decryptor from the DES instance.
        ICryptoTransform desdecrypt = DES.CreateDecryptor();
        //Create crypto stream set to read and do a 
        //DES decryption transform on incoming bytes.
        CryptoStream cryptostreamDecr = new CryptoStream(fsread,
           desdecrypt,
           CryptoStreamMode.Read);
        //Print the contents of the decrypted file.
        StreamWriter fsDecrypted = new StreamWriter(sOutputFilename);
        fsDecrypted.Write(new StreamReader(cryptostreamDecr).ReadToEnd());
        fsDecrypted.Flush();
        fsDecrypted.Close();
        fsread.Close();
        cryptostreamDecr.Close();
    }
Это было полезно?

Решение

I don't know what the guy that wrote that article was smoking, but:

DESCryptoServiceProvider desCrypto =
   (DESCryptoServiceProvider)DESCryptoServiceProvider.Create();

return ASCIIEncoding.ASCII.GetString(desCrypto.Key);

will not get you a valid key. At least one problem is the fact that the key you use to encrypt is not the same key that you're using to decrypt, because you can't convert bytes to ASCII and back like that.

If you want to treat the key as a string, what you probably want is:

string keyAsString = Convert.ToBase64String(desCrypto.Key);

Then when you want to turn it back into bytes, instead of ASCIIEncoding.ASCII.GetBytes, you'll do:

byte[] key = Convert.FromBase64String(keyAsString);

EDIT

There's a ton more wrong with that article too. I'd say ignore that one and find a better example.

EDIT

Here's a very clean basic AES working example that I use for my standard encryption needs. Some of the major improvements over the article are:

  • Proper creation of a key
  • Current algorithm (AES 256-bit key)
  • Random IV
  • Buffered file access instead of reading/writing the entire file in one chunk
  • Wrapping all the disposable objects in using

Aside from that, it's the same basic idea.

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

namespace ConsoleApplication12
{
    class Program
    {
        private const int KEY_SIZE_BYTES = 32;
        private const int IV_SIZE_BYTES = 16;

        static void Main(string[] args)
        {
            var rand = new Random();
            using (var fs = File.Open(@"C:\temp\input.bin", FileMode.Create, FileAccess.Write, FileShare.None))
            {
                byte[] buffer = new byte[10000];
                for (int i = 0; i < 100; ++i)
                {
                    rand.NextBytes(buffer);
                    fs.Write(buffer, 0, buffer.Length);
                }
            }
            string key = GenerateRandomKey();
            Encrypt(@"C:\temp\input.bin", @"C:\temp\encrypted.bin", key);
            Decrypt(@"C:\temp\encrypted.bin", @"C:\temp\decyrypted.bin", key);
        }

        static string GenerateRandomKey()
        {
            byte[] key = new byte[KEY_SIZE_BYTES];
            using (var rng = RandomNumberGenerator.Create())
            {
                rng.GetBytes(key);
            }
            return Convert.ToBase64String(key);
        }

        static void Encrypt(string inputFile, string outputFile, string key)
        {
            const int BUFFER_SIZE = 8192;
            byte[] buffer = new byte[BUFFER_SIZE];
            byte[] keyBytes = Convert.FromBase64String(key);
            byte[] ivBytes = new byte[IV_SIZE_BYTES];
            using (var rng = RandomNumberGenerator.Create())
            {
                rng.GetBytes(ivBytes);
            }
            using (var inputStream = File.Open(inputFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
            {
                using (var outputStream = File.Open(outputFile, FileMode.Create, FileAccess.Write, FileShare.None))
                {
                    outputStream.Write(ivBytes, 0, ivBytes.Length);
                    using (var cryptoAlgo = Aes.Create())
                    {
                        using (var encryptor = cryptoAlgo.CreateEncryptor(keyBytes, ivBytes))
                        {
                            using (var cryptoStream = new CryptoStream(outputStream, encryptor, CryptoStreamMode.Write))
                            {
                                int count;
                                while ((count = inputStream.Read(buffer, 0, buffer.Length)) > 0)
                                {
                                    cryptoStream.Write(buffer, 0, count);
                                }
                            }
                        }
                    }
                }
            }
        }

        static void Decrypt(string inputFile, string outputFile, string key)
        {
            const int BUFFER_SIZE = 8192;
            byte[] buffer = new byte[BUFFER_SIZE];
            byte[] keyBytes = Convert.FromBase64String(key);
            byte[] ivBytes = new byte[IV_SIZE_BYTES];
            using (var inputStream = File.Open(inputFile, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
            {
                inputStream.Read(ivBytes, 0, ivBytes.Length);
                using (var outputStream = File.Open(outputFile, FileMode.Create, FileAccess.Write, FileShare.None))
                {
                    using (var cryptoAlgo = Aes.Create())
                    {
                        using (var decryptor = cryptoAlgo.CreateDecryptor(keyBytes, ivBytes))
                        {
                            using (var cryptoStream = new CryptoStream(inputStream, decryptor, CryptoStreamMode.Read))
                            {
                                int count;
                                while ((count = cryptoStream.Read(buffer, 0, buffer.Length)) > 0)
                                {
                                    outputStream.Write(buffer, 0, count);
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}

Because the IV is random, you'll see another small difference in technique. When encrypting the file, you first write the IV to the encrypted file (it's not a secret, so you just write it straight out). When decrypting the file, you read the first few bytes to retrieve the IV, then the rest of the file contains the actual encrypted data. The purpose of a random IV is so the same plaintext file will encrypt into a different encrypted file every time you run it.

The Main method here demonstrates encryption with a random key. If you want to use a password, it's a little more work, but you can implement PBKDF2 with maybe a dozen or so extra lines of code.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top