博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
『原创』c#实现文件加密、解密及文件拖拽至程序图标直接打开
阅读量:6557 次
发布时间:2019-06-24

本文共 6362 字,大约阅读时间需要 21 分钟。

最近,工作特别忙,一直没空子来写Blog,这不,忙里偷闲,顺手写了个文件加解密的小程序,本来公司市场部的同事出去带着合同,怕弄丢了,所以让我们开发个小程序,用于加密合同文件,到客户那里解密打开,然后签订合同,最后加密,带回公司保存。

时间不充裕,也就一上午时间吧,下午就要去签合同了,嘿嘿,于是我亲自试验了一把,下面和大家分享一下吧。

首先,这是个winform的程序,部署在市场部同事的笔记本上面,基于.Net 2.0做的,它的功能大致如下:

  • 加密合同文档(*.doc)
  • 在客户处解密此合同文档,进行编辑,再次加密
  • 回到公司可以通过密码打开它

由于时间关系,只是很粗略的做了个大概。打开vs2008,建立一个winform项目,设计程序界面如下:

  

很简单的,待会儿在文章最后会有下载地址。我们可以把任意文件,拖入程序界面,即可进行加密,在此暂不作说明,大家可以待会儿下载回去试试,很简单的。

下面分享一下加密代码吧:

 

代码
 
