Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are there random characters appearing in my decrypted text?

Intro

I'm trying to encrypt and decrypt texts and sometimes, especially for larger texts, random characters appear within the decrypted text. I'm using AES cryptography within the System.Security.Cryptography namespace and the text I'm trying to encrypt at the moment would be a URL and some info, such as the page title. I've provided an example below and what I've attempted. I've also written the two encryption and decryption methods, minus any lines that output to the Debug Window. The Key and IV used shouldn't be a problem as, for now, they would be constant.

I think it would be wise for me to point out that it encrypts and decrypts 18/01/2013;18/01/2013, in a separate occurrence, as expected.

Example

Say I wanted to decrypt this text:

Barnabe Googes Information & Homepage | Search and Research on BarnabeGooge.com;18/01/2013;18/01/2013;;http://www.googe.com

By default it uses UTF-8 and it would encrypt to:

뤟౏羜ڮ胂淺弊놛荧ꠃ錺槝ヸ蘜ầᄼꕒヘ⍩㗪潺뱂施㒞ꨛ殳硪픴ی뿨춃�燲ᯁﱪ뙊힓琲鯖嶑⨹갂Ѭ쳀鿜�྄䋖⭫ퟂ㪏�荾ꆺשּ붹梾麦膛

And decrypts back to:

Barnabe Googes Information & Homepage | Search and Research on B���Ax2�!��f�M]18/01/20�;18/01[�;>َ�l?����m��*-��+��^A[=�

What I've attempted

  • I've attempted to change to other Encodings, but UTF-8 seem to affect the decrypted text the least.
  • Changed to different types of padding, but Padding.Zeros seems the best. I also can't use Padding.None because it throws a NotSupportedException: bad data length.
  • Changed the Mode to CBC (Not that it should matter).
  • Flush/Close CryptoStream so it could flush the final block, or something.
  • Just in case the fault rested with the title, I used WebUtility.HtmlDecode() to decode the title, but it didn't affect it.

Encryption Method

The encryption below uses AES Encryption, as you can see. I want to point out that key and IV are two global strings within the same class as both of the Encryption and Decryption methods. The reason I've done this is to mess around with different encodings and CryptographyServiceProviders, just if by chance a random change works. Please ignore these as they are constant and won't affect the final encryption/decryption.

public static byte[] EncryptStringToBytes(string plainText, Encoding Enc)
{

    if (plainText == null || plainText.Length <= 0)
            throw new ArgumentNullException("plainText");
    byte[] encrypted;
    using (AesCryptoServiceProvider tdsAlg = new AesCryptoServiceProvider())
    {
         tdsAlg.Key = (byte[])Enc.GetBytes(key).Take(tdsAlg.Key.Length).ToArray();
         tdsAlg.IV = (byte[])Enc.GetBytes(IV).Take(tdsAlg.IV.Length).ToArray();
         tdsAlg.Padding = PaddingMode.Zeros;
         tdsAlg.Mode = CipherMode.CBC;
         ICryptoTransform encryptor = tdsAlg.CreateEncryptor(tdsAlg.Key, tdsAlg.IV);

         using (MemoryStream msEncrypt = new MemoryStream())
         {
             using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
             {
                 using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                 {
                     swEncrypt.Write(plainText);
                 }
                 encrypted = msEncrypt.ToArray();
                 csEncrypt.Close();
             }
         }
    }

    return encrypted;
}

Decryption Method

public static string DecryptStringFromBytes(byte[] cipherText,Encoding Enc)
{
    if (cipherText == null || cipherText.Length <= 0)
        throw new ArgumentNullException("cipherText");

    string plaintext = null;

    using (AesCryptoServiceProvider tdsAlg = new AesCryptoServiceProvider())
    {
        tdsAlg.Key = (byte[])Enc.GetBytes(key).Take(tdsAlg.Key.Length).ToArray();
        tdsAlg.IV = (byte[])Enc.GetBytes(IV).Take(tdsAlg.IV.Length).ToArray() ;
        tdsAlg.Padding = PaddingMode.Zeros;
        tdsAlg.Mode = CipherMode.CBC;
        ICryptoTransform decryptor = tdsAlg.CreateDecryptor();

        using (MemoryStream msDecrypt = new MemoryStream(cipherText))
        {
            using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
            {
                using (StreamReader srDecrypt = new StreamReader(csDecrypt,true))
                {
                    plaintext = srDecrypt.ReadToEnd().Replace("\0","");
                    csDecrypt.Close();
                    return plaintext.Replace("\0",string.Empty);
                }
            }
        }
   }    
   return plaintext;    
}

Bootnote

Just in case it matters, I'm using this to get the title of the webpage, but as I've mentioned using HtmlDecode doesn't affect it.

WebClient x = new WebClient();
string source = x.DownloadString(Url);
x.Dispose();
string title= Regex.Match(source, @"\<title\b[^>]*\>\s*(?<Title>[\s\S]*?)\</title\>", RegexOptions.IgnoreCase).Groups["Title"].Value;
title = title.Replace(";", " ");
return title;
like image 433
Brownish Monster Avatar asked Jan 18 '13 18:01

Brownish Monster


People also ask

What does decrypting messages mean?

What is Decryption. Definition: The conversion of encrypted data into its original form is called Decryption. It is generally a reverse process of encryption. It decodes the encrypted information so that an authorized user can only decrypt the data because decryption requires a secret key or password.

What is data known as once it has been decrypted?

In computing, unencrypted data is also known as plaintext, and encrypted data is called ciphertext. The formulas used to encode and decode messages are called encryption algorithms, or ciphers.

Is a message before it has been encrypted or after it has been decrypted?

Messages and files are encrypted before they leave the phone or computer and aren't decrypted until they reach their destination. Hackers can't access data on the server because they don't have the private keys required to decrypt the data. Instead, secret keys are stored on the individual user's device.


1 Answers

Thanks to Hans Passant I found the solution. The problem was that I was using Encoding.GetString() or Encoding.GetBytes() when I was encrypting and decrypting, when I should have been using Convert.ToBase64String() or Convert.FromBase64String().

like image 152
Brownish Monster Avatar answered Nov 15 '22 18:11

Brownish Monster