Are my codes as secure as using AES? - c#

I am currently working on a project assigned by my teacher and I need to ensure the application it has strong encryption. Below is my encrypt method:
private String Encrypt(string text)
{
RijndaelManaged RijndaelCipher = new RijndaelManaged();
string Password = System.Configuration.ConfigurationManager.AppSettings["Password"];
byte[] PlainText = System.Text.Encoding.Unicode.GetBytes(TextBox1.Text);
byte[] Salt = Encoding.ASCII.GetBytes(Password.Length.ToString());
PasswordDeriveBytes SecretKey = new PasswordDeriveBytes(Password, Salt);
ICryptoTransform Encryptor = RijndaelCipher.CreateEncryptor(SecretKey.GetBytes(32), SecretKey.GetBytes(16));
MemoryStream memoryStream = new MemoryStream();
CryptoStream cryptoStream = new CryptoStream(memoryStream, Encryptor, CryptoStreamMode.Write);
cryptoStream.Write(PlainText, 0, PlainText.Length);
cryptoStream.FlushFinalBlock();
byte[] CipherBytes = memoryStream.ToArray();
memoryStream.Close();
cryptoStream.Close();
string EncryptedData = Convert.ToBase64String(CipherBytes);
return EncryptedData;
}
This is my Decrypt Method
public string Decrypt(string encrypted)
{
RijndaelManaged RijndaelCipher = new RijndaelManaged();
string Password = System.Configuration.ConfigurationManager.AppSettings["Password"];
string DecryptedData;
try
{
byte[] EncryptedData = Convert.FromBase64String(TextBox2.Text);
byte[] Salt = Encoding.ASCII.GetBytes(Password.Length.ToString());
PasswordDeriveBytes SecretKey = new PasswordDeriveBytes(Password, Salt);
ICryptoTransform Decryptor = RijndaelCipher.CreateDecryptor(SecretKey.GetBytes(32), SecretKey.GetBytes(16));
MemoryStream memoryStream = new MemoryStream(EncryptedData);
CryptoStream cryptoStream = new CryptoStream(memoryStream, Decryptor, CryptoStreamMode.Read);
byte[] PlainText = new byte[EncryptedData.Length];
int DecryptedCount = cryptoStream.Read(PlainText, 0, PlainText.Length);
memoryStream.Close();
cryptoStream.Close();
DecryptedData = Encoding.Unicode.GetString(PlainText, 0, DecryptedCount);
}
catch
{
DecryptedData = TextBox3.Text;
}
return DecryptedData;
}
As you can see from my codes, I am using the password from the web config and I do not store any IV and key into the database. So my question is if the encryptions method that I use is as secure as using AES method. If it isn't, is there any other possible solutions that I can refer to? Thanks for replying and sorry for my poor english skills.

This bad in several ways:
It's unauthenticated. Add a MAC on use an existing authenticated algorithm like AES-GCM, AES-SIV.
The salt is derived deterministically from the password, which is equivalent to using no salt at all. Each user needs to use a different salt.
Similar to the salt, the point of an IV is to ensure that encrypting similar or identical plaintexts using a fixed key produces completely different outputs every time. If your key is single-use (e.g. because its derivation involves a single-use salt), a fixes IV would be acceptable.
PasswordDeriveBytes is a mix of PBKDF1 and undocumented Microsoft specific extensions. Don't use it. At minimum use Rfc2898DeriveBytes which is standard compliant PBKDF2-HMAC-SHA1. Using about 100000 iterations, instead of the much too small default.
I recommend using jbtule's answer to Encrypt and decrypt a string in C#

Related

Equivalent C# cryptograph in react native

