如何将图像bytearray解密为原始值?

时间:2015-06-02 07:48:52

标签: c# encryption

我想加密图片框图像并将其保存到文件中,并能够将其解密并加载回图片框。那里有各种代码示例,但它们似乎都不适合我。我总是得到比原来更大的解密文件。

我尝试了不同的方法,这是我写的最新的方法:

// Save signature file
    public void SaveFile(System.Drawing.Image image, string filename, string password)
    {


        byte[] img = imgToByteArray(image);
        byte[] encrypted = Signatures.Encryption.Encrypt(img, password);
        File.WriteAllBytes(filename, encrypted);

        // DEBUG
        byte[] decrypted = Signatures.Encryption.Decrypt(encrypted, password);
        image.Save(filename + "O");
        File.WriteAllBytes(filename + "E", encrypted);
        File.WriteAllBytes(filename + "D", decrypted);
        // End of DEBUG

    }

    // Open signature file
    public System.Drawing.Image ReadFile(string filename, string password)
    {
        byte[] encrypted = File.ReadAllBytes(filename);
        byte[] decrypted = Signatures.Encryption.Decrypt(encrypted, password);
        Image image = bytearrayToImage(decrypted);
        return image;
    }


    // Convert image to bytearray
    private byte[] imgToByteArray(Image img)
    {
        using (MemoryStream ms = new MemoryStream())
        {
            img.Save(ms, ImageFormat.Png);
            return ms.ToArray();
        }
    }

    // Convert bytearray to image
    private Image bytearrayToImage(byte[] bytearray)
    {
        using (MemoryStream ms = new MemoryStream(bytearray))
        {
            return Image.FromStream(ms);    
        }
    }

Signatures.Encryption:

public static byte[] Encrypt(byte[] input, string password)
    {
        byte[] output;

        PasswordDeriveBytes pdb = new PasswordDeriveBytes(password, new byte[] { 0x43, 0x87, 0x23, 0x72 });

        Aes aes = new AesManaged();

        aes.Padding = PaddingMode.PKCS7;
        aes.KeySize = 256;
        aes.Key = pdb.GetBytes(aes.KeySize / 8);
        aes.IV = pdb.GetBytes(aes.BlockSize / 8);

        using (MemoryStream ms = new MemoryStream())
        {
            using (CryptoStream cs = new CryptoStream(ms, aes.CreateEncryptor(), CryptoStreamMode.Write))
            {
                cs.Write(input, 0, input.Length);
            }

            output = ms.ToArray();
        }

        return output;
    }

    public static byte[] Decrypt(byte[] input, string password)
    {
        byte[] output;

        PasswordDeriveBytes pdb = new PasswordDeriveBytes(password, new byte[] { 0x43, 0x87, 0x23, 0x72 });

        Aes aes = new AesManaged();

        aes.Padding = PaddingMode.PKCS7;
        aes.KeySize = 256;
        aes.Key = pdb.GetBytes(aes.KeySize / 8);
        aes.IV = pdb.GetBytes(aes.BlockSize / 8);

        using (MemoryStream ms = new MemoryStream())
        {
            using (CryptoStream cs = new CryptoStream(ms, aes.CreateDecryptor(), CryptoStreamMode.Write))
            {
                cs.Write(input, 0, input.Length);
            }

            output = ms.ToArray();
        }

        return output;
    }

使用PaddingMode.PKCS7生成异常:

 +      Thrown: "Padding is invalid and cannot be removed." (System.Security.Cryptography.CryptographicException)   Exception Message = "Padding is invalid and cannot be removed.", Exception Type = "System.Security.Cryptography.CryptographicException", Exception WinRT Data = null    

PaddingMode.Zeros生成异常:

+       Thrown: "Parameter is not valid." (System.ArgumentException)    Exception Message = "Parameter is not valid.", Exception Type = "System.ArgumentException", Exception WinRT Data = null 

我认为生成Parameter is not valid.异常是因为图像无效(因为解密字节长度较高),CompareBytes(byte[] first, byte[] second)在所有这些情况下都会false

编辑: I just found out将一个NULL字节添加到加密/解密文件的末尾。 EDIT2:加密时会添加NULL字节。删除它不会做太多,Image.FromStream();仍然会抛出"参数无效。"。

1 个答案:

答案 0 :(得分:0)

这里的问题是(重新)压缩,而不是加密。我在JPG文件上尝试了你的代码,解密的输出是PNG。

要保留大小,您必须在相同的输入和帐户上使用相同的编解码器进行元数据和数据对齐,即您可能无法控制的内容。