图片加密解密时出现"要解密的数据的长度无效"

sxmonsy 2011-04-19 10:23:01
在读取解密图片的时候出现“要解密的数据的长度无效” 大家帮我看下是什么原因。
代码如下:

/// <summary>
/// 加密保存
/// </summary>
private void button1_Click(object sender, EventArgs e)
{
if (pictureBox1.Image != null)
{
//进行加密
byte[] imgData =CommonClass.ImageOperae.EncryptFle(pictureBox1.Image, "201104");

string cmdText = "";
using (OleDbConnection conn = new OleDbConnection(CommonClass.OleDbHelper.connAutomation))
{
//数据库保存略
}
}
}
/// <summary>
/// 读取文件
/// </summary>
private void button2_Click(object sender, EventArgs e)
{

OleDbConnection conn = new OleDbConnection(CommonClass.OleDbHelper.connAutomation);
conn.Open();
OleDbDataAdapter obda = new OleDbDataAdapter("select [image] from table1 where id=6", conn);
DataTable dt = new DataTable();
obda.Fill(dt);
conn.Close();
byte[] buffer = dt.Rows[0][0] as byte[];

//解密打开
MemoryStream ms = new MemoryStream(CommonClass.ImageOperae.DecryptFile(buffer,"sxm"));
pictureBox1.Image = img;
}

/// <summary>
/// 图片加密
/// </summary>
public static Byte[] EncryptFile(Image img, string keyStr)
{
//通过des加密
DESCryptoServiceProvider des = new DESCryptoServiceProvider();
MemoryStream ms = new MemoryStream();
//获取文件二进制字符
img.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
byte[] inputByteArray = ms.GetBuffer();

//获得加密字符串二进制字符
byte[] keyByteArray = Encoding.Default.GetBytes(keyStr);

//计算指定字节组指定区域哈希值
SHA1 ha = new SHA1Managed();
byte[] hb = ha.ComputeHash(keyByteArray);
//加密密钥数组
byte[] sKey = new byte[8];
//加密变量
byte[] sIV = new byte[8];
for (int i = 0; i < 8; i++)
sKey[i] = hb[i];
for (int i = 8; i < 16; i++)
sIV[i - 8] = hb[i];
//获取加密密钥
des.Key = sKey;
//设置加密初始化向量
des.IV = sIV;

CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write);
cs.Write(inputByteArray, 0, inputByteArray.Length);
cs.FlushFinalBlock();
cs.Close();
ms.Close();
return ms.ToArray();
}

/// <summary>
/// 图片解密
/// </summary>
public static byte[] DecryptFile(byte[] inputByteArray, string keyStr)
{
//通过des解密
DESCryptoServiceProvider des = new DESCryptoServiceProvider();

//密钥数组
byte[] keyByteArray = Encoding.Default.GetBytes(keyStr);
//定义哈希变量
SHA1 ha = new SHA1Managed();
//计算指定字节组指定区域哈希值
byte[] hb = ha.ComputeHash(keyByteArray);
//加密密钥数组
byte[] sKey = new byte[8];
//加密变量
byte[] sIV = new byte[8];
for (int i = 0; i < 8; i++)
sKey[i] = hb[i];
for (int i = 8; i < 16; i++)
sIV[i - 8] = hb[i];
//获取加密密钥
des.Key = sKey;
//加密变量
des.IV = sIV;
MemoryStream ms = new MemoryStream();
CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write);
cs.Write(inputByteArray, 0, inputByteArray.Length);

图片解读的时候这里出现"要解密的数据的长度无效"
cs.FlushFinalBlock();
cs.Close();
ms.Close();
return ms.ToArray();
}
...全文
357 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
sxmonsy 2011-04-22
  • 打赏
  • 举报
回复
ms.Position = 0;
这个很关健的说 加上这个就好用了。
谢谢楼上诸位 问题解决了 结贴。