I am looking for a ReactNative equivalent for the following C# Crypto methods. Basically, I am calling a C# API endpoint that requires Json calls to be encrypted. Its also sending back encrypted results using the same Cryptography. The C# methods where provided by my client.
I am fairly new to ReactNative as such I have been unable to successfully reproduced the methods in ReactNative.
I have looked at similar functions online such as one highlighted here but to no avail.
I will higly appreciate your help.
C# METHODS
public string EncryptFromDataObject(string jsonString)
{
byte[] initVectorBytes = Encoding.UTF8.GetBytes(MySecret.sInitVector);
byte[] plainTextBytes = Encoding.UTF8.GetBytes(jsonString);
PasswordDeriveBytes password = new PasswordDeriveBytes(MySecret.sPassPhrase, null);
byte[] keyBytes = password.GetBytes(MySecret.iKeySize / 8);
RijndaelManaged symmetricKey = new RijndaelManaged();
symmetricKey.Mode = CipherMode.CBC;
ICryptoTransform encryptor = symmetricKey.CreateEncryptor(keyBytes, initVectorBytes);
MemoryStream memoryStream = new MemoryStream();
CryptoStream cryptoStream = new CryptoStream(memoryStream, encryptor, CryptoStreamMode.Write);
cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
cryptoStream.FlushFinalBlock();
byte[] cipherTextBytes = memoryStream.ToArray();
memoryStream.Close();
cryptoStream.Close();
//string s = Convert.ToBase64String(cipherTextBytes); // base64 without padding
//s = s.PadRight(s.Length + (s.Length * 3) % 4, '='); // add padding
return Convert.ToBase64String(cipherTextBytes);
}
//Decrypt
public string DecryptToDataObject(string cipherDataObj)
{
byte[] initVectorBytes = Encoding.ASCII.GetBytes(MySecret.sInitVector);
byte[] cipherTextBytes = Convert.FromBase64String(cipherDataObj);
PasswordDeriveBytes password = new PasswordDeriveBytes(MySecret.sPassPhrase, null);
byte[] keyBytes = password.GetBytes(MySecret.iKeySize / 8);
RijndaelManaged symmetricKey = new RijndaelManaged();
symmetricKey.Mode = CipherMode.CBC;
ICryptoTransform decryptor = symmetricKey.CreateDecryptor(keyBytes, initVectorBytes);
MemoryStream memoryStream = new MemoryStream(cipherTextBytes);
CryptoStream cryptoStream = new CryptoStream(memoryStream, decryptor, CryptoStreamMode.Read);
byte[] plainTextBytes = new byte[cipherTextBytes.Length];
int decryptedByteCount = cryptoStream.Read(plainTextBytes, 0, plainTextBytes.Length);
memoryStream.Close();
cryptoStream.Close();
string jsonString = Encoding.UTF8.GetString(plainTextBytes, 0, decryptedByteCount);
return jsonString;
}
I actually managed though not by using the above C# class but used the implementation here.
I managed to encrypt from C# and decrypt using ReactNative and vise-versa. The only catch is to make sure that the iv value used in ReactNative is generated is obtained from C# code.

Example code PHP / C# AES encryption - random IV

