这是我的加密/解密代码。它运行良好但在加密文件时崩溃,即使它仍然加密它。同样,程序在解密文件时崩溃,即使它对文件进行解密也是如此。
加密或解密后,程序会在您的应用程序中发出错误“未处理的异常”。它还说“道路不是合法的形式”。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Security;
using System.Security.Cryptography;
using System.Diagnostics;
using Microsoft.VisualBasic;
namespace Encryption_Decryption_Tool
{
public partial class frmMain : Form
{
string strFileToEncrypt, strFileToDecrypt, strOutputEncrypt, strOutputDecrypt;
System.IO.FileStream fsInput;
System.IO.FileStream fsOutput;
public frmMain()
{
InitializeComponent();
}
private byte[] CreateKey(string strPassword)
{
//Convert strPassword to an array and store in chrData.
char[] chrData = strPassword.ToCharArray();
//Use intLength to get strPassword size.
int intLength = chrData.GetUpperBound(0);
//Declare bytDataToHash and make it the same size as chrData.
byte[] bytDataToHash = new byte[intLength + 1];
//Use For Next to convert and store chrData into bytDataToHash.
for (int i = 0; i <= chrData.GetUpperBound(0); i++)
{
bytDataToHash[i] = Convert.ToByte(chrData[i]);
}
//Declare what hash to use.
System.Security.Cryptography.SHA512Managed SHA512 = new System.Security.Cryptography.SHA512Managed();
//Declare bytResult, Hash bytDataToHash and store it in bytResult.
byte[] bytResult = SHA512.ComputeHash(bytDataToHash);
//Declare bytKey(31). It will hold 256 bits.
byte[] bytKey = new byte[32];
//Use For Next to put a specific size (256 bits) of
//bytResult into bytKey. The 0 To 31 will put the first 256 bits
//of 512 bits into bytKey.
for (int i = 0; i <= 31; i++)
{
bytKey[i] = bytResult[i];
}
return bytKey;
//Return the key.
}
private byte[] CreateIV(string strPassword)
{
//Convert strPassword to an array and store in chrData.
char[] chrData = strPassword.ToCharArray();
//Use intLength to get strPassword size.
int intLength = chrData.GetUpperBound(0);
//Declare bytDataToHash and make it the same size as chrData.
byte[] bytDataToHash = new byte[intLength + 1];
//Use For Next to convert and store chrData into bytDataToHash.
for (int i = 0; i <= chrData.GetUpperBound(0); i++)
{
bytDataToHash[i] = Convert.ToByte(chrData[i]);
}
//Declare what hash to use.
System.Security.Cryptography.SHA512Managed SHA512 = new System.Security.Cryptography.SHA512Managed();
//Declare bytResult, Hash bytDataToHash and store it in bytResult.
byte[] bytResult = SHA512.ComputeHash(bytDataToHash);
//Declare bytIV(15). It will hold 128 bits.
byte[] bytIV = new byte[16];
//Use For Next to put a specific size (128 bits) of
//bytResult into bytIV. The 0 To 30 for bytKey used the first 256 bits.
//of the hashed password. The 32 To 47 will put the next 128 bits into bytIV.
for (int i = 32; i <= 47; i++)
{
bytIV[i - 32] = bytResult[i];
}
return bytIV;
//return the IV
}
private enum CryptoAction
{
//Define the enumeration for CryptoAction.
ActionEncrypt = 1,
ActionDecrypt = 2
}
private void EncryptOrDecryptFile(string strInputFile, string strOutputFile, byte[] bytKey, byte[] bytIV, CryptoAction Direction)
{
//In case of errors.
try
{
//Setup file streams to handle input and output.
fsInput = new System.IO.FileStream(strInputFile, FileMode.Open, FileAccess.Read);
fsOutput = new System.IO.FileStream(strOutputFile, FileMode.OpenOrCreate, FileAccess.Write);
fsOutput.SetLength(0);
//make sure fsOutput is empty
//Declare variables for encrypt/decrypt process.
byte[] bytBuffer = new byte[4097];
//holds a block of bytes for processing
long lngBytesProcessed = 0;
//running count of bytes processed
long lngFileLength = fsInput.Length;
//the input file's length
int intBytesInCurrentBlock = 0;
//current bytes being processed
CryptoStream csCryptoStream = null;
//Declare your CryptoServiceProvider.
System.Security.Cryptography.RijndaelManaged cspRijndael = new System.Security.Cryptography.RijndaelManaged();
//Setup Progress Bar
pbStatus.Value = 0;
pbStatus.Maximum = 100;
//Determine if ecryption or decryption and setup CryptoStream.
switch (Direction)
{
case CryptoAction.ActionEncrypt:
csCryptoStream = new CryptoStream(fsOutput, cspRijndael.CreateEncryptor(bytKey, bytIV), CryptoStreamMode.Write);
break;
case CryptoAction.ActionDecrypt:
csCryptoStream = new CryptoStream(fsOutput, cspRijndael.CreateDecryptor(bytKey, bytIV), CryptoStreamMode.Write);
break;
}
//Use While to loop until all of the file is processed.
while (lngBytesProcessed < lngFileLength)
{
//Read file with the input filestream.
intBytesInCurrentBlock = fsInput.Read(bytBuffer, 0, 4096);
//Write output file with the cryptostream.
csCryptoStream.Write(bytBuffer, 0, intBytesInCurrentBlock);
//Update lngBytesProcessed
lngBytesProcessed = lngBytesProcessed + Convert.ToInt64(intBytesInCurrentBlock);
//Update Progress Bar
pbStatus.Value = Convert.ToInt32((lngBytesProcessed / lngFileLength) * 100);
}
//Close FileStreams and CryptoStream.
csCryptoStream.Close();
fsInput.Close();
fsOutput.Close();
//If encrypting then delete the original unencrypted file.
if (Direction == CryptoAction.ActionEncrypt)
{
FileInfo fileOriginal = new FileInfo(strFileToEncrypt);
fileOriginal.Delete();
}
//If decrypting then delete the encrypted file.
if (Direction == CryptoAction.ActionDecrypt)
{
FileInfo fileEncrypted = new FileInfo(strFileToDecrypt);
fileEncrypted.Delete();
}
//Update the user when the file is done.
string Wrap = "\r\n";
if (Direction == CryptoAction.ActionEncrypt)
{
MessageBox.Show("Encryption Complete" + Wrap + Wrap + "Total bytes processed = " + lngBytesProcessed.ToString(), "Done", MessageBoxButtons.OK, MessageBoxIcon.Information);
//Update the progress bar and textboxes.
pbStatus.Value = 0;
txtFileToEncrypt.Text = "Click Browse to load file.";
txtPassEncrypt.Text = "";
txtConPassEncrypt.Text = "";
txtDestinationEncrypt.Text = "";
btnChangeEncrypt.Enabled = false;
btnEncrypt.Enabled = false;
}
else
{
//Update the user when the file is done.
MessageBox.Show("Decryption Complete" + Wrap + Wrap + "Total bytes processed = " + lngBytesProcessed.ToString(),"Done",MessageBoxButtons.OK,MessageBoxIcon.Information) ;
//Update the progress bar and textboxes.
pbStatus.Value = 0;
txtFileToDecrypt.Text = "Click Browse to load file.";
txtPassDecrypt.Text = "";
txtConPassDecrypt.Text = "";
txtDestinationDecrypt.Text = "";
btnChangeDecrypt.Enabled = false;
btnDecrypt.Enabled = false;
}
//Catch file not found error.
//if file not found
}
catch
{
MessageBox.Show("Please check to make sure the path and filename" + "are correct and if the file exists.", "Invalid Path or Filename", MessageBoxButtons.OK, MessageBoxIcon.Information);
//Catch all other errors. And delete partial files.
}
finally
{
fsInput.Close();
fsOutput.Close();
if (Direction == CryptoAction.ActionDecrypt)
{
FileInfo fileDelete = new FileInfo(txtDestinationDecrypt.Text);
fileDelete.Delete();
pbStatus.Value = 0;
txtPassDecrypt.Text = "";
txtConPassDecrypt.Text = "";
MessageBox.Show("Please check to make sure that you entered the correct" + "password.","Invalid Password", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
else
{
FileInfo fileDelete = new FileInfo(txtDestinationEncrypt.Text);
fileDelete.Delete();
pbStatus.Value = 0;
txtPassEncrypt.Text = "";
txtConPassEncrypt.Text = "";
MessageBox.Show("This file cannot be encrypted.", "File Cannot Be Encrypted", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
}
}
private void btnBrowseEncrypt_Click(object sender, EventArgs e)
{
//Setup the open dialog.
openFileDialog1.FileName = "";
openFileDialog1.Title = "Choose a file to encrypt";
openFileDialog1.InitialDirectory = "C:\\";
openFileDialog1.Filter = "All Files (*.*) | *.*";
//Find out if the user chose a file.
if (openFileDialog1.ShowDialog() == DialogResult.OK)
{
strFileToEncrypt = openFileDialog1.FileName;
txtFileToEncrypt.Text = strFileToEncrypt;
int iPosition = 0;
int i = 0;
//Get the position of the last "\" in the OpenFileDialog.FileName path.
//-1 is when the character your searching for is not there.
//IndexOf searches from left to right.
while (strFileToEncrypt.IndexOf('\\', i) != -1)
{
iPosition = strFileToEncrypt.IndexOf('\\', i);
i = iPosition + 1;
}
//Assign strOutputFile to the position after the last "\" in the path.
//This position is the beginning of the file name.
strOutputEncrypt = strFileToEncrypt.Substring(iPosition + 1);
//Assign S the entire path, ending at the last "\".
string S = strFileToEncrypt.Substring(0, iPosition + 1);
//Replace the "." in the file extension with "_".
strOutputEncrypt = strOutputEncrypt.Replace('.', '_');
//The final file name. XXXXX.encrypt
txtDestinationEncrypt.Text = S + strOutputEncrypt + ".encrypt";
//Update buttons.
btnEncrypt.Enabled = true;
btnChangeEncrypt.Enabled = true;
}
}
private void btnBrowseDecrypt_Click(object sender, EventArgs e)
{
//Setup the open dialog.
openFileDialog2.FileName = "";
openFileDialog2.Title = "Choose a file to decrypt";
openFileDialog2.InitialDirectory = "C:\\";
openFileDialog2.Filter = "Encrypted Files (*.encrypt) | *.encrypt";
//Find out if the user chose a file.
if (openFileDialog2.ShowDialog() == DialogResult.OK)
{
strFileToDecrypt = openFileDialog2.FileName;
txtFileToDecrypt.Text = strFileToDecrypt;
int iPosition = 0;
int i = 0;
//Get the position of the last "\" in the OpenFileDialog.FileName path.
//-1 is when the character your searching for is not there.
//IndexOf searches from left to right.
while (strFileToDecrypt.IndexOf('\\', i) != -1)
{
iPosition = strFileToDecrypt.IndexOf('\\', i);
i = iPosition + 1;
}
//strOutputFile = the file path minus the last 8 characters (.encrypt)
strOutputDecrypt = strFileToDecrypt.Substring(0, strFileToDecrypt.Length - 8);
//Assign S the entire path, ending at the last "\".
string S = strFileToDecrypt.Substring(0, iPosition + 1);
//Assign strOutputFile to the position after the last "\" in the path.
strOutputDecrypt = strOutputDecrypt.Substring((iPosition + 1));
//Replace "_" with "."
txtDestinationDecrypt.Text = S + strOutputDecrypt.Replace('_', '.');
//Update buttons
btnDecrypt.Enabled = true;
btnChangeDecrypt.Enabled = true;
}
}
private void btnChangeEncrypt_Click(object sender, EventArgs e)
{
//Setup up folder browser.
folderBrowserDialog1.Description = "Select a folder to place the encrypted file in.";
//If the user selected a folder assign the path to txtDestinationEncrypt.
if (folderBrowserDialog1.ShowDialog() == DialogResult.OK)
{
txtDestinationEncrypt.Text = folderBrowserDialog1.SelectedPath + "\\" + strOutputEncrypt + ".encrypt";
}
}
private void btnChangeDecrypt_Click(object sender, EventArgs e)
{
//Setup up folder browser.
folderBrowserDialog2.Description = "Select a folder for to place the decrypted file in.";
//If the user selected a folder assign the path to txtDestinationDecrypt.
if (folderBrowserDialog2.ShowDialog() == DialogResult.OK)
{
txtDestinationDecrypt.Text = folderBrowserDialog2.SelectedPath + "\\" + strOutputDecrypt.Replace('_', '.');
}
}
private void btnEncrypt_Click(object sender, EventArgs e)
{
//Make sure the password is correct.
if (txtConPassEncrypt.Text == txtPassEncrypt.Text)
{
//Declare variables for the key and iv.
//The key needs to hold 256 bits and the iv 128 bits.
byte[] bytKey = null;
byte[] bytIV = null;
//Send the password to the CreateKey function.
bytKey = CreateKey(txtPassEncrypt.Text);
//Send the password to the CreateIV function.
bytIV = CreateIV(txtPassEncrypt.Text);
//Start the encryption.
EncryptOrDecryptFile(strFileToEncrypt, txtDestinationEncrypt.Text, bytKey, bytIV, CryptoAction.ActionEncrypt);
}
else
{
MessageBox.Show ("Please re-enter your password.","Error",MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
txtPassEncrypt.Text = "";
txtConPassEncrypt.Text = "";
}
}
private void btnDecrypt_Click(object sender, EventArgs e)
{
//Make sure the password is correct.
if (txtConPassDecrypt.Text == txtPassDecrypt.Text)
{
//Declare variables for the key and iv.
//The key needs to hold 256 bits and the iv 128 bits.
byte[] bytKey = null;
byte[] bytIV = null;
//Send the password to the CreateKey function.
bytKey = CreateKey(txtPassDecrypt.Text);
//Send the password to the CreateIV function.
bytIV = CreateIV(txtPassDecrypt.Text);
//Start the decryption.
EncryptOrDecryptFile(strFileToDecrypt, txtDestinationDecrypt.Text, bytKey, bytIV, CryptoAction.ActionDecrypt);
}
else
{
MessageBox.Show ("Please re-enter your password.","Error",MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
txtPassDecrypt.Text = "";
txtConPassDecrypt.Text = "";
}
}
}
}
从重复的帖子中复制例外:
************* Exception Text **************
System.ArgumentException: The path is not of a legal form.
at System.IO.Path.NormalizePathFast(String path, Boolean fullCheck)
at System.IO.FileInfo..ctor(String fileName)
at Encryption_Decryption_Tool.frmMain.EncryptOrDecryptFile(String strInputFile, String strOutputFile, Byte[] bytKey, Byte[] bytIV, CryptoAction Direction) in C:\Users\baffa\Documents\Visual Studio 2008\Projects\Encryption_Decryption_Tool\Encryption_Decryption_Tool\Form1.cs:line 236
at Encryption_Decryption_Tool.frmMain.btnEncrypt_Click(Object sender, EventArgs e) in C:\Users\baffa\Documents\Visual Studio 2008\Projects\Encryption_Decryption_Tool\Encryption_Decryption_Tool\Form1.cs:line 373
at System.Windows.Forms.Control.OnClick(EventArgs e)
at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent)
at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.ButtonBase.WndProc(Message& m)
at System.Windows.Forms.Button.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
答案 0 :(得分:1)
您的输入或输出文件名不正确。
您在按钮点击事件中处理文件名的方式是大量的过度杀伤,并且可能导致问题。
使用标准的System.IO.Path方法会好得多。
具体来说,如果您只是尝试获取所选文件名并更改扩展名,则所有文件名操作代码都可以替换为一行:
txtDestinationEncrypt.Text = System.IO.Path.ChangeExtension(openFileDialog1.FileName, ".encrypt");
<强>更新强>
我已经大大清理了EncryptOrDecryptFile代码并验证它在两个方向上都能正常工作。我已将模块级fsInput和fsOutput移动到此方法中,并将主要参与者包含在using语句中。我还将finally区域中的错误代码移动到catch区域,这是它所属的位置。最后,我还在方法的开头添加了检查,以确保指定了文件并且该文件存在。
private void EncryptOrDecryptFile(string strInputFile, string strOutputFile, byte[] bytKey, byte[] bytIV, CryptoAction Direction)
{
//In case of errors.
try
{
if (string.IsNullOrEmpty(strInputFile))
{
MessageBox.Show("Please select an input file name", "Missing file name", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
if (!File.Exists(strInputFile))
{
MessageBox.Show(string.Format("The selected input file {0} does not exist.", strInputFile), "Invalid Path or Filename", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
if (string.IsNullOrEmpty(strOutputFile))
{
MessageBox.Show("Please select an output file name", "Missing file name", MessageBoxButtons.OK, MessageBoxIcon.Information);
return;
}
//holds a block of bytes for processing
long lngBytesProcessed = 0;
// Setup file streams to handle input and output.
using (var fsInput = new System.IO.FileStream(strInputFile, FileMode.Open, FileAccess.Read))
{
using (var fsOutput = new System.IO.FileStream(strOutputFile, FileMode.OpenOrCreate, FileAccess.Write))
{
//Declare your CryptoServiceProvider.
using (var cspRijndael = new System.Security.Cryptography.RijndaelManaged())
{
try
{
//Setup Progress Bar
pbStatus.Value = 0;
pbStatus.Maximum = 100;
cspRijndael.Key = bytKey;
cspRijndael.IV = bytIV;
ICryptoTransform oTransform = null;
// Determine if ecryption or decryption and setup transform.
switch (Direction)
{
case CryptoAction.ActionEncrypt:
oTransform = cspRijndael.CreateEncryptor();
break;
case CryptoAction.ActionDecrypt:
oTransform = cspRijndael.CreateDecryptor();
break;
default:
throw new Exception("Unknown Direction");
}
using (var csCryptoStream = new CryptoStream(fsOutput, oTransform, CryptoStreamMode.Write))
{
//Declare variables for encrypt/decrypt process.
byte[] bytBuffer = new byte[4097];
//running count of bytes processed
long lngFileLength = fsInput.Length;
//the input file's length
int intBytesInCurrentBlock = 0;
//Use While to loop until all of the file is processed.
while (lngBytesProcessed < lngFileLength)
{
//Read file with the input filestream.
intBytesInCurrentBlock = fsInput.Read(bytBuffer, 0, 4096);
//Write output file with the cryptostream.
csCryptoStream.Write(bytBuffer, 0, intBytesInCurrentBlock);
//Update lngBytesProcessed
lngBytesProcessed = lngBytesProcessed + Convert.ToInt64(intBytesInCurrentBlock);
//Update Progress Bar
pbStatus.Value = Convert.ToInt32((lngBytesProcessed / lngFileLength) * 100);
}
}
}
finally
{
if (cspRijndael != null)
{
// Clear the managed object
cspRijndael.Clear();
}
}
}
}
}
// If encrypting then delete the original unencrypted file.
if (Direction == CryptoAction.ActionEncrypt)
{
File.Delete(strFileToEncrypt);
}
// If decrypting then delete the encrypted file.
if (Direction == CryptoAction.ActionDecrypt)
{
File.Delete(strFileToDecrypt);
}
// Update the user when the file is done.
string Wrap = "\r\n";
if (Direction == CryptoAction.ActionEncrypt)
{
MessageBox.Show("Encryption Complete" + Wrap + Wrap + "Total bytes processed = " + lngBytesProcessed.ToString(), "Done", MessageBoxButtons.OK, MessageBoxIcon.Information);
//Update the progress bar and textboxes.
pbStatus.Value = 0;
txtFileToEncrypt.Text = "Click Browse to load file.";
txtPassEncrypt.Text = "";
txtConPassEncrypt.Text = "";
txtDestinationEncrypt.Text = "";
btnChangeEncrypt.Enabled = false;
btnEncrypt.Enabled = false;
}
else
{
//Update the user when the file is done.
MessageBox.Show("Decryption Complete" + Wrap + Wrap + "Total bytes processed = " + lngBytesProcessed.ToString(), "Done", MessageBoxButtons.OK, MessageBoxIcon.Information);
//Update the progress bar and textboxes.
pbStatus.Value = 0;
txtFileToDecrypt.Text = "Click Browse to load file.";
txtPassDecrypt.Text = "";
txtConPassDecrypt.Text = "";
txtDestinationDecrypt.Text = "";
btnChangeDecrypt.Enabled = false;
btnDecrypt.Enabled = false;
}
}
catch (Exception ex)
{
MessageBox.Show("Unknown exception occurred: " + ex.Message, "Unknown Exception", MessageBoxButtons.OK, MessageBoxIcon.Stop);
// Catch all other errors. And delete partial files.
if (Direction == CryptoAction.ActionDecrypt)
{
if (!string.IsNullOrEmpty(txtDestinationDecrypt.Text) && (File.Exists(txtDestinationDecrypt.Text)))
{
File.Delete(txtDestinationDecrypt.Text);
}
pbStatus.Value = 0;
txtPassDecrypt.Text = "";
txtConPassDecrypt.Text = "";
MessageBox.Show("Please check to make sure that you entered the correct password.", "Invalid Password", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
else
{
if (!string.IsNullOrEmpty(txtDestinationEncrypt.Text) && (File.Exists(txtDestinationEncrypt.Text)))
{
File.Delete(txtDestinationEncrypt.Text);
}
pbStatus.Value = 0;
txtPassEncrypt.Text = "";
txtConPassEncrypt.Text = "";
MessageBox.Show("This file cannot be encrypted.", "File Cannot Be Encrypted", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
}
}
}
我还修改了每个btnChange点击事件的第一部分,以验证在按下此按钮之前是否已选择文件:
private void btnChangeEncrypt_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(strOutputEncrypt))
{
MessageBox.Show("Please select a file to encrypt first", "Select File", MessageBoxButtons.OK, MessageBoxIcon.Stop);
return;
}
和
private void btnChangeDecrypt_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(strOutputDecrypt))
{
MessageBox.Show("Please select a file to decrypt first", "Select File", MessageBoxButtons.OK, MessageBoxIcon.Stop);
return;
}