teerhu 2011-04-21
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 beerium 的回复:]
同意楼上,经过试验,已经测试成功
加入红色的有一句话。

C# code
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Te……
[/Quote]
up
sxmonsy 2011-04-21
  • 打赏
  • 举报
回复
谢谢楼上二位 我马上去测试一下
qldsrx 2011-04-21
  • 打赏
  • 举报
回复
[Quote=引用 17 楼 beerium 的回复:]
同意楼上,经过试验,已经测试成功
加入红色的有一句话。

C# code
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Te……
[/Quote]
不应该这样写,你加入那代码显然没考虑效率问题。楼主你考虑了内存流的再利用,只是考虑欠缺了。其实只要改动一点点就可以让内存流再利用了。
byte[] inputByteArray = ms.GetBuffer();

改为:
byte[] inputByteArray = ms.ToArray();


CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write);

前面添加:
ms.Position = 0;


第一处改动非常重要,不能用GetBuffer,也许你觉得GetBuffer效率会高,错了,刚好相反,GetBuffer虽然不用复制数组,但是GetBuffer得到的数组长度往往比ToArray得到的长,超过了实际长度,因为MemoryStream内部分配Buffer大小的时候,总是以一个固定的大小递增着分配的,因此MemoryStream的Length属性不代表那个Buffer的大小,只是有效数据的长度。另外当MemoryStream内容改变时,那个GetBuffer获得的数据也会跟着变,因此不适合MemoryStream的重利用。
第二处改动之所以可以,因为加密后的流会比加密前多出8个字节,因此我让流指针指向开始位置,从开始位置写入,这样就可以完全将以前图片保存时写过的位置全部覆盖掉,重利用了内存流。
chengjia2284 2011-04-20
  • 打赏
  • 举报
回复
帮顶。找资料去了。以前好像弄过一个。得找找了......
sxmonsy 2011-04-20
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 fengyarongaa 的回复:]
Image img ???
你这改了能一样还怪了
前后不着调
[/Quote]
最顶上给的就是我改的用image 做参数的加密方法 麻烦看下 看看哪不着调 谢谢了
raykenio 2011-04-20
  • 打赏
  • 举报
回复
是不是要补长度?我猜测的!以前好像写过,但是也没成功!
ycproc 2011-04-20
  • 打赏
  • 举报
回复
Image img ???
你这改了能一样还怪了
前后不着调
sxmonsy 2011-04-20
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 sxmonsy 的回复:]
应该不是解密方法的错误。
我的另一个加密方法也是用这个解密的。

C# code

public static void EncryptFile(string filePath, string savePath, string keyStr)
{
//通过des加密
DESCryptoServiceProvide……
[/Quote]
用这个方法加密和解密就是正常的 但把参数改为Image img 后就不好用了。
vrhero 2011-04-20
  • 打赏
  • 举报
回复
不可能不支持,你得用缓冲区读啊...

inputByteArray、MemoryStream和CryptoStream都是源,你得新建一个byte[]做缓冲区...例如...
byte[] result = new byte[dinputByteArray.Length];
cs.Read(result, 0, result.Length);
return result;
sxmonsy 2011-04-20
  • 打赏
  • 举报
回复
应该不是解密方法的错误。
我的另一个加密方法也是用这个解密的。

public static void EncryptFile(string filePath, string savePath, string keyStr)
{
//通过des加密
DESCryptoServiceProvider des = new DESCryptoServiceProvider();

//通过流打开文件
FileStream fs = File.OpenRead(filePath);
//获取文件二进制字符
byte[] inputByteArray = new byte[fs.Length];
//读流文件
fs.Read(inputByteArray, 0, (int)fs.Length);
//关闭流
fs.Close();
//获得加密字符串二进制字符
byte[] keyByteArray = Encoding.Default.GetBytes(keyStr);

//下面都一样
sxmonsy 2011-04-20
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 vrhero 的回复:]
解密方法不对...解密时CryptoStream是源,要Read不是Write...

C# code
MemoryStream ms = new MemoryStream(inputByteArray);
CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Read);
cs.Re……
[/Quote]
提示 流不支持读取。。。。
cfvgodot 2011-04-20
  • 打赏
  • 举报