I found an implementation for AES encryption/decryption that's supposed to work in PHP and C#:
https://odan.github.io/2017/08/10/aes-256-encryption-and-decryption-in-php-and-csharp.html
However, in this example, the IV is always 0, which is not good.
So, as the author suggests, I use the openssl_random_pseudo_bytes() function:
$ivlen = openssl_cipher_iv_length($method);
$iv = openssl_random_pseudo_bytes($ivlen);
However, the problem now is, that I have to store the IV somewhere so that the C# app can use it for decryption. My idea was to base64_encode it and prepend it to the encrypted message with ":" separating both, so that I can simply split the string, then base64 decode it in C# and can use the IV. However, this does not work. This is the code:
public string DecryptString(string cipherText, byte[] key, byte[] iv)
{
// Instantiate a new Aes object to perform string symmetric encryption
Aes encryptor = Aes.Create();
encryptor.Mode = CipherMode.CBC;
// Set key and IV
byte[] aesKey = new byte[32];
Array.Copy(key, 0, aesKey, 0, 32);
encryptor.Key = aesKey;
encryptor.IV = iv;
// Instantiate a new MemoryStream object to contain the encrypted bytes
MemoryStream memoryStream = new MemoryStream();
// Instantiate a new encryptor from our Aes object
ICryptoTransform aesDecryptor = encryptor.CreateDecryptor();
// Instantiate a new CryptoStream object to process the data and write it to the
// memory stream
CryptoStream cryptoStream = new CryptoStream(memoryStream, aesDecryptor, CryptoStreamMode.Write);
// Will contain decrypted plaintext
string plainText = String.Empty;
try {
// Convert the ciphertext string into a byte array
byte[] cipherBytes = Convert.FromBase64String(cipherText);
// Decrypt the input ciphertext string
cryptoStream.Write(cipherBytes, 0, cipherBytes . Length);
// Complete the decryption process
cryptoStream.FlushFinalBlock();
// Convert the decrypted data from a MemoryStream to a byte array
byte[] plainBytes = memoryStream.ToArray();
// Convert the decrypted byte array to string
plainText = Encoding.ASCII.GetString(plainBytes, 0, plainBytes.Length);
} finally {
// Close both the MemoryStream and the CryptoStream
memoryStream.Close();
cryptoStream.Close();
}
// Return the decrypted data as a string
return plainText;
}
And this is how I try to call the function with the IV prepended to the encrypted message:
private void btnDecrypt_Click(object sender, EventArgs e)
{
string encrypted = txtEncrypted.Text;
string password = txtPW.Text;
string[] temp = encrypted.Split(":".ToCharArray());
string iv_str = temp[0];
encrypted = temp[1];
SHA256 mySHA256 = SHA256Managed.Create();
byte[] key = mySHA256.ComputeHash(Encoding.ASCII.GetBytes(password));
iv_str = Encoding.Default.GetString(Convert.FromBase64String(iv_str));
byte[] iv = Encoding.ASCII.GetBytes(iv_str);
txtDecrypted.Text = this.DecryptString(encrypted, key, iv);
}
Doesn't work. It decrypts something, but that's just gibberish and not the message I encrypted in PHP.
I think it has to do with the IV somehow.
#Topaco:
Thank you very much... now I see what my mistake was. It works now with generated IV.
By the way, two more questions on the strength of the encryption:
Is it ok to use the following function to generate an IV (GenerateIV() for some reason won't work):
byte[] iv = new byte[16];
Random rnd = new Random();
rnd.NextBytes(iv);
I added a randomly generated salt to the password of the user, so that the key is a hash from the user password and a salt. I also prepend the salt, together with the now randomly generated IV, to the message. Then for the decryption process I use the prepended salt and the key the user enters. Works so far. But does it weaken the encryption? No, right?
Thank you very much.
// Edit: Code format doesn't work, don't know why.

Rijndael encryption/decryption

I have the following code for encryption and decryption. The problem is that at decryption besides the decrypted text i have some "aaaaa" after the text. why? need some help. THX!
public static byte[] Encrypt(byte[] PlainTextBytes, string key , string InitialVector)
{
try
{
System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
Byte[] KeyBytes = encoding.GetBytes(key);
byte[] InitialVectorBytes = encoding.GetBytes(InitialVector);
RijndaelManaged SymmetricKey = new RijndaelManaged();
ICryptoTransform Encryptor = SymmetricKey.CreateEncryptor(KeyBytes, InitialVectorBytes);
MemoryStream MemStream = new MemoryStream();
CryptoStream CryptoStream = new CryptoStream(MemStream, Encryptor, CryptoStreamMode.Write);
CryptoStream.Write(PlainTextBytes, 0, PlainTextBytes.Length);
CryptoStream.FlushFinalBlock();
byte[] CipherTextBytes = MemStream.ToArray();
return CipherTextBytes;
//decrytion
public static string Decrypt(byte[] PlainTextBytes1, string key, string InitialVector)
{
System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
Byte[] KeyBytes = encoding.GetBytes(key);
RijndaelManaged SymmetricKey = new RijndaelManaged();
byte[] InitialVectorBytes = Encoding.UTF8.GetBytes(InitialVector);
ICryptoTransform Decryptor = SymmetricKey.CreateDecryptor(KeyBytes, InitialVectorBytes);
MemoryStream MemStream1 = new MemoryStream(PlainTextBytes1);
CryptoStream CryptoStream = new CryptoStream(MemStream1, Decryptor, CryptoStreamMode.Read);
Byte[] pltxt = new byte[PlainTextBytes1.Length];
CryptoStream.Read(pltxt, 0, pltxt.Length);
ASCIIEncoding textConverter = new ASCIIEncoding();
round = textConverter.GetString(pltxt);
return round;
}
where am i wrong?
In your decrypt function you have:
Byte[] pltxt = new byte[PlainTextBytes1.Length];
This is wrong because the cypher text is longer than the plain text, because it's padded to get a multiple of the block size.
CryptoStream.Read(pltxt, 0, pltxt.Length);
Read returns how many bytes were actually returned. It doesn't guarantee that it will return as many bytes as you requested.
And then there are multiple other defects/bad style things:
The parameter passed into Decrypt is called PlainTextBytes1 it should be called cyphertext.
The way you create the key/initvec bytes from the string. ASCII encoding is a bad choice here. ASCII can't represent any byte string. Perhaps you want to hex en/decode a string of twice the size of the key instead?
ASCII en/decoding the plaintext will only work for ASCII characters and silently corrupt all other characters. Why don't you use UTF-8 instead?
.net naming conventions say you should use lowercase names for parameters

DES decryption error "Bad Data" in C# when closing cryptostream

I try to decrypt an encrypted byte array (encrypt with K1 and decrypt with K2). Visual Studio throws an exception "BAD DATA" when it tries to close my crypto stream
here's my code snippet of DES decryption
public Byte[] Decrypt(Byte[] cipherData, Byte[] key, Byte[] iv)
{
MemoryStream ms = new MemoryStream();
DES mDES = DES.Create();
mDES.Key = key;
mDES.IV = iv;
mDES.Padding = PaddingMode.PKCS7;
CryptoStream cs = new CryptoStream(ms, mDES.CreateDecryptor(), CryptoStreamMode.Write);
cs.Write(cipherData, 0, cipherData.Length);
cs.Close();
Byte[] decryptedData = ms.ToArray();
return decryptedData;
}
the initial vector is the same as encryption. I don't know why this error occurred.
Added:
As recommended by Greg B, I post here my code snippet of encryption. The output of encryption is the input of decryption (two different keys)
public Byte[] Decrypt(Byte[] cipherData, Byte[] key, Byte[] iv)
{
MemoryStream ms = new MemoryStream();
DES mDES = DES.Create();
mDES.Key = key;
mDES.IV = iv;
mDES.Padding = PaddingMode.PKCS7;
CryptoStream cs = new CryptoStream(ms, mDES.CreateDecryptor(), CryptoStreamMode.Write);
cs.Write(cipherData, 0, cipherData.Length);
cs.Close();
Byte[] decryptedData = ms.ToArray();
return decryptedData;
}
the problem you encountered comes from the selected padding mode.
since padding is used when decrypting your cipher text the cryptostream tries to remove the padding when your retrieve the decrypted bytes. since you don't use the key the data was encrypted with, you will get "garbage" ... the cryptostream fails to detect the padding that needs to be removed, and the operation fails with the observed exception.
if you want to rebuld someething like 3DES with the DES class use PaddingMode NONE for your decryption and the following encryption step (so only the first encryption or the last decryption uses padding)

Simple Encryption/Decryption method for encrypting an image file

My requirement is that I need simple encryption/decryption methods in C# to encrypt and
decrypt an image (maybe gif/jpeg).Simple cause I have to store it in the database in a BLOB field andsome other developers in some other programming language(like java) may need to extract and display this image.I don't need much security cause its just a matter of "security by obscuring"(life).
Gulp..can someone help...
Since you "don't need much security" you can probably manage to get by with something like AES (Rijndael). It uses a symmetric-key and there is plenty of help in the .NET framework to make is easy to implement. There is plenty of info in MSDN on the Rijndael class that you might find helpful.
Here is a very stripped down example of encrypt / decrypt methods which can be used for working with byte arrays (binary contents)...
using System;
using System.IO;
using System.Text;
using System.Security.Cryptography;
public class RijndaelHelper
{
// Example usage: EncryptBytes(someFileBytes, "SensitivePhrase", "SodiumChloride");
public static byte[] EncryptBytes(byte[] inputBytes, string passPhrase, string saltValue)
{
RijndaelManaged RijndaelCipher = new RijndaelManaged();
RijndaelCipher.Mode = CipherMode.CBC;
byte[] salt = Encoding.ASCII.GetBytes(saltValue);
PasswordDeriveBytes password = new PasswordDeriveBytes(passPhrase, salt, "SHA1", 2);
ICryptoTransform Encryptor = RijndaelCipher.CreateEncryptor(password.GetBytes(32), password.GetBytes(16));
MemoryStream memoryStream = new MemoryStream();
CryptoStream cryptoStream = new CryptoStream(memoryStream, Encryptor, CryptoStreamMode.Write);
cryptoStream.Write(inputBytes, 0, inputBytes.Length);
cryptoStream.FlushFinalBlock();
byte[] CipherBytes = memoryStream.ToArray();
memoryStream.Close();
cryptoStream.Close();
return CipherBytes;
}
// Example usage: DecryptBytes(encryptedBytes, "SensitivePhrase", "SodiumChloride");
public static byte[] DecryptBytes(byte[] encryptedBytes, string passPhrase, string saltValue)
{
RijndaelManaged RijndaelCipher = new RijndaelManaged();
RijndaelCipher.Mode = CipherMode.CBC;
byte[] salt = Encoding.ASCII.GetBytes(saltValue);
PasswordDeriveBytes password = new PasswordDeriveBytes(passPhrase, salt, "SHA1", 2);
ICryptoTransform Decryptor = RijndaelCipher.CreateDecryptor(password.GetBytes(32), password.GetBytes(16));
MemoryStream memoryStream = new MemoryStream(encryptedBytes);
CryptoStream cryptoStream = new CryptoStream(memoryStream, Decryptor, CryptoStreamMode.Read);
byte[] plainBytes = new byte[encryptedBytes.Length];
int DecryptedCount = cryptoStream.Read(plainBytes, 0, plainBytes.Length);
memoryStream.Close();
cryptoStream.Close();
return plainBytes;
}
}
Look at the System.Security.Cryptography namespace.
Here is an article about encrypting data.
Your question is very general - the linked article gives you examples of encryption using the built in functions.

Categories