简体   繁体   中英

cant open the image after decryption of DES encryption C#

I'm having trouble in encrypting and decrypting image with DES encryption

I'm using the code from http://support.microsoft.com/kb/307010

I modified it a bit(I add the "cryptostream.FlushFinalBlock();" and change the encoding to "Encoding.Default")

I tried to encrypt an image and decrypt it but the decrypted image cant be opened(it says "file appears to be damaged or corrupted")

the original image size is 18,7 KB(19,159 bytes), the encrypted image is 18,7 KB(19,160 bytes), but the decrypted image is 33,4 KB(34,248 bytes).

here is my code

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Security;
using System.Security.Cryptography;
using System.Runtime.InteropServices;

namespace microsoft_example
{

public partial class Form1:Form
{
    //
    //  Call this function to remove the key from memory after use for security
    [System.Runtime.InteropServices.DllImport("KERNEL32.DLL", EntryPoint="RtlZeroMemory")]
    public static extern bool ZeroMemory(IntPtr Destination, int Length);

    // Function to Generate a 64 bits Key.
    static string GenerateKey()
    {
        // Create an instance of Symetric Algorithm. Key and IV is generated automatically.
        DESCryptoServiceProvider desCrypto =(DESCryptoServiceProvider)DESCryptoServiceProvider.Create();

        // Use the Automatically generated key for Encryption.
        return Encoding.Default.GetString(desCrypto.Key);
    }

    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 = Encoding.Default.GetBytes(sKey);
        DES.IV = Encoding.Default.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.FlushFinalBlock();
        cryptostream.Close();
        fsInput.Close();
        fsEncrypted.Close();
    }

    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 = Encoding.Default.GetBytes(sKey);
        //Set initialization vector.
        DES.IV = Encoding.Default.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();
    }
    //

    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_Load(object sender,EventArgs e)
    {
        // Must be 64 bits, 8 bytes.
        // Distribute this key to the user who will decrypt this file.
        string sSecretKey;

        // Get the Key for the file to Encrypt.
        sSecretKey = GenerateKey();

        // For additional security Pin the key.
        GCHandle gch = GCHandle.Alloc( sSecretKey,GCHandleType.Pinned );

        // Encrypt the file.        
        EncryptFile(@"D:\IMAGE\chara\des\aoi2z.jpg", @"D:\IMAGE\chara\des\Encrypted.des", sSecretKey);

        // Decrypt the file.
        DecryptFile(@"D:\IMAGE\chara\des\Encrypted.des", @"D:\IMAGE\chara\des\aoi2zdes.jpg", sSecretKey);

        // Remove the Key from memory. 
        ZeroMemory(gch.AddrOfPinnedObject(), sSecretKey.Length * 2);
        gch.Free();
    }
}
}

I've googled it and it says I should use "FlushFinalBlock" and change the encoding

I've tried, still doesnt work

Thanks before

The problem most likely is the usage of the StreamReader when reading the CryptoStream from the encrypted file.
The StreamReader is good for reading a text-representation of the data, which is visible by the data type returned from .ReadToEnd(); ( string ). Now, strings may not be able to parse specific data, especially binary data used in images. The most common problem (as far as i have experienced) is that images may contain null-bytes ( \\0 ) which is the termination character for strings.
To test if this is the problem, you could check if:
- The file size of the decrypted file is smaller than the original file - If it is smaller, read the bytes of the original file and have a look at the position where the decrypted file ends. If there is the \\0 -byte, you have the answer.

It is possible that the culprit is another special byte sequence and not the \\0 , but that doesn't change the fact that using a StreamReader here isn't the right choice.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM