Im trying to make a console app, about password manager. It has the capability to encrypt and decrypt the input, for added security. But im getting error when it comes to decryption of the data.
Updated code:
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;
}
}
}
option 1, seems to work just fine, and when it comes to displaying the data, it works after removing the trailing "\n", or the "10" and "13" bytes from the data array. However, if I were to try another input, there is going to be a set of "13", and "10" in between the first data and the second data, which increases the byte size, and is returning error when ran.
I still want the "\n" that is in between the different inputs, so as to differenciate the inputs, not to mix up the print. but how do I do that? How do I increase the byte size, so that It will not cause exception error? I tried aesAlg.Blocksize = 2; which is not working either.
EDIT: The "what if encryption output is not a single line" issue
This is where ugh, I have 4 inputs, but after encryption, there is a extra line, like the encryption has "\n" within it smh. It now throws another exception. though this error is like once every 5-10ish times, sometimes, the encryption itself gets off control, sometimes it starts writing chinese characters after encryption. :\
CodePudding user response:
You need to split up your encrypted text into separate arrays without the line ending characters, and then decrypt each line:
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);
}
CodePudding user response:
There are a couple things you could consider to change:
- You wanted to use new line separator to separate different inputs, but your code does not consider the encrypted data itself could contain new line separator.
- Since you write to the file using
WriteLine
, you should ideally read the file usingReadLine
so that you don't need to process new line separator yourself.
For #1, you can write Base64 encoded string to your file:
byte[] encrypted = EncryptionOfContent(mmm, Entry.Key, Entry.IV);
...
sw.WriteLine(Convert.ToBase64String(encrypted));
For #2, you can change how you read the file:
var inputs = File.ReadAllLines(path);
foreach (var input in inputs)
{
var data = Convert.FromBase64String(input);
...
string decrypted = DecryptionOfContent(data, Entry.Key, Entry.IV);
}