How to use aes_encrypt in C# Windows Form Application - c#

I have been mainly writing in PHP and only know one way to create an aes encryption for a variable:
aes_encrypt(variableName, 'SecretSalt')
I need to encrypt a variable in C# and I have tried a similar approach as in PHP but it is not working (I get an error "The name aes does not exist in current context"
Here is my current code in C#:
var username = txtusername.Text;
var password = txtpassword.Text;
var usernameAES = aes_encrypt(username, 'mySalt');
What is the correct way to use AES_ENCRYPT? I am sending the variable to a PHP Web Service
Update:
More C# code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net.Http;
using System.Net;
using System.IO;
using System.Threading;
private void Login()
{
if (String.IsNullOrEmpty(txtusername.Text))
{
MessageBox.Show("Please insert username");
}
if (String.IsNullOrEmpty(txtpassword.Text))
{
MessageBox.Show("Please insert password");
}
var Token = "TMMZC 77385 R8G2D6";
var username = txtusername.Text;
var password = txtpassword.Text;
var usernameAES = aes_encrypt(username, 'mySalt');
var url = "https://mydomain.co.za/LoginVerification.php?";
var var = "username=" + username + "&password=" + password + "&Token=" + Token Token;
var URL = url + var;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(URL);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Stream dataStream = response.GetResponseStream();
// Open the stream using a StreamReader for easy access.
StreamReader reader = new StreamReader(dataStream);
// Read the content.
var responseFromServer = reader.ReadToEnd();
//MessageBox.Show(responseFromServer);
// Display the content.
if (responseFromServer == "Allow")
{
//Open Form1
Form1 Form = new Form1();
Form.Show();
//CLose Password Form
Password PasswordForm = new Password();
PasswordForm.Close();
}

try this code
using System.Security.Cryptography;
using System.IO;
public string EncryptText(string input, string password)
{
// Get the bytes of the string
byte[] bytesToBeEncrypted = Encoding.UTF8.GetBytes(input);
byte[] passwordBytes = Encoding.UTF8.GetBytes(password);
// Hash the password with SHA256
passwordBytes = SHA256.Create().ComputeHash(passwordBytes);
byte[] bytesEncrypted = AES_Encrypt(bytesToBeEncrypted, passwordBytes);
string result = Convert.ToBase64String(bytesEncrypted);
return result;
}
public byte[] aes_encrypt(byte[] bytesToBeEncrypted, byte[] passwordBytes)
{
byte[] encryptedBytes = null;
// Set your salt here, change it to meet your flavor:
// The salt bytes must be at least 8 bytes.
byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
using (MemoryStream ms = new MemoryStream())
{
using (RijndaelManaged AES = new RijndaelManaged())
{
AES.KeySize = 256;
AES.BlockSize = 128;
var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
AES.Key = key.GetBytes(AES.KeySize / 8);
AES.IV = key.GetBytes(AES.BlockSize / 8);
AES.Mode = CipherMode.CBC;
using (var cs = new CryptoStream(ms, AES.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(bytesToBeEncrypted, 0, bytesToBeEncrypted.Length);
cs.Close();
}
encryptedBytes = ms.ToArray();
}
}
return encryptedBytes;
}

Related

Error in Key Size I'm Using for AES Encryption C#

I'm trying to use the Key below given to me by my client to encrypt a string
public static string EncryptKey()
{
var word = "9999";
var key = "Z1UbeuBT7Uu3SZinrq0vzuDVXBU5FbiKksopJswQGk81";
var iv = "KUNd9fhw48li2WUZ";
byte[] result = null;
byte[] wordBytes = Encoding.UTF8.GetBytes(word);
using (MemoryStream ms = new MemoryStream())
{
using (RijndaelManaged AES = new RijndaelManaged())
{
AES.Key = Convert.FromBase64String(key);
AES.IV = Encoding.UTF8.GetBytes(iv);
using (var cs = new CryptoStream(ms, AES.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(wordBytes, 0, wordBytes.Length);
cs.Close();
}
byte[] encryptedBytes = ms.ToArray();
result = encryptedBytes;
return Convert.ToBase64String(result);
}
}
}
but I get an error
System.Security.Cryptography.CryptographicException: 'Specified key is not a valid size for this algorithm.
The client has been using this Key.
What am I doing wrong?
My client uses
HttpServerUtility.UrlTokenDecode(string input);
for decoding the base64 string.
Hope this helps someone in the future.

Need to fix wrong encryption method in my c# web api

I need to correct an encryption method written in C#.
First, a little background: I am taking charge of an existing web application with an ecma6 / html frontend and c# web api .net standard 4.6 backend.
It has many integrations with different customers for user identification. Some of the integrations simply navigate to a customers URL to do a login process on the infrastructure of the customer, and then return to the app with an encripted user token in the URL's query string.
This token is encripted using AES256 encryption.
The backend is correctly decrypting the tokens, but when I tried to use the encryption routine to build a unit test, I discovered something is wrong. When I encrypt and then decrypt a message, the decryption routine throws the following error:
Unhandled Exception:
System.Security.Cryptography.CryptographicException: Length of the data to decrypt is invalid.
Input message is "key1=value1;key2=value2" (without the quotes)
Encrypted message I get is NzcrOTc3Kzk3Nys5NzcrOTc3Kzk3Nys5NzcrOVpsVHZ2NzF3NzcrOUZ6UVlRZ3Z2djcxSVlPKy92U0V6NzcrOVNqZFY3Nys5VHpBZA==
I need to correct the implementation error in the encryption method. The implementation of the decryption method shows expected behavior, and you'll notice a double Base64 decoding done on the encrypted string: this is given, as we are integrated with an already developed encryption routine done by a customer in PERL which we detected did double encoding.
I inspected the order of operations to see a mismatch among the encryption and decryption and I was unable to detect an inconsistency, so the need to ask for help.
The code I synthesized for this test is:
using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;
class MainClass {
public static void Main (string[] args) {
var secretKey = "This is my secret key";
var secretIV = "This is my secret iv";
var originalMessage = "key1=value1;key2=value2";
var userToken = Cryptography.EncryptAES256CBCBase64x2(originalMessage, secretKey, secretIV);
Console.WriteLine(userToken);
var unencryptedToken = Cryptography.DecryptAES256CBCBase64x2(userToken, secretKey, secretIV);
if (originalMessage == unencryptedToken)
Console.WriteLine("All fine!");
else
Console.WriteLine("Error!");
}
}
public static class Cryptography
{
public static string DecryptAES256CBCBase64x2(string base64EncryptedString, string secretKey, string secretIV)
{
base64EncryptedString = SaveBase64String(base64EncryptedString);
var keyBytes = Encoding.UTF8.GetBytes(secretKey);
var ivBytes = Encoding.UTF8.GetBytes(secretIV);
var hash = SHA256.Create();
var keyHash = hash.ComputeHash(keyBytes);
Array.Resize(ref keyHash, 32);
var keyHashString = string.Empty;
foreach (byte x in keyHash)
keyHashString += string.Format("{0:x2}", x);
keyHash = Encoding.UTF8.GetBytes(keyHashString.Substring(0, 32));
var ivHash = hash.ComputeHash(ivBytes);
Array.Resize(ref ivHash, 16);
var ivHashString = string.Empty;
foreach (byte x in ivHash)
ivHashString += string.Format("{0:x2}", x);
ivHash = Encoding.UTF8.GetBytes(ivHashString.Substring(0, 16));
// Create an RijndaelManaged object
// with the specified key and IV.
using (var rijAlg = new RijndaelManaged())
{
rijAlg.Padding = PaddingMode.PKCS7;
rijAlg.Mode = CipherMode.CBC;
rijAlg.Key = keyHash;
rijAlg.IV = ivHash;
var encryptedBytes =
Convert.FromBase64String(
Encoding.UTF8.GetString(
Convert.FromBase64String(base64EncryptedString)));
// Create a decryptor to perform the stream transform.
var decryptor = rijAlg.CreateDecryptor(rijAlg.Key, rijAlg.IV);
// Create the streams used for decryption.
using (var msDecrypt = new MemoryStream(encryptedBytes))
{
using (var csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
using (var srDecrypt = new StreamReader(csDecrypt))
{
// Read the decrypted bytes from the decrypting stream
// and place them in a string.
return srDecrypt.ReadToEnd();
}
}
}
}
}
public static string EncryptAES256CBCBase64x2(string baseString, string secretKey, string secretIV)
{
var keyBytes = Encoding.UTF8.GetBytes(secretKey);
var ivBytes = Encoding.UTF8.GetBytes(secretIV);
var hash = SHA256.Create();
var keyHash = hash.ComputeHash(keyBytes);
Array.Resize(ref keyHash, 32);
var keyHashString = string.Empty;
foreach (byte x in keyHash)
keyHashString += string.Format("{0:x2}", x);
keyHash = Encoding.UTF8.GetBytes(keyHashString.Substring(0, 32));
var ivHash = hash.ComputeHash(ivBytes);
Array.Resize(ref ivHash, 16);
var ivHashString = string.Empty;
foreach (byte x in ivHash)
ivHashString += string.Format("{0:x2}", x);
ivHash = Encoding.UTF8.GetBytes(ivHashString.Substring(0, 16));
// Create an RijndaelManaged object
// with the specified key and IV.
using (var rijAlg = new RijndaelManaged())
{
rijAlg.Padding = PaddingMode.PKCS7;
rijAlg.Mode = CipherMode.CBC;
rijAlg.Key = keyHash;
rijAlg.IV = ivHash;
var encryptedBytes = Encoding.UTF8.GetBytes(baseString);
// Create a encryptor to perform the stream transform.
var encryptor = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV);
// Create the streams used for encryption.
using (var msEncrypt = new MemoryStream(encryptedBytes))
{
using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Read))
{
using (var srEncrypt = new StreamReader(csEncrypt))
{
// Read the encrypted bytes from the encrypting stream
// and place them in a string.
var result = srEncrypt.ReadToEnd();
return Convert.ToBase64String(
Encoding.UTF8.GetBytes(
Convert.ToBase64String(
Encoding.UTF8.GetBytes(result))));
}
}
}
}
}
public static string SaveBase64String(string data)
{
data = data.Replace("-", "+").Replace("_", "/");
var mod = data.Length % 4;
if (mod > 2)
mod = 1;
return data + string.Empty.PadRight(mod, '=');
}
}
At the following link an online example is available for you to try: https://repl.it/#ormasoftchile/Test-encrypt-decrypt
Thank you everyone.
In the current code, the ciphertext is stored in a string (StreamReader.ReadToEnd), which generally doesn't work, since the data are corrupted thereby. Instead, the ciphertext should be stored in a byte-array, which can be Base64-encoded if required.
To fix the problem
remove the line:
var encryptedBytes = Encoding.UTF8.GetBytes(baseString);
and replace the entire MemoryStream-block by:
using (var msEncrypt = new MemoryStream())
{
using (var csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
{
using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
{
swEncrypt.Write(baseString);
}
var encryptedBytes = msEncrypt.ToArray();
return Convert.ToBase64String(Encoding.UTF8.GetBytes(Convert.ToBase64String(encryptedBytes)));
}
}
Another point is the double Base64-encoding/decoding. This makes no sense and is simply redundant and degrades performance. If possible, this should be changed.

C# Properly storing an E-mail Password

I'm creating a messaging application that will use an outlook account to send an email. However, I'm unsure about the proper steps to store the e-mail password on the user's computer. Suppose I had the following code:
SmtpClient SmtpServer = new SmtpClient("smtp.live.com");
var mail = new MailMessage();
mail.From = new MailAddress("youremail#hotmail.com");
mail.To.Add("to#gmail.com");
mail.Subject = "Test Mail - 1";
mail.IsBodyHtml = true;
string htmlBody;
htmlBody = "Write some HTML code here";
mail.Body = htmlBody;
SmtpServer.Port = 587;
SmtpServer.UseDefaultCredentials = false;
SmtpServer.Credentials = new System.Net.NetworkCredential("youremail#hotmail.com", "password");
SmtpServer.EnableSsl = true;
SmtpServer.Send(mail);
Obviously, I don't want "password" stored as a string inside my application. What would be the ideal/proper solution to storing a password on the user's machine so I can read it into my application, and pass it to the NetworkCredential constructor?
I've done reading here, and here. The first link suggest storing it in a file or registry, not sure how to store it in a registry. How would I properly store it in a file?
The best approach would be to serialize the credentials and then encrypt it and then write the encrypted bytes to a file. Reversing the process will work for retrieving the data.
First, create a class AES.cs:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace AES_Password_Storer
{
public static class AES
{
public static byte[] AES_Encrypt(byte[] bytesToBeEncrypted, byte[] passwordBytes)
{
byte[] encryptedBytes = null;
// Set your salt here, change it to meet your flavor:
// The salt bytes must be at least 8 bytes.
byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
using (MemoryStream ms = new MemoryStream())
{
using (RijndaelManaged AES = new RijndaelManaged())
{
AES.KeySize = 256;
AES.BlockSize = 128;
var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
AES.Key = key.GetBytes(AES.KeySize / 8);
AES.IV = key.GetBytes(AES.BlockSize / 8);
AES.Mode = CipherMode.CBC;
using (var cs = new CryptoStream(ms, AES.CreateEncryptor(), CryptoStreamMode.Write))
{
cs.Write(bytesToBeEncrypted, 0, bytesToBeEncrypted.Length);
cs.Close();
}
encryptedBytes = ms.ToArray();
}
}
return encryptedBytes;
}
public static byte[] AES_Decrypt(byte[] bytesToBeDecrypted, byte[] passwordBytes)
{
byte[] decryptedBytes = null;
// Set your salt here, change it to meet your flavor:
// The salt bytes must be at least 8 bytes.
byte[] saltBytes = new byte[] { 1, 2, 3, 4, 5, 6, 7, 8 };
using (MemoryStream ms = new MemoryStream())
{
using (RijndaelManaged AES = new RijndaelManaged())
{
AES.KeySize = 256;
AES.BlockSize = 128;
var key = new Rfc2898DeriveBytes(passwordBytes, saltBytes, 1000);
AES.Key = key.GetBytes(AES.KeySize / 8);
AES.IV = key.GetBytes(AES.BlockSize / 8);
AES.Mode = CipherMode.CBC;
using (var cs = new CryptoStream(ms, AES.CreateDecryptor(), CryptoStreamMode.Write))
{
cs.Write(bytesToBeDecrypted, 0, bytesToBeDecrypted.Length);
cs.Close();
}
decryptedBytes = ms.ToArray();
}
}
return decryptedBytes;
}
}
}
Next, create a class Credentials.cs: N.B. - Now I have created the Credentials class to hold only one user's credentials. You can tweak it to hold multiple ones by creating a list.
[Serializable]
public class Credentials
{
public string Email { get; set; }
public string Password { get; set; }
}
Next, for encryption (writing the data to a file):
XmlSerializer xs = new XmlSerializer(typeof(Credentials));
MemoryStream ms = new MemoryStream();
xs.Serialize(ms, new Credentials() { Email = "email#service.com", Password = "passworduser" });
byte[] encrypted = AES.AES_Encrypt(ms.ToArray(), Encoding.UTF8.GetBytes("encryptionkey")); //This is the key
File.WriteAllBytes("passwordfile.pwd", encrypted);
Now, for decryption:
MemoryStream ms = new MemoryStream(AES.AES_Decrypt(File.ReadAllBytes("passwordfile.pwd"), Encoding.UTF8.GetBytes("encryptionkey"))); //Here goes the key
XmlSerializer xs = new XmlSerializer(typeof(Credentials));
Credentials c = (Credentials)xs.Deserialize(ms);
// This 'c' contains your credentials.
Now in the codes for encryption and decryption, there is a string "encryptionkey". This is the main key to all this. You can (in fact, should) change this and keep it in a safe place (in your app).

What in the Salt causes it to fail in decryption

The code below and in the Fiddle isn't for production, it is for educational purposes. I do not want to fix anything, as I have a viable solution. However, I would like to know why:
var password = "password";
var salt = Encoding.ASCII.GetBytes(password.Length.ToString());
var secret = new PasswordDeriveBytes(password, salt);
When the above is implemented, in the following method FixedEncryptor will work.
// Valid:
public static string FixedEncryptor(string content)
{
var cipher = new RijndaelManaged();
var plain = Encoding.Unicode.GetBytes(content);
var key = new PasswordDeriveBytes(password, salt);
using (var encrypt = cipher.CreateEncryptor(key.GetBytes(32), key.GetBytes(16)))
using (var stream = new MemoryStream())
using (var crypto = new CryptoStream(stream, encrypt, CryptoStreamMode.Write))
{
crypto.Write(plain, 0, plain.Length);
crypto.FlushFinalBlock();
return Convert.ToBase64String(stream.ToArray());
}
}
However, if you implement:
var secret = new PasswordDeriveBytes("password",
Encoding.ASCII.GetBytes("password"));
The code will suddenly produce:
Run-time exception (line 70): Padding is invalid and cannot be
removed.
Stack Trace:
[System.Security.Cryptography.CryptographicException: Padding is
invalid and cannot be removed.] at Crypt.Decryptor(String content):
line 70 at Program.Main(): line 17
As denoted in the following method:
// Invalid:
public static string Encryptor(string content)
{
var cipher = new RijndaelManaged();
var plain = Encoding.Unicode.GetBytes(content);
var key = new PasswordDeriveBytes("password", Encoding.ASCII.GetBytes("password"));
using (var encrypt = cipher.CreateEncryptor(key.GetBytes(32), key.GetBytes(16)))
using (var stream = new MemoryStream())
using (var crypto = new CryptoStream(stream, encrypt, CryptoStreamMode.Write))
{
crypto.Write(plain, 0, plain.Length);
crypto.FlushFinalBlock();
return Convert.ToBase64String(stream.ToArray());
}
}
So why can one successfully decrypt, while the other doesn't decrypt correctly and produces the above error?
A Fiddle with a small example is here.
From your posted code example your problem comes from the fact you are using two different salts.
In FixedEncryptor you use a salt of
Encoding.ASCII.GetBytes(password.Length.ToString());
That encodes to be a byte array equal to { 56 }, this is because Length returns 8 then calling ToString() on that returns the string "8" which you convert in to the ascii value 56.
In Encryptor you use a salt of
Encoding.ASCII.GetBytes("password")
That encodes to be a byte array equal to { 112, 97, 115, 115, 119, 111, 114, 100}, which is the ascii values of the characters "p", "a", "s", "s", "w", "o", "r", and "d".
The problem you are running in to is you only attempt to use { 56 } in your decrypt function, so your problem comes down to your encrypt function and your decrypt function are using two different salts.
If I make a make a new Decrypter to use the same salt and password as Encryptor then make a separate FixedDecryptor to match the salt of FixedEncryptor everything will work fine
public class Program
{
public static void Main()
{
var message = "Hello World!";
var fixedCipherText = Crypt.FixedEncryptor(message);
var cipherText = Crypt.Encryptor(message);
Console.WriteLine(cipherText);
Console.WriteLine(fixedCipherText);
var plainText = Crypt.Decryptor(cipherText);
var fixedPlainText = Crypt.FixedDecryptor(fixedCipherText);
Console.WriteLine(plainText);
Console.WriteLine(fixedPlainText);
}
}
public static class Crypt
{
private const string password = "password";
private readonly static byte[] salt = Encoding.ASCII.GetBytes(password.Length.ToString());
public static string FixedEncryptor(string content)
{
var cipher = new RijndaelManaged();
var plain = Encoding.Unicode.GetBytes(content);
var key = new PasswordDeriveBytes(password, salt);
using (var encrypt = cipher.CreateEncryptor(key.GetBytes(32), key.GetBytes(16)))
using (var stream = new MemoryStream())
using (var crypto = new CryptoStream(stream, encrypt, CryptoStreamMode.Write))
{
crypto.Write(plain, 0, plain.Length);
crypto.FlushFinalBlock();
return Convert.ToBase64String(stream.ToArray());
}
}
public static string Encryptor(string content)
{
var cipher = new RijndaelManaged();
var plain = Encoding.Unicode.GetBytes(content);
var key = new PasswordDeriveBytes("password", Encoding.ASCII.GetBytes("password"));
using (var encrypt = cipher.CreateEncryptor(key.GetBytes(32), key.GetBytes(16)))
using (var stream = new MemoryStream())
using (var crypto = new CryptoStream(stream, encrypt, CryptoStreamMode.Write))
{
crypto.Write(plain, 0, plain.Length);
crypto.FlushFinalBlock();
return Convert.ToBase64String(stream.ToArray());
}
}
public static string FixedDecryptor(string content)
{
var cipher = new RijndaelManaged();
var encrypted = Convert.FromBase64String(content);
var key = new PasswordDeriveBytes(password, salt);
using (var decryptor = cipher.CreateDecryptor(key.GetBytes(32), key.GetBytes(16)))
using (var stream = new MemoryStream(encrypted))
using (var crypto = new CryptoStream(stream, decryptor, CryptoStreamMode.Read))
{
byte[] plain = new byte[encrypted.Length];
int decrypted = crypto.Read(plain, 0, plain.Length);
string data = Encoding.Unicode.GetString(plain, 0, decrypted);
return data;
}
}
public static string Decryptor(string content)
{
var cipher = new RijndaelManaged();
var encrypted = Convert.FromBase64String(content);
var key = new PasswordDeriveBytes("password", Encoding.ASCII.GetBytes("password"));
using (var decryptor = cipher.CreateDecryptor(key.GetBytes(32), key.GetBytes(16)))
using (var stream = new MemoryStream(encrypted))
using (var crypto = new CryptoStream(stream, decryptor, CryptoStreamMode.Read))
{
byte[] plain = new byte[encrypted.Length];
int decrypted = crypto.Read(plain, 0, plain.Length);
string data = Encoding.Unicode.GetString(plain, 0, decrypted);
return data;
}
}
}
Fiddel of the code.
However this still is not the "correct" way to do things. See Sine Nomen's answer
First of all, the method by which you generate a salt is not secure at all; secondly, PasswordDerivedBytes is deprecated and you should be looking at its successor, Rfc2898DeriveBytes.
Try something like the following - note that this requires a few using statements: System, System.IO, System.Security.Cryptography and System.Text.
Simply encrypt the data with Encrypt(PlainText, Password) and decrypt it again with Decrypt(EncryptedData, Password). The salt is rolled into the encrypted data as the first 16 bytes and it is completely random for each encryption/decryption round.
This code is part of my own open source password manager.
/*
* Encryption/Decryption, based on AES256 and PBKDF2
*/
public string Encrypt (string plainText, string passPhrase, bool fast_encrypt = false)
{
string result;
using (Rijndael algR = Rijndael.Create ()) {
RNGCryptoServiceProvider rngC = new RNGCryptoServiceProvider ();
byte[] iv = new byte[16];
rngC.GetBytes (iv);
Rfc2898DeriveBytes derived = new Rfc2898DeriveBytes (passPhrase, iv, fast_encrypt ? 10 : 3000);
algR.KeySize = 256;
algR.BlockSize = 128;
algR.Key = derived.GetBytes (32);
algR.IV = iv;
using (MemoryStream memoryStream = new MemoryStream ()) {
memoryStream.Write (iv, 0, 16);
using (CryptoStream cryptoStreamEncrypt = new CryptoStream (memoryStream, algR.CreateEncryptor (algR.Key, algR.IV), CryptoStreamMode.Write)) {
using (StreamWriter streamWriterEncrypt = new StreamWriter (cryptoStreamEncrypt)) {
streamWriterEncrypt.Write (plainText);
}
}
result = Convert.ToBase64String (memoryStream.ToArray ());
}
}
return result;
}
public string Decrypt (string cipherText, string passPhrase, bool fast_decrypt = false)
{
string result;
using (Rijndael algR = Rijndael.Create ()) {
using (MemoryStream memoryStream = new MemoryStream (Convert.FromBase64String (cipherText))) {
byte[] iv = new byte[16];
memoryStream.Read (iv, 0, 16);
Rfc2898DeriveBytes derived = new Rfc2898DeriveBytes (passPhrase, iv, fast_decrypt ? 10 : 3000);
algR.KeySize = 256;
algR.BlockSize = 128;
algR.Key = derived.GetBytes (32);
algR.IV = iv;
using (CryptoStream cryptoStreamDecrypt = new CryptoStream (memoryStream, algR.CreateDecryptor (algR.Key, algR.IV), CryptoStreamMode.Read)) {
using (StreamReader streamReaderDecrypt = new StreamReader (cryptoStreamDecrypt)) {
result = streamReaderDecrypt.ReadToEnd ();
}
}
}
}
return result;
}

Decrypting using rijndael and C# issue

I am encrypting some text and converting it to base64 and upon decryption I appear to have some odd characters as it blocks the rest of the output...
For example, I want to encrypt 10,2013-12-16 10:22:24,1387189344 which converts to MaEA8gd7Xyg8tNBrtVBlb75U/a0J9x5x7UryI81gy3R+ZvL01p05uzDtzdBWL5Pg (base64) and then when I decrypt I try to print the output as "[" + decrypted + "]" but the second bracket doesn't come out.....
Here's my code. Thanks in advance.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using DataSync;
using System.IO;
using System.Security.Cryptography;
namespace EncryptionTest
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
// encrypt
private void button1_Click(object sender, EventArgs e)
{
txtOutput.Text = Encrypt(txtData.Text, txtCIV.Text, txtSecret.Text);
}
// decrypt
private void button2_Click(object sender, EventArgs e)
{
txtOutput.Text = "[" + Decrypt(txtData.Text, txtCIV.Text, txtSecret.Text) + "\r\n" + "]";
}
public string GenerateIV()
{
RijndaelManaged RM = new RijndaelManaged();
RM.KeySize = 128;
RM.BlockSize = 128;
RM.Mode = CipherMode.CBC;
RM.Padding = PaddingMode.Zeros;
RM.GenerateIV();
return Convert.ToBase64String(RM.IV);
}
public string Decrypt(string Encrypted, string IV, string SecretKey)
{
byte[] DecryptThis = Convert.FromBase64String(Encrypted);
byte[] DecryptIV = Convert.FromBase64String(IV);
byte[] Key = Encoding.UTF8.GetBytes(SecretKey);
SHA256 SHA256Obj = SHA256.Create();
byte[] PrivateKeyHash = SHA256Obj.ComputeHash(Key, 0, Key.Length);
RijndaelManaged RM = new RijndaelManaged();
RM.Mode = CipherMode.CBC;
RM.Padding = PaddingMode.Zeros;
MemoryStream ms = new MemoryStream();
CryptoStream cs = new CryptoStream(ms, RM.CreateDecryptor(PrivateKeyHash, DecryptIV), CryptoStreamMode.Write);
cs.Write(DecryptThis, 0, DecryptThis.Length);
cs.FlushFinalBlock();
cs.Close();
// Strip null (padding) characters
int Position = -1;
foreach (byte Char in ms.ToArray())
{
++Position;
if (Char == 0)
{
break;
}
}
string Temp = Encoding.UTF8.GetString(ms.ToArray());
return Temp.Substring(0, Position+1).Trim();
}
public string Encrypt(string ToBeEncrypted, string IV, string SecretKey)
{
byte[] EncryptThis = Encoding.UTF8.GetBytes(ToBeEncrypted);
byte[] EncryptIV = Convert.FromBase64String(IV);
byte[] Key = Encoding.UTF8.GetBytes(SecretKey);
SHA256 SHA256Obj = SHA256.Create();
byte[] PrivateKeyHash = SHA256Obj.ComputeHash(Key, 0, Key.Length);
RijndaelManaged RM = new RijndaelManaged();
RM.Mode = CipherMode.CBC;
RM.Padding = PaddingMode.Zeros;
MemoryStream ms = new MemoryStream();
CryptoStream cs = new CryptoStream(ms, RM.CreateEncryptor(PrivateKeyHash, EncryptIV), CryptoStreamMode.Write);
cs.Write(EncryptThis, 0, EncryptThis.Length);
cs.FlushFinalBlock();
cs.Close();
return Convert.ToBase64String(ms.ToArray());
}
}
}
You have a line break in your code here:
txtOutput.Text = "[" + Decrypt(txtData.Text, txtCIV.Text, txtSecret.Text) + "\r\n" + "]";
^^^
You have to place the line break after the bracket:
txtOutput.Text = "[" + Decrypt(txtData.Text, txtCIV.Text, txtSecret.Text) + "]" + "\r\n";
Also I am not sure if you even need the line break. Are you using a multiline textbox?
You are not removing all the "\0" in your Decrypt() method.
at line 82, replace
return Temp.Substring(0, Position + 1).Trim();
by
return Temp.Substring(0, Position).Trim();

Categories