/// <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; } }