带文件IO的解密过程
Decryption process with file IO
我正在尝试制作一个关于密码管理器的控制台应用程序。它具有加密和解密输入的能力,以增加安全性。但是我在解密数据时遇到错误。
更新代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Security.Cryptography;
using System.Text.RegularExpressions;
namespace ProjectNumeroUno
{
internal class Program
{
static void Main(string[] args)
{
string[] vs = { };
Console.Write("Welcome to your personal password database.\nData will be protected, and cannot be accessed directly.\nVery personalized and secure!\n\n1.New Data entry\n2.Display and search\n3.exit\nEnter your option: ");
string option = Console.ReadLine();
string path = @"D:\Pass.txt";
while (option != "3")
{
if (option == "1")
{
Console.Write("Enter website: ");
string url = Console.ReadLine();
Console.Write("Enter username: ");
string usr = Console.ReadLine();
Console.Write("Enter password: ");
string pwd = Console.ReadLine();
string mmm = "URL: " + url + " Username: " + usr + " Password: " + pwd;
using (Aes Entry = Aes.Create())
{
Entry.Key = Encoding.Default.GetBytes(new string('j', 16));
Entry.IV = Encoding.Default.GetBytes(new string('j', 16));
byte[] encrypted = EncryptionOfContent(mmm, Entry.Key, Entry.IV);
using (StreamWriter sw = File.AppendText(path))
{
sw.WriteLine(Encoding.Default.GetString(encrypted));
}
}
}
else if (option == "2")
{
try
{
string[] lines = Regex.Split(File.ReadAllText(path), "\r\n|\r|\n");
byte[][] lineData = lines.Select(l => Encoding.Default.GetBytes(l)).Where(l => l.Length > 0).ToArray();
foreach (var data in lineData)
{
using (Aes entry = Aes.Create())
{
entry.Key = Encoding.Default.GetBytes(new string('j', 16));
entry.IV = Encoding.Default.GetBytes(new string('j', 16));
string decrypted = DecryptionOfContent(data, entry.Key, entry.IV);
vs.Append(decrypted);
Console.WriteLine(decrypted);
}
}
}
catch (IOException e)
{
Console.WriteLine("The file could not be read:");
Console.WriteLine(e.Message);
}
}
Console.Write("\n1.New Data entry\n2.Display and search\n3.exit\nEnter your option: ");
option = Console.ReadLine();
}
}
static byte[] EncryptionOfContent(string plainText, byte[] Key, byte[] IV)
{
// Check arguments.
if (plainText == null || plainText.Length <= 0)
throw new ArgumentNullException("plainText");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
if (IV == null || IV.Length <= 0)
throw new ArgumentNullException("IV");
byte[] encrypted;
// Create an Aes object
// with the specified key and IV.
using (Aes aesAlg = Aes.Create())
{
aesAlg.Key = Key;
aesAlg.IV = IV;
// Create an encryptor to perform the stream transform.
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
// Create the streams used for encryption.
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
//Write all data to the stream.
swEncrypt.Write(plainText);
}
encrypted = msEncrypt.ToArray();
}
}
}
// Return the encrypted bytes from the memory stream.
return encrypted;
}
static string DecryptionOfContent(byte[] cipherText, byte[] Key, byte[] IV)
{
// Check arguments.
if (cipherText == null || cipherText.Length <= 0)
throw new ArgumentNullException("cipherText");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
if (IV == null || IV.Length <= 0)
throw new ArgumentNullException("IV");
// Declare the string used to hold
// the decrypted text.
string plaintext = null;
// Create an Aes object
// with the specified key and IV.
using (Aes aesAlg = Aes.Create())
{
aesAlg.Key = Key;
aesAlg.IV = IV;
// Create a decryptor to perform the stream transform.
ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
// Create the streams used for decryption.
using (MemoryStream msDecrypt = new MemoryStream(cipherText))
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
{
// Read the decrypted bytes from the decrypting stream
// and place them in a string.
plaintext = srDecrypt.ReadToEnd();
}
}
}
}
return plaintext;
}
}
}
选项 1,似乎工作得很好,当涉及到显示数据时,它在从数据数组中删除尾随的“\n”或“10”和“13”字节后工作。但是,如果我尝试另一个输入,第一个数据和第二个数据之间会有一组“13”和“10”,这会增加字节大小,并且在 [=30 时返回错误=].
错误:
我仍然想要不同输入之间的“\n”,以区分输入,而不是混淆打印。但我该怎么做呢?如何增加字节大小,使其不会导致异常错误?我试过 aesAlg.Blocksize += 2;这也不起作用。
编辑:“如果加密输出不是单行怎么办”问题
这就是呃,我有4个输入,但是加密后,有一个额外的行,就像加密里面有“\n”一样smh。它现在抛出另一个异常。虽然这个错误大约每 5-10 次出现一次,但有时,加密本身会失控,有时它会在加密后开始写入汉字。 :\
您需要将您的加密文本拆分成不带行结束字符的单独数组,然后对每一行进行解密:
string[] lines = Regex.Split(File.ReadAllText(path), "\r\n|\r|\n");
byte[][] lineData = lines.Select(l => Encoding.Default.GetBytes(l)).Where(l => l.Length > 0).ToArray();
foreach (var data in lineData)
{
using Aes entry = Aes.Create();
entry.Key = Encoding.Default.GetBytes(new string('j', 16));
entry.IV = Encoding.Default.GetBytes(new string('j', 16));
string decrypted = DecryptionOfContent(data, entry.Key, entry.IV);
Console.WriteLine(decrypted);
}
您可以考虑更改以下几项内容:
- 您想使用换行符来分隔不同的输入,但您的代码没有考虑到加密数据本身可能包含换行符。
- 由于您使用
WriteLine
写入文件,您最好使用 ReadLine
读取文件,这样您就不需要自己处理换行符。
对于 #1,您可以将 Base64 编码的字符串写入您的文件:
byte[] encrypted = EncryptionOfContent(mmm, Entry.Key, Entry.IV);
...
sw.WriteLine(Convert.ToBase64String(encrypted));
对于 #2,您可以更改读取文件的方式:
var inputs = File.ReadAllLines(path);
foreach (var input in inputs)
{
var data = Convert.FromBase64String(input);
...
string decrypted = DecryptionOfContent(data, Entry.Key, Entry.IV);
}
我正在尝试制作一个关于密码管理器的控制台应用程序。它具有加密和解密输入的能力,以增加安全性。但是我在解密数据时遇到错误。
更新代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Security.Cryptography;
using System.Text.RegularExpressions;
namespace ProjectNumeroUno
{
internal class Program
{
static void Main(string[] args)
{
string[] vs = { };
Console.Write("Welcome to your personal password database.\nData will be protected, and cannot be accessed directly.\nVery personalized and secure!\n\n1.New Data entry\n2.Display and search\n3.exit\nEnter your option: ");
string option = Console.ReadLine();
string path = @"D:\Pass.txt";
while (option != "3")
{
if (option == "1")
{
Console.Write("Enter website: ");
string url = Console.ReadLine();
Console.Write("Enter username: ");
string usr = Console.ReadLine();
Console.Write("Enter password: ");
string pwd = Console.ReadLine();
string mmm = "URL: " + url + " Username: " + usr + " Password: " + pwd;
using (Aes Entry = Aes.Create())
{
Entry.Key = Encoding.Default.GetBytes(new string('j', 16));
Entry.IV = Encoding.Default.GetBytes(new string('j', 16));
byte[] encrypted = EncryptionOfContent(mmm, Entry.Key, Entry.IV);
using (StreamWriter sw = File.AppendText(path))
{
sw.WriteLine(Encoding.Default.GetString(encrypted));
}
}
}
else if (option == "2")
{
try
{
string[] lines = Regex.Split(File.ReadAllText(path), "\r\n|\r|\n");
byte[][] lineData = lines.Select(l => Encoding.Default.GetBytes(l)).Where(l => l.Length > 0).ToArray();
foreach (var data in lineData)
{
using (Aes entry = Aes.Create())
{
entry.Key = Encoding.Default.GetBytes(new string('j', 16));
entry.IV = Encoding.Default.GetBytes(new string('j', 16));
string decrypted = DecryptionOfContent(data, entry.Key, entry.IV);
vs.Append(decrypted);
Console.WriteLine(decrypted);
}
}
}
catch (IOException e)
{
Console.WriteLine("The file could not be read:");
Console.WriteLine(e.Message);
}
}
Console.Write("\n1.New Data entry\n2.Display and search\n3.exit\nEnter your option: ");
option = Console.ReadLine();
}
}
static byte[] EncryptionOfContent(string plainText, byte[] Key, byte[] IV)
{
// Check arguments.
if (plainText == null || plainText.Length <= 0)
throw new ArgumentNullException("plainText");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
if (IV == null || IV.Length <= 0)
throw new ArgumentNullException("IV");
byte[] encrypted;
// Create an Aes object
// with the specified key and IV.
using (Aes aesAlg = Aes.Create())
{
aesAlg.Key = Key;
aesAlg.IV = IV;
// Create an encryptor to perform the stream transform.
ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);
// Create the streams used for encryption.
using (MemoryStream msEncrypt = new MemoryStream())
{
using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
//Write all data to the stream.
swEncrypt.Write(plainText);
}
encrypted = msEncrypt.ToArray();
}
}
}
// Return the encrypted bytes from the memory stream.
return encrypted;
}
static string DecryptionOfContent(byte[] cipherText, byte[] Key, byte[] IV)
{
// Check arguments.
if (cipherText == null || cipherText.Length <= 0)
throw new ArgumentNullException("cipherText");
if (Key == null || Key.Length <= 0)
throw new ArgumentNullException("Key");
if (IV == null || IV.Length <= 0)
throw new ArgumentNullException("IV");
// Declare the string used to hold
// the decrypted text.
string plaintext = null;
// Create an Aes object
// with the specified key and IV.
using (Aes aesAlg = Aes.Create())
{
aesAlg.Key = Key;
aesAlg.IV = IV;
// Create a decryptor to perform the stream transform.
ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);
// Create the streams used for decryption.
using (MemoryStream msDecrypt = new MemoryStream(cipherText))
{
using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (StreamReader srDecrypt = new StreamReader(csDecrypt))
{
// Read the decrypted bytes from the decrypting stream
// and place them in a string.
plaintext = srDecrypt.ReadToEnd();
}
}
}
}
return plaintext;
}
}
}
选项 1,似乎工作得很好,当涉及到显示数据时,它在从数据数组中删除尾随的“\n”或“10”和“13”字节后工作。但是,如果我尝试另一个输入,第一个数据和第二个数据之间会有一组“13”和“10”,这会增加字节大小,并且在 [=30 时返回错误=].
错误:
我仍然想要不同输入之间的“\n”,以区分输入,而不是混淆打印。但我该怎么做呢?如何增加字节大小,使其不会导致异常错误?我试过 aesAlg.Blocksize += 2;这也不起作用。
编辑:“如果加密输出不是单行怎么办”问题
这就是呃,我有4个输入,但是加密后,有一个额外的行,就像加密里面有“\n”一样smh。它现在抛出另一个异常。虽然这个错误大约每 5-10 次出现一次,但有时,加密本身会失控,有时它会在加密后开始写入汉字。 :\
您需要将您的加密文本拆分成不带行结束字符的单独数组,然后对每一行进行解密:
string[] lines = Regex.Split(File.ReadAllText(path), "\r\n|\r|\n");
byte[][] lineData = lines.Select(l => Encoding.Default.GetBytes(l)).Where(l => l.Length > 0).ToArray();
foreach (var data in lineData)
{
using Aes entry = Aes.Create();
entry.Key = Encoding.Default.GetBytes(new string('j', 16));
entry.IV = Encoding.Default.GetBytes(new string('j', 16));
string decrypted = DecryptionOfContent(data, entry.Key, entry.IV);
Console.WriteLine(decrypted);
}
您可以考虑更改以下几项内容:
- 您想使用换行符来分隔不同的输入,但您的代码没有考虑到加密数据本身可能包含换行符。
- 由于您使用
WriteLine
写入文件,您最好使用ReadLine
读取文件,这样您就不需要自己处理换行符。
对于 #1,您可以将 Base64 编码的字符串写入您的文件:
byte[] encrypted = EncryptionOfContent(mmm, Entry.Key, Entry.IV);
...
sw.WriteLine(Convert.ToBase64String(encrypted));
对于 #2,您可以更改读取文件的方式:
var inputs = File.ReadAllLines(path);
foreach (var input in inputs)
{
var data = Convert.FromBase64String(input);
...
string decrypted = DecryptionOfContent(data, Entry.Key, Entry.IV);
}