using
System;
using
System.Collections.Generic;
using
System.Text;
using
System.Security.Cryptography;
using
System.IO;
namespace
FileLock
{
///
<summary>
///
异常处理类
///
</summary>
public
class
CryptoHelpException : ApplicationException
{
public
CryptoHelpException(
string
msg) :
base
(msg) { }
}
public
class
CryptoHelp
{
private
const
ulong
FC_TAG
=
0xFC010203040506CF
;
private
const
int
BUFFER_SIZE
=
128
*
1024
;
///
<summary>
///
检验两个Byte数组是否相同
///
</summary>
///
<param name="b1">
Byte数组
</param>
///
<param name="b2">
Byte数组
</param>
///
<returns>
true-相等
</returns>
private
static
bool
CheckByteArrays(
byte
[] b1,
byte
[] b2)
{
if
(b1.Length
==
b2.Length)
{
for
(
int
i
=
0
; i
<
b1.Length;
++
i)
{
if
(b1[i]
!=
b2[i])
return
false
;
}
return
true
;
}
return
false
;
}
///
<summary>
///
创建Rijndael SymmetricAlgorithm
///
</summary>
///
<param name="password">
密码
</param>
///
<param name="salt"></param>
///
<returns>
加密对象
</returns>
private
static
SymmetricAlgorithm CreateRijndael(
string
password,
byte
[] salt)
{
PasswordDeriveBytes pdb
=
new
PasswordDeriveBytes(password, salt,
"
SHA256
"
,
1000
);
SymmetricAlgorithm sma
=
Rijndael.Create();
sma.KeySize
=
256
;
sma.Key
=
pdb.GetBytes(
32
);
sma.Padding
=
PaddingMode.PKCS7;
return
sma;
}
///
<summary>
///
加密文件随机数生成
///
</summary>
private
static
RandomNumberGenerator rand
=
new
RNGCryptoServiceProvider();
///
<summary>
///
生成指定长度的随机Byte数组
///
</summary>
///
<param name="count">
Byte数组长度
</param>
///
<returns>
随机Byte数组
</returns>
private
static
byte
[] GenerateRandomBytes(
int
count)
{
byte
[] bytes
=
new
byte
[count];
rand.GetBytes(bytes);
return
bytes;
}
///
<summary>
///
加密文件
///
</summary>
///
<param name="inFile">
待加密文件
</param>
///
<param name="outFile">
加密后输入文件
</param>
///
<param name="password">
加密密码
</param>
public
static
void
EncryptFile(
string
inFile,
string
outFile,
string
password)
{
using
(FileStream fin
=
File.OpenRead(inFile),
fout
=
File.OpenWrite(outFile))
{
long
lSize
=
fin.Length;
//
输入文件长度
int
size
=
(
int
)lSize;
byte
[] bytes
=
new
byte
[BUFFER_SIZE];
//
缓存
int
read
=
-
1
;
//
输入文件读取数量
int
value
=
0
;
//
获取IV和salt
byte
[] IV
=
GenerateRandomBytes(
16
);
byte
[] salt
=
GenerateRandomBytes(
16
);
//
创建加密对象
SymmetricAlgorithm sma
=
CryptoHelp.CreateRijndael(password, salt);
sma.IV
=
IV;
//
在输出文件开始部分写入IV和salt
fout.Write(IV,
0
, IV.Length);
fout.Write(salt,
0
, salt.Length);
//
创建散列加密
HashAlgorithm hasher
=
SHA256.Create();
using
(CryptoStream cout
=
new
CryptoStream(fout, sma.CreateEncryptor(), CryptoStreamMode.Write),
chash
=
new
CryptoStream(Stream.Null, hasher, CryptoStreamMode.Write))
{
BinaryWriter bw
=
new
BinaryWriter(cout);
bw.Write(lSize);
bw.Write(FC_TAG);
//
读写字节块到加密流缓冲区
while
((read
=
fin.Read(bytes,
0
, bytes.Length))
!=
0
)
{
cout.Write(bytes,
0
, read);
chash.Write(bytes,
0
, read);
value
+=
read;
}
//
关闭加密流
chash.Flush();
chash.Close();
//
读取散列
byte
[] hash
=
hasher.Hash;
//
输入文件写入散列
cout.Write(hash,
0
, hash.Length);
//
关闭文件流
cout.Flush();
cout.Close();
}
}
}
///
<summary>
///
解密文件
///
</summary>
///
<param name="inFile">
待解密文件
</param>
///
<param name="outFile">
解密后输出文件
</param>
///
<param name="password">
解密密码
</param>
public
static
void
DecryptFile(
string
inFile,
string
outFile,
string
password)
{
//
创建打开文件流
using
(FileStream fin
=
File.OpenRead(inFile),
fout
=
File.OpenWrite(outFile))
{
int
size
=
(
int
)fin.Length;
byte
[] bytes
=
new
byte
[BUFFER_SIZE];
int
read
=
-
1
;
int
value
=
0
;
int
outValue
=
0
;
byte
[] IV
=
new
byte
[
16
];
fin.Read(IV,
0
,
16
);
byte
[] salt
=
new
byte
[
16
];
fin.Read(salt,
0
,
16
);
SymmetricAlgorithm sma
=
CryptoHelp.CreateRijndael(password, salt);
sma.IV
=
IV;
value
=
32
;
long
lSize
=
-
1
;
//
创建散列对象, 校验文件
HashAlgorithm hasher
=
SHA256.Create();
//
using (CryptoStream cin = new CryptoStream(fin, sma.CreateDecryptor(), CryptoStreamMode.Read),
//
chash = new CryptoStream(Stream.Null, hasher, CryptoStreamMode.Write))
//
{
CryptoStream cin
=
new
CryptoStream(fin, sma.CreateDecryptor(), CryptoStreamMode.Read), chash
=
new
CryptoStream(Stream.Null, hasher, CryptoStreamMode.Write);
//
读取文件长度
BinaryReader br
=
new
BinaryReader(cin);
lSize
=
br.ReadInt64();
ulong
tag
=
br.ReadUInt64();
if
(FC_TAG
!=
tag)
throw
new
CryptoHelpException(
"
文件被破坏或者密码不正确
"
);
long
numReads
=
lSize
/
BUFFER_SIZE;
long
slack
=
(
long
)lSize
%
BUFFER_SIZE;
for
(
int
i
=
0
; i
<
numReads;
++
i)
{
read
=
cin.Read(bytes,
0
, bytes.Length);
fout.Write(bytes,
0
, read);
chash.Write(bytes,
0
, read);
value
+=
read;
outValue
+=
read;
}
if
(slack
>
0
)
{
read
=
cin.Read(bytes,
0
, (
int
)slack);
fout.Write(bytes,
0
, read);
chash.Write(bytes,
0
, read);
value
+=
read;
outValue
+=
read;
}
chash.Flush();
chash.Close();
fout.Flush();
fout.Close();
byte
[] curHash
=
hasher.Hash;
//
获取比较和旧的散列对象
byte
[] oldHash
=
new
byte
[hasher.HashSize
/
8
];
read
=
cin.Read(oldHash,
0
, oldHash.Length);
if
((oldHash.Length
!=
read)
||
(
!
CheckByteArrays(oldHash, curHash)))
throw
new
CryptoHelpException(
"
文件被破坏
"
);
cin.Flush();
cin.Close();
//
}
if
(outValue
!=
lSize)
throw
new
CryptoHelpException(
"
文件大小不匹配
"
);
}
}
}
}

 