回复
读取流位置的时候设置一下ms.Position=0
sxmonsy 2011-04-20
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 51crack 的回复:]
加密用"201104"
解密用"sxm"
?????
[/Quote]
其实都是“201104”
vrhero 2011-04-20
  • 打赏
  • 举报
回复
解密方法不对...解密时CryptoStream是源,要Read不是Write...
MemoryStream ms = new MemoryStream(inputByteArray);
CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Read);
cs.Read(...//bolabola自己改吧...
51Crack 2011-04-20
  • 打赏
  • 举报
回复
加密用"201104"
解密用"sxm"
?????
sxmonsy 2011-04-20
  • 打赏
  • 举报
回复
100分没人理 再加100 帮帮忙吧
大山里的松 2011-04-20
  • 打赏
  • 举报
回复
同意楼上,经过试验,已经测试成功
加入红色的有一句话。
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.Security.Cryptography;
using System.IO;
using System.Data.OleDb;

namespace CommonClass
{
public partial class ImageOperae : Form
{
public ImageOperae()
{
InitializeComponent();

}
/// <summary>
/// 加密保存
/// </summary>
private void button1_Click(object sender, EventArgs e)
{
this.pictureBox1.ImageLocation = @"c:\Winter.jpg";
if (pictureBox1.Image != null)
{
//进行加密
byte[] imgData = CommonClass.ImageOperae.EncryptFile(pictureBox1.Image, "201104");

using (OleDbConnection conn = new OleDbConnection(CommonClass.OleDbHelper.connAutomation))
{
conn.Open();

OleDbCommand cmd = new OleDbCommand();
cmd.Connection = conn;
//cmd.CommandText = "delete from table1";
//cmd.ExecuteNonQuery();
//cmd.Parameters.Clear();

OleDbParameter prm = new OleDbParameter();
prm.ParameterName = "@ppp";
prm.OleDbType = OleDbType.Binary;
prm.Value = imgData;

cmd.Parameters.Add(prm);

cmd.CommandText = "insert into table1 (id, [image]) values ('6', ?)";

int count = cmd.ExecuteNonQuery();
MessageBox.Show(count.ToString());

cmd.Dispose();
conn.Close();
}
}
}
/// <summary>
/// 读取文件
/// </summary>
private void button2_Click(object sender, EventArgs e)
{

OleDbConnection conn = new OleDbConnection(CommonClass.OleDbHelper.connAutomation);
conn.Open();
OleDbDataAdapter obda = new OleDbDataAdapter("select [image] from table1 where id=6", conn);
DataTable dt = new DataTable();
obda.Fill(dt);
conn.Close();
byte[] buffer = dt.Rows[0][0] as byte[];

//解密打开
MemoryStream ms = new MemoryStream(CommonClass.ImageOperae.DecryptFile(buffer, "201104"));

Image img = Image.FromStream(ms);
pictureBox1.Image = img;
}

/// <summary>
/// 图片加密
/// </summary>
public static Byte[] EncryptFile(Image img, string keyStr)
{
//通过des加密
DESCryptoServiceProvider des = new DESCryptoServiceProvider();
MemoryStream ms = new MemoryStream();
//获取文件二进制字符
img.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
byte[] inputByteArray = ms.GetBuffer();

//获得加密字符串二进制字符
byte[] keyByteArray = Encoding.Default.GetBytes(keyStr);

//计算指定字节组指定区域哈希值
SHA1 ha = new SHA1Managed();
byte[] hb = ha.ComputeHash(keyByteArray);
//加密密钥数组
byte[] sKey = new byte[8];
//加密变量
byte[] sIV = new byte[8];
for (int i = 0; i < 8; i++)
sKey[i] = hb[i];
for (int i = 8; i < 16; i++)
sIV[i - 8] = hb[i];
//获取加密密钥
des.Key = sKey;
//设置加密初始化向量
des.IV = sIV;

ms = new MemoryStream(); //加上这句话
CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write);
cs.Write(inputByteArray, 0, inputByteArray.Length);
cs.FlushFinalBlock();
cs.Close();
ms.Close();
return ms.ToArray();
}

/// <summary>
/// 图片解密
/// </summary>
public static byte[] DecryptFile(byte[] inputByteArray, string keyStr)
{
//通过des解密
DESCryptoServiceProvider des = new DESCryptoServiceProvider();

//密钥数组
byte[] keyByteArray = Encoding.Default.GetBytes(keyStr);
//定义哈希变量
SHA1 ha = new SHA1Managed();
//计算指定字节组指定区域哈希值
byte[] hb = ha.ComputeHash(keyByteArray);
//加密密钥数组
byte[] sKey = new byte[8];
//加密变量
byte[] sIV = new byte[8];
for (int i = 0; i < 8; i++)
sKey[i] = hb[i];
for (int i = 8; i < 16; i++)
sIV[i - 8] = hb[i];
//获取加密密钥
des.Key = sKey;
//加密变量
des.IV = sIV;
MemoryStream ms = new MemoryStream();
CryptoStream cs = new CryptoStream(ms, des.CreateDecryptor(), CryptoStreamMode.Write);
cs.Write(inputByteArray, 0, inputByteArray.Length);

cs.FlushFinalBlock();
cs.Close();
ms.Close();
return ms.ToArray();
}

}
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace CommonClass
{
public class OleDbHelper
{
public static string connAutomation
= @"Provider=SQLOLEDB.1;Persist Security Info=False;User ID=sa; password=123;Initial Catalog=test;Data Source=.\sql2008";
}
}

qldsrx 2011-04-20
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 sxmonsy 的回复:]
100分没人理 再加100 帮帮忙吧
[/Quote]
刚看到这个帖子,不是因为分少哦。

