【问题标题】:cant open the image after decryption of DES encryption C#DES加密C#解密后无法打开图像
【发布时间】:2014-12-19 09:40:56
【问题描述】:

我在使用 DES 加密加密和解密图像时遇到问题

我正在使用来自http://support.microsoft.com/kb/307010的代码

我稍微修改了一下(我添加了“cryptostream.FlushFinalBlock();”并将编码更改为“Encoding.Default”)

我尝试加密图像并对其进行解密,但解密后的图像无法打开(它说 “文件似乎已损坏或损坏”)

原始图像大小为 18,7 KB(19,159 字节),加密图像为 18,7 KB(19,160 字节),但解密图像为 33,4 KB(34,248 字节)。

这是我的代码

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();
    }
}
}

我用谷歌搜索过,它说我应该使用“FlushFinalBlock”并更改编码

试过了,还是不行

感谢之前

【问题讨论】:

  • 1) Encoding.Default.GetString(desCrypto.Key) 不可能是正确的。请改用 Base64 或十六进制。 2) 你在没有检查返回值的情况下调用stream.Read。这可能导致截断。 3) DES 很弱 4) 使用静态 IV 很糟糕,使用密钥更糟糕。 5)流读取器/写入器没有意义,因为它们用于文本并且可能损坏二进制数据。

标签: c# image encryption cryptography des


【解决方案1】:

问题很可能是从加密文件中读取 CryptoStream 时使用了 StreamReader。
StreamReader 适用于读取数据的文本表示形式,从.ReadToEnd(); (string) 返回的数据类型可见。现在,字符串可能无法解析特定数据,尤其是图像中使用的二进制数据。最常见的问题(据我所知)是图像可能包含空字节 (\0),它是字符串的终止字符。
要测试这是否是问题所在,您可以检查是否:
- 解密文件的文件大小比原始文件小 - 如果较小,读取原始文件的字节并查看解密文件结束的位置。如果有\0-byte,你就有答案了。

罪魁祸首可能是另一个特殊的字节序列而不是\0,但这并不能改变这样一个事实,即在这里使用 StreamReader 不是正确的选择。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-03-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多