数字签名的简单实现
static void Main(string[] args)
{
//
// TODO: 在此处添加代码以启动应用程序
//
string sFilePath =@"c:\kevin.txt";
//在c盘下创建一个用于测试的文挡;
StreamWriter sw = File.CreateText(sFilePath);
//在新创建的文挡下插入测试数据
sw.Write("Hi,This is a test Document!");
//关闭写流
sw.Close();
//转换文挡成哈希数组
byte[] bHash = GetFileHash(sFilePath);
//生成公钥
string sPublicKey = GetKeyFromName("测试",false);
//生成私钥
string sPrivateKey =GetKeyFromName("测试",true);
Console.WriteLine("发送方为:A");
Console.Write("电子文件路径为:");
Console.WriteLine(sFilePath);
Console.Write("电子文件转换后的哈希值:");
Console.WriteLine(TransformByteToString(bHash));
Console.Write("生成的私钥:");
Console.WriteLine(sPrivateKey);
//用私钥生成数字签名
byte[] bDigiol = EncryptHash(sPrivateKey,bHash);
Console.Write("生成的数字签名为:");
Console.WriteLine(GetString(bDigiol));
Console.WriteLine("接收方接受数据:");
string sFileCopyPath = @"c:\KevinCopy.txt";
File.Copy(sFilePath,sFileCopyPath,true);
Console.WriteLine("是否同意篡改文件?");
string sChange =string.Empty;
byte[] bGetHash=null;
do
{
sChange =Console.ReadLine();
}while(sChange!="Y" && sChange !="N");
if(sChange =="N")
{
Console.WriteLine("接收方开始接收数据.....");
Console.WriteLine("接收方:B");
Console.Write("接收文件存放地址:");
Console.WriteLine(sFileCopyPath);
bGetHash =GetFileHash(sFileCopyPath);
Console.Write("转换后的哈希值:");
Console.WriteLine(GetString(bGetHash));
}
else if(sChange=="Y")
{
Console.WriteLine("正在篡改文件.....");
StreamWriter sws = new StreamWriter(sFileCopyPath);
sws.WriteLine("this documeny have been modified!");
sws.Close();
Console.WriteLine("接收方开始接收数据.....");
Console.WriteLine("接收方:B");
Console.Write("接收文件存放地址:");
Console.WriteLine(sFileCopyPath);
bGetHash =GetFileHash(sFileCopyPath);
Console.Write("转换后的哈希值:");
Console.WriteLine(GetString(bGetHash));
}
Console.Write("生成的公钥:");
Console.WriteLine(sPublicKey);
//使用公钥进行验证
if(DecryptHash(sPublicKey,bGetHash,bDigiol))
{
Console.WriteLine("验证成功,该文件没有被篡改!");
}
else
{
Console.WriteLine("验证失败,文件已被篡改!");
}
Console.ReadLine();
}
/// <summary>
/// 用于把文件用MD5进行加密,返回文件的哈希值
/// </summary>
/// <param name="sFilePath">文件的路径</param>
/// <returns>文件的哈希值</returns>
public static byte[] GetFileHash(string sFilePath)
{
try
{
//根据文件路径读取文件,得到一个FileStream流
FileStream fStream =File.OpenRead(sFilePath);
//生成MD5加密器
System.Security.Cryptography.HashAlgorithm hMD5Th = System.Security.Cryptography.HashAlgorithm.Create("MD5");
//用MD5加密器加密文件,得到哈希字节数组
byte[] bFileByte = hMD5Th.ComputeHash(fStream);
//关闭读取文件流
fStream.Close();
//返回哈希数组
return bFileByte;
}
//异常处理
catch(System.IO.IOException ex)
{
Console.WriteLine("When thrasaction has Error: "+ ex.Message);
return null;
}
}
/// <summary>
/// 用于把Byte数组转换成string字符串
/// </summary>
/// <param name="bByTransform">用于转换的Byte数组</param>
/// <returns>转换后的字符串</returns>
public static string TransformByteToString(byte[] bByTransform)
{
//用于串联各个字节转成的字符
System.Text.StringBuilder sbData =new System.Text.StringBuilder();
if(bByTransform !=null && bByTransform.Length >0)
{
foreach(byte b in bByTransform)
{
sbData.Append(b.ToString("X"));
}
}
return sbData.ToString();
}
/// <summary>
/// 转化Byte数组
/// </summary>
/// <param name="bBytes">用于转换的Byte数组</param>
/// <returns>转换后的字符串</returns>
public static string GetString(byte[] bBytes)
{
if(bBytes!=null && bBytes.Length>0)
{
//转化字节数组
return BitConverter.ToString(bBytes);
}
else
{
return "";
}
}
/// <summary>
/// 生成公钥或者私钥
/// </summary>
/// <param name="sName">如果生成的是私钥,则提供私钥的名称</param>
/// <param name="blKeyType">确定生成私钥或者公钥,True为私钥,False为公钥</param>
/// <returns>生成的密钥</returns>
public static string GetKeyFromName(string sName,bool blKeyType)
{
//参数容器
System.Security.Cryptography.CspParameters cp = new System.Security.Cryptography.CspParameters();
//提供的参数
cp.KeyContainerName =sName;
System.Security.Cryptography.RSACryptoServiceProvider RSA = new System.Security.Cryptography.RSACryptoServiceProvider(cp);
return RSA.ToXmlString(blKeyType);
}
/// <summary>
/// 对文件转换后的哈希数组生成数字签名
/// </summary>
/// <param name="sPrivateKeyName">提供的私钥名称</param>
/// <param name="bFileBytes">用于设置的文件哈希数组</param>
/// <returns>哈希数组生成的数字签名</returns>
public static byte[] EncryptHash(string sPrivateKeyName,byte[] bFileBytes)
{
//实例化加密服务提供程序
System.Security.Cryptography.RSACryptoServiceProvider RSA = new System.Security.Cryptography.RSACryptoServiceProvider();
//通过指定的私钥重构加密服务提供程序
RSA.FromXmlString(sPrivateKeyName);
//创建RSAPKCS1.5版的数字签名实例
System.Security.Cryptography.RSAPKCS1SignatureFormatter RSAFormater = new System.Security.Cryptography.RSAPKCS1SignatureFormatter(RSA);
//设置用MD5加密算法进行签名
RSAFormater.SetHashAlgorithm("MD5");
return RSAFormater.CreateSignature(bFileBytes);
}
/// <summary>
/// 对数据签名用公钥进行验证
/// </summary>
/// <param name="sPublicKey">用于验证的公钥</param>
/// <param name="bFileBytes">要验证的文件哈希</param>
/// <param name="electronicSignature">要验证的数据签名</param>
/// <returns>是否验证成功</returns>
public static bool DecryptHash(string sPublicKey,byte[] bFileBytes,byte[] electronicSignature)
{
//实例化加密服务提供程序
System.Security.Cryptography.RSACryptoServiceProvider RSA = new System.Security.Cryptography.RSACryptoServiceProvider();
//通过指定的公钥重构加密服务提供程序
RSA.FromXmlString(sPublicKey);
//验证RSAPKCS1.5版的数字签名实例
System.Security.Cryptography.RSAPKCS1SignatureDeformatter RSADeformatter = new System.Security.Cryptography.RSAPKCS1SignatureDeformatter(RSA);
////设置用MD5加密算法进行验证
RSADeformatter.SetHashAlgorithm("MD5");
return RSADeformatter.VerifySignature(bFileBytes,electronicSignature);
}