如果我没猜错,你的问题在这里:
public static Byte[] EncryptFile(Image img, string keyStr)
{
//通过des加密
DESCryptoServiceProvider des = new DESCryptoServiceProvider();
MemoryStream ms = new MemoryStream();
//获取文件二进制字符
img.Save(ms, System.Drawing.Imaging.ImageFormat.Jpeg);
byte[] inputByteArray = ms.GetBuffer();

//获得加密字符串二进制字符
byte[] keyByteArray = Encoding.Default.GetBytes(keyStr);

//计算指定字节组指定区域哈希值
SHA1 ha = new SHA1Managed();
byte[] hb = ha.ComputeHash(keyByteArray);
//加密密钥数组
byte[] sKey = new byte[8];
//加密变量
byte[] sIV = new byte[8];
for (int i = 0; i < 8; i++)
sKey[i] = hb[i];
for (int i = 8; i < 16; i++)
sIV[i - 8] = hb[i];
//获取加密密钥
des.Key = sKey;
//设置加密初始化向量
des.IV = sIV;

CryptoStream cs = new CryptoStream(ms, des.CreateEncryptor(), CryptoStreamMode.Write); cs.Write(inputByteArray, 0, inputByteArray.Length);
cs.FlushFinalBlock();
cs.Close();
ms.Close();
return ms.ToArray();
}
看红色部分,这里的ms变量存放了你加密后的数据流,可是你却用了两次,第一次用在图片保存上了,以至于在加密数据是对一个非空的流写入,返回的数据是图片数据+加密数据的拼接。
wuxing2006 2011-04-20
  • 打赏
  • 举报
回复
看了下代码,你可以检查下是不是已经超int范围了,改用long,分批写入CryptoStream 流试试
加载更多回复(1)

110,561

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