/// <summary>
///
/// </summary>
/// <param name="originalFileName"></param>
/// <param name="encryptedFileName"></param>
/// <param name="senderCertificate"></param>
/// <param name="receiverCertificate"></param>
private static void EncryptFile(string originalFileName, string encryptedFileName, X509Certificate2 senderCertificate, X509Certificate2 receiverCertificate)
{
try
{
//生成DES Key用以加密文件内容
byte[] desKeys = KeyHelper.GenerateDESKey();
//保护DES密钥,制作签名
//DES密钥(8字节数组)需要先转换成十六进制的字符串(16字节数组)后,再签名
byte[] encryptedKeys = SignBeforeEncryptAndEncryptSignature(Utility.GetBytes(Utility.BytesToHexString(desKeys).ToUpper()), senderCertificate, receiverCertificate);
//转换为Base64字节数组
encryptedKeys = Utility.ConvertToBase64Bytes(encryptedKeys);
//创建输出文件,如果文件存在则覆盖
using (BinaryWriter binWriter =
new BinaryWriter(File.Open(encryptedFileName, FileMode.Create, FileAccess.Write,FileShare.Read), Utility.GetEncoding()))
{
//写入密钥密文的长度
binWriter.Write(Utility.GetBytes(string.Format("{0:D10}", encryptedKeys.Length)));
//写入密钥密文数据
binWriter.Write(encryptedKeys);
//打开输入文件加密,并写入目标文件
using (BinaryReader binReader =
new BinaryReader(File.Open(originalFileName, FileMode.Open, FileAccess.Read, FileShare.Read), Utility.GetEncoding()))
{
while (true)
{
byte[] originalData = binReader.ReadBytes(Utility.MAX_ENCRYPTODECRYPT_BYTESCOUNT);
if (originalData.Length == 0)
break;
//加密originalData
byte[] encryptedData = EncryptHelper.EncryptByDES(originalData, desKeys, null);
binWriter.Write(encryptedData);
}
}
binWriter.Flush();
}
}
catch
{
throw;
}
}
/// <summary>
///
/// </summary>
/// <param name="originalFileName"></param>
/// <param name="decryptedFileName"></param>
/// <param name="receiverCertificate"></param>
private static void DecryptFile(string originalFileName, string decryptedFileName, X509Certificate2 receiverCertificate)
{
try
{
using (BinaryReader binReader =
new BinaryReader(File.Open(originalFileName, FileMode.Open, FileAccess.Read,FileShare.Read), Utility.GetEncoding()))
{
//读取签名部分长度
int signatureDataLen;
if (!Int32.TryParse(Utility.GetString(binReader.ReadBytes(10)), out signatureDataLen))
throw new InvalidDataException("源文件"+originalFileName+"数据无效。");
//验证签名并获取用于解密文件内容的DES Key
//解密出的DES Key数据需要先从十六进制的字符串(16字节数组)转换成DES密钥(8字节数组)
byte[] dataToVerify = binReader.ReadBytes(signatureDataLen);
dataToVerify = Utility.ConvertFromBase64Bytes(dataToVerify);
byte[] desKeys = DecryptSignatureAndVerifyAfterDecrypt(dataToVerify,receiverCertificate);
desKeys = Utility.HexStringToBytes(Utility.GetString(desKeys));
//创建输出文件,写入解密内容
using (BinaryWriter binWriter =
new BinaryWriter(File.Open(decryptedFileName, FileMode.Create, FileAccess.Write,FileShare.Read), Utility.GetEncoding()))
{
binWriter.Seek(0, SeekOrigin.Begin);
while (true)
{
byte[] originalData = binReader.ReadBytes(Utility.MAX_ENCRYPTODECRYPT_BYTESCOUNT);
if (originalData.Length == 0)
break;
//解密originalData
byte[] decryptedData = EncryptHelper.DecryptByDES(originalData, desKeys, null);
binWriter.Write(decryptedData);
}
binWriter.Flush();
}
}
}
catch
{
throw;
}
}
/// <summary>
///
/// </summary>
/// <param name="originalData"></param>
/// <param name="senderCertificate"></param>
/// <param name="receiverCertificate"></param>
/// <returns></returns>
private static byte[] SignBeforeEncryptAndEncryptSignature(byte[] originalData, X509Certificate2 senderCertificate, X509Certificate2 receiverCertificate)
{
try
{
//****************************************************
//使用发送者证书私钥PrivateKey签名originalData
if (!senderCertificate.HasPrivateKey)
throw new NotSupportedException("证书 "+senderCertificate.Subject+" 不含私钥,无法执行签名!");
byte[] signedData = SignHelper.HashAndSignBytes(originalData, senderCertificate.PrivateKey, new SHA1CryptoServiceProvider());
//****************************************************
//创建字节数组用于TripleDES加密
byte[] plainData = new byte[8 + originalData.Length + signedData.Length + senderCertificate.RawData.Length];
Array.Copy(BitConverter.GetBytes(originalData.Length), 0, plainData, 0, 4); //写入明文数据长度,4字节 Int32
Array.Copy(BitConverter.GetBytes((short)signedData.Length), 0, plainData, 4, 2); //写入签名数据长度,2字节 Int16
Array.Copy(BitConverter.GetBytes((short)senderCertificate.RawData.Length), 0, plainData, 6, 2); //
写入发送者证书的原始数据的长度,2字节 Int16
Array.Copy(originalData, 0, plainData, 8, originalData.Length); //写入明文数据
Array.Copy(signedData, 0, plainData, 8 + originalData.Length, signedData.Length); //写入签名数据
Array.Copy(senderCertificate.RawData, 0, plainData, 8 + originalData.Length + signedData.Length, senderCertificate.RawData.Length); //
写入发送者证书的原始数据
//使用TripleDES对称密钥加密
byte[] tDESKeys = KeyHelper.GenerateTripleDESKey(128); //生成TripleDES Key 128位 16字节
byte[] IV = KeyHelper.GenerateTripleDESIV(); //生成TripleDES IV 64位 8字节
byte[] encryptedData = EncryptHelper.EncryptByTripleDES(plainData, tDESKeys, IV);
//****************************************************
//使用接收者证书公钥PublicKey加密对称密钥
plainData = new byte[24];
Array.Copy(tDESKeys, 0, plainData, 0, 16); //写入对称密钥tDESKeys
Array.Copy(IV, 0, plainData, 16, 8); //写入向量IV
byte[] encryptedKeys = EncryptHelper.EncryptByRSA(plainData, receiverCertificate.PublicKey.Key, false);
//****************************************************
//生成最终数据
byte[] signatureData = new byte[6 + encryptedData.Length + encryptedKeys.Length];
Array.Copy(BitConverter.GetBytes(encryptedData.Length), 0, signatureData, 0, 4); //写入数据密文数据长度,4字节 Int32
Array.Copy(BitConverter.GetBytes(encryptedKeys.Length), 0, signatureData, 4, 2); //写入密钥密文数据长度,2字节 Int16
Array.Copy(encryptedData, 0, signatureData, 6, encryptedData.Length); //写入数据密文数据
Array.Copy(encryptedKeys, 0, signatureData, 6 + encryptedData.Length, encryptedKeys.Length); //写入密钥密文数据
return signatureData;
}
catch
{
throw;
}
}
/// <summary>
///
/// </summary>
/// <param name="cipherData"></param>
/// <param name="receiverCertificate"></param>
/// <returns></returns>
private static byte[] DecryptSignatureAndVerifyAfterDecrypt(byte[] cipherData, X509Certificate2 receiverCertificate)
{
try
{
if (!receiverCertificate.HasPrivateKey)
throw new NotSupportedException("证书 " + receiverCertificate.Subject + " 不含私钥,无法解密签名!");
Int16 keysCipherLen = BitConverter.ToInt16(cipherData, 4); //密钥密文长度
Int32 signatureCipherLen = BitConverter.ToInt32(cipherData, 0); //签名密文长度
//****************************************************
//先解密密钥密文获取解密签名密文的TripleDES Key和IV
//****************************************************
byte[] keysCipherData = new byte[keysCipherLen];
Array.Copy(cipherData, 6+signatureCipherLen, keysCipherData, 0, keysCipherData.Length);
//使用接收者证书私钥PrivateKey解密对称密钥
byte[] keysPlainData = EncryptHelper.DecryptByRSA(keysCipherData, receiverCertificate.PrivateKey, false);
//获取TripleDES Key和IV
byte[] tDESKeys = new byte[16];
Array.Copy(keysPlainData, 0, tDESKeys, 0, 16);
byte[] IV = new byte[8];
Array.Copy(keysPlainData, 16, IV, 0, 8);
//****************************************************
//使用TripleDES Key和IV解密签名密文
//****************************************************
byte[] signatureCipherData = new byte[signatureCipherLen];
Array.Copy(cipherData, 6, signatureCipherData, 0, signatureCipherData.Length);
byte[] signaturePlainData = EncryptHelper.DecryptByTripleDES(signatureCipherData, tDESKeys, IV);
//****************************************************
//使用发送者证书PublicKey验证签名
//****************************************************
//原文
byte[] dataToVerify = new byte[BitConverter.ToInt32(signaturePlainData,0)];
Array.Copy(signaturePlainData, 8, dataToVerify, 0, dataToVerify.Length);
//签名
byte[] signedData = new byte[BitConverter.ToInt16(signaturePlainData, 4)];
Array.Copy(signaturePlainData, 8 +dataToVerify.Length , signedData, 0, signedData.Length);
//发送方证书
byte[] certRawData = new byte[BitConverter.ToInt16(signaturePlainData,6)];
Array.Copy(signaturePlainData, 8 + dataToVerify.Length + signedData.Length, certRawData, 0,certRawData.Length);
X509Certificate2 senderCertificate = new X509Certificate2(certRawData);
if(!SignHelper.VerifySignedHash(dataToVerify,signedData,senderCertificate.PublicKey.Key,new SHA1CryptoServiceProvider()))
throw new InvalidDataException("签名验证失败。");
return dataToVerify;
}
catch
{
throw;
}
}
C#如何使用数字签名?
最新推荐文章于 2023-08-10 10:44:00 发布