0

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.

Need Help
  • 39
  • 4
  • 1
    If you want AES, just use [AES](https://msdn.microsoft.com/en-us/library/system.security.cryptography.aesmanaged.aspx) – Martheen Dec 23 '16 at 06:25
  • AES is a subset of Rijndael, so for many purposes they are the same. Your code does not specify an [encryption mode](en.wikipedia.org/wiki/Block_cipher_mode_of_operation), so I presume you are using the C# default mode. This is not good practice. Specify a mode explicitly. Use either CBC or CTR mode. CBC needs an IV (again, do not use the default) and CTR needs a nonce. – rossum Dec 23 '16 at 09:14
  • The way you generate an IV is poor. You should instead generate 16 random bytes (assuming your block size is 128 bits) and prepend it to the output data. – Luke Joshua Park Dec 23 '16 at 11:06
  • Your question about AES makes no sense, since Rijndael with a 32-byte key and 16-byte block-size is AES-256. – CodesInChaos Dec 23 '16 at 12:09

1 Answers1

1

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#

CodesInChaos
  • 106,488
  • 23
  • 218
  • 262