X509数字证书之二:摘要和签名

摘要:发送方可以用X509数字证书对要发送文件的报文摘要进行签名,接收方再用X509数字证书验证发送方发出的文件是否被其他人篡改。

实际场景描述如下:

Bob有一份重要的商务文件要送给Alice和Jack;Alice和Jack在收到Bob的商务文件后,需要确认此商务文件的真实性,即要验证文件来源自Bob,而且要验证文件内容没有被篡改过。双方对文件校验的流程简单描述如下:

1. Bob 生成X509证书并导出公钥和私钥文件,私钥文件只留给自己;公钥文件发给Alice和Jack;

2. Bob先用Hash算法生成商务文件的报文摘要信息,然后再用私钥进行签名;

3. Bob把原商务文件、签名信息和公钥文件打包一起发给Alice和Jack;

4. Alick和Jack校验商务文件是否来自Bob,并且内容是否被篡改过。


流程图如下:



Alice和Jack收到打包的文件后,重新利用Hash算法对该商务文件计算报文摘要信息,然后再用Bob的公钥文件验证生成的报文摘要信息是否和Bob发送来的签名一致。如果一致,则说明商务文件没有被篡改,如果不一致,则说明商务文件被篡改。流程图如下:


程序代码如下:

1. Bob用SHA1算法计算报文摘要

string docFile = Server.MapPath("~/docx/DirectAccess_StepByStep.doc");
byte[] hashBytes;
using (FileStream fs = new FileStream(docFile, FileMode.Open))
{
    //计算报文的Hash值
    HashAlgorithm hashAlgorithm = HashAlgorithm.Create("SHA1");
    hashBytes = hashAlgorithm.ComputeHash(fs);
    fs.Close();
}
           
//Bob用自己(发送方)的私钥对报文摘要进行签名
//包含私钥文件的rsa算法初始化
string priKeyFile = Server.MapPath("~/certificate/WosMiddle.pfx");
X509Certificate2 certEncrypt = new X509Certificate2(priKeyFile, "123456");
byte[] signedHashBytes;
using (RSACryptoServiceProvider rsaProviderEncrypt = (RSACryptoServiceProvider)certEncrypt.PrivateKey)
{
    //给报文摘要进行签名
    RSAPKCS1SignatureFormatter signFormatter = new RSAPKCS1SignatureFormatter(rsaProviderEncrypt);
    signFormatter.SetHashAlgorithm("SHA1");
    signedHashBytes = signFormatter.CreateSignature(hashBytes);
    rsaProviderEncrypt.Dispose();
}

2. Alice和Jack接收方重新计算接收文件的报文摘要

/为了测试没有篡改和篡改两种情况,对文件内容可以只复制和人为修改。
string docFileNew = Server.MapPath("~/docx/DirectAccess_StepByStep_02.doc");
byte[] hashBytesNew;
using (FileStream fs = new FileStream(docFileNew, FileMode.Open))
{
    //计算报文的Hash值
    HashAlgorithm hashAlgorithm = HashAlgorithm.Create("SHA1");
    hashBytesNew = hashAlgorithm.ComputeHash(fs);
    fs.Close();
}

//由证书公钥文件验证
//初始化rsa算法
string pubKeyFile = Server.MapPath("~/certificate/WosMiddle-pubkey.cer");
X509Certificate2 cerDecrypt = new X509Certificate2(pubKeyFile);
bool isOk = false;
using (RSACryptoServiceProvider rsaProviderDecrypt = (RSACryptoServiceProvider)cerDecrypt.PublicKey.Key)
{
    //验证报文摘要和签名是否匹配
    RSAPKCS1SignatureDeformatter deFormatter = new RSAPKCS1SignatureDeformatter(rsaProviderDecrypt);
    deFormatter.SetHashAlgorithm("SHA1");
    isOk = deFormatter.VerifySignature(hashBytesNew, signedHashBytes);
    rsaProviderDecrypt.Dispose();
}

本示例代码经过实际测试(包括文件被改动和未被改动的两种情况),是正确运行的代码;此处共享,供开发人员参考。

你可能感兴趣的:(C#,网络安全)