是不是很明了呢?当然了,网上一搜一大把,我这个也是不小心搜到的,感觉比较不错的代码,后来经过我少许加工,即可使用了。当然,在这里,还要提一句,这个小程序,为了让它更方便,直接拖拽文件到其图标之上,就默认打开程序,加载该文件,并进行加密操作,听起来是不是很cool!?呵呵,下面再和大家分享一下如何实现吧:

在窗体的DragDrop和DragEnter事件下,添加如下代码:

 

代码
 
private
void
MainForm_DragEnter(
object
sender, DragEventArgs e)
{
if
(e.Data.GetDataPresent(DataFormats.FileDrop))
e.Effect
=
DragDropEffects.Move;
else
e.Effect
=
DragDropEffects.None;
}
private
void
MainForm_DragDrop(
object
sender, DragEventArgs e)
{
string
path
=
((System.Array)e.Data.GetData(DataFormats.FileDrop)).GetValue(
0
).ToString();
extension
=
System.IO.Path.GetExtension(path);
//
扩展名
if
(extension
==
"
.encrypted
"
)
{
btnEncy.Enabled
=
false
;
btnDecy.Enabled
=
true
;
}
else
{
btnEncy.Enabled
=
true
;
btnDecy.Enabled
=
false
;
}
txtInFile.Text
=
path;
}

 

 

 

Ok,是不是很简单,这样,在程序未启动时,拖拽一个目标文件到程序图标上,程序会自动打开,并进行相应操作。具体的操作,大家可以自己创造更有意义的代码来进行操作!

最后,献上下载地址,源代码:

希望对大家有用哦

转载地址:http://elqco.baihongyu.com/

你可能感兴趣的文章
Linux 用户和用户组管理
查看>>
tomcat架构分析(valve源码导读)
查看>>
spring中InitializingBean接口使用理解(转)
查看>>
基于php5.5使用PHPMailer-5.2发送邮件
查看>>
InstallShield 2012 Spring新功能试用(16): Suite/Advanced UI 或 Advanced UI安装程序能在安装时进行输入合法性校验与反馈...
查看>>
C#面试宝典
查看>>
基金项目的英文
查看>>
《软件性能测试与LoadRunner实战教程》喜马拉雅有声图书上线
查看>>
ios 字典转模型
查看>>
正在编译转换: 未能找到元数据文件 EntityFramework.dll
查看>>
Java类集
查看>>
K-Means聚类算法的原理及实现【转】
查看>>
类的生命周期
查看>>
php apache用户写文件夹权限设置
查看>>
003-诠释 Java 工程师【一】
查看>>
浅析rune数据类型
查看>>
普通用户开启AUTOTRACE 功能
查看>>
1034 - Navigation
查看>>
Bind+Nginx实现负载均衡
查看>>
游侠原创:推荐一款免费的Syslog转发工具
查看>>