0

When I decrypt an encrypted username using AES encryption it shows a bunch of "\0\0\0" at the end of the decrypted username. Is there a way to not add these when encrypting?

The example code of the encryption and decryption:

  string ky = xx_Convert.Base64ToString("RllhSzNjM09PZFAwT2RYMkdxOFI2cG9HYjVmWVIybnQ=");
  string iv = xx_Convert.Base64ToString("Y2pZQmJsdVlqdlBYM0RtcXVleDJkNGNTa0FIYjhYQ2Y=");

  string username = "test@mail.com";

  string encriptedUsername = xx_Crypto.EncryptAES(ky, iv, username);
  string encriptedPassword = xx_Crypto.EncryptAES(ky, iv, "password");

  string decryptedUsername = xx_Crypto.DecryptAES(ky, iv, encriptedUsername);
  string decryptedPassword = xx_Crypto.DecryptAES(ky, iv, encriptedPassword);

This gives the following result for decryptedUsername when inspecting the variable: "test@mail.com\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"

This is likely a result of the Padding property of the encryption function. In the Encryption function the Padding is set to Padding = PaddingMode.Zeros but when I remove this line it still pads the result but with other invisible characters.

Encryption function:

public static string EncryptAES(string keyString, string ivString, string 
text)
{
  RijndaelManaged myRijndael = new RijndaelManaged()
  {
    Padding = PaddingMode.Zeros,
    Mode = CipherMode.CBC,
    KeySize = 256,
    BlockSize = 256
  };

  byte[] key = Encoding.UTF8.GetBytes(keyString);
  byte[] IV = Encoding.UTF8.GetBytes(ivString);

  ICryptoTransform encryptor = myRijndael.CreateEncryptor(key, IV);

  byte[] encrypted = null;
  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(text);
      }
      encrypted = msEncrypt.ToArray();
    }
  }

  return (Convert.ToBase64String(encrypted));
}

Edit: As requested here is the Decryption function:

public static string DecryptAES(string keyString, string ivString, string text)
{
  var myRijndael = new RijndaelManaged()
  {
    Padding = PaddingMode.Zeros,
    Mode = CipherMode.CBC,
    KeySize = 256,
    BlockSize = 256
  };

  byte[] key = Encoding.UTF8.GetBytes(keyString);
  byte[] IV = Encoding.UTF8.GetBytes(ivString);

  ICryptoTransform decryptor = myRijndael.CreateDecryptor(key, IV);

  byte[] sEncrypted = Convert.FromBase64String(text);

  byte[] fromEncrypt = new byte[sEncrypted.Length];

  MemoryStream msDecrypt = new MemoryStream(sEncrypted);
  CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read);

  csDecrypt.Read(fromEncrypt, 0, fromEncrypt.Length);

  return (Encoding.UTF8.GetString(fromEncrypt));
}

So is it possible to prevent this in the encryption function?

P.S: I did not use the same keys as in the original code

M.Meuris
  • 43
  • 10
  • Check this article, https://www.c-sharpcorner.com/article/aes-encryption-in-c-sharp/ – Camadas May 27 '19 at 13:32
  • 1
    From where did you get the idea that the encryption function is the one causing the problem? Where is the decryption code? And most important of it all, ***why*** are you encrypting passwords??? – Camilo Terevinto May 27 '19 at 13:35
  • 2
    Do note that you are using `PaddingMode.Zeros` and setting a block mode cipher, so it is padding the result with zeroes to fill the block size. If you must use that settings, consider [string.TrimEnd()](https://docs.microsoft.com/en-us/dotnet/api/system.string.trimend?view=netframework-4.7.2#System_String_TrimEnd_System_Char___) – Cleptus May 27 '19 at 13:35
  • This is related question, and worth reading to understand AES encryption modes [How to choose an AES encryption mode (CBC ECB CTR OCB CFB)?](https://stackoverflow.com/questions/1220751/how-to-choose-an-aes-encryption-mode-cbc-ecb-ctr-ocb-cfb) – Cleptus May 27 '19 at 13:44
  • @CamiloTerevinto The code above is just example code. I did not use it in the program. But to my understanding saving passwords plain text is something you should not do. How would I otherwise save passwords? I shall add to Decryption function as well – M.Meuris May 27 '19 at 13:48
  • @M.Meuris By [hashing them, of course](https://stackoverflow.com/questions/326699/difference-between-hashing-a-password-and-encrypting-it) – Camilo Terevinto May 27 '19 at 13:49
  • You should not save passwords, either encrypted or in plain text, but store their hash. – Cleptus May 27 '19 at 13:49
  • @CamiloTerevinto They do get hashed server side when saved in the database. They get encrypted to store them in the registry. – M.Meuris May 27 '19 at 13:52
  • Do not trust user level code to such sensitive info. Registry can also be accessed, thus defeating the database hashing algorithm (the security of a system is always the security of the weakest link, in this case your registry AES storage), consider operative system level encryption if encrypting is a must [Data Protection API](https://en.wikipedia.org/wiki/Data_Protection_API) – Cleptus May 27 '19 at 13:58

1 Answers1

0

So is it possible to prevent this in the encryption function?

Yes, just use:

read = csDecrypt.Read(fromEncrypt, 0, fromEncrypt.Length);
return (Encoding.UTF8.GetString(fromEncrypt, 0, read));

You are currently encoding the entire buffer. The padding bytes are removed but the bytes in the buffer are preset to zero during initialization when you created the buffer.

Note that zero padding isn't used much because if your plaintext ends with one or more zero bytes, those bytes may be removed. So some messages cannot be decrypted successfully this way (and cryptographers want to encrypt arbitrary messages, not just strings).

Maarten Bodewes
  • 80,169
  • 13
  • 121
  • 225