Hello, so I have a more complex class in another file, but I have duplicated my trouble on a simpler class which I will show to you. I am trying to base64 encode a path via cipher text, either a good idea or a bad idea. Anyway, I am noticing that the cryptography decrypts, but the cipher text varies and is never the same twice. I was wondering if you could spot why it's doing it. My knee jerk reaction to this is that one of the input variables for the crypto method is changing between calls, but I can't see where it is. Any help would be appreciated, the data security books are to no avail.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Security.Cryptography;
using System.IO;

namespace EncryptionTest {

    class Program {

        static void Main(string[] args) {

            String plainText = "SomeFolder";
            for (int i = 0; i < 100; i++) {
                byte[] encryptedA = EncryptBase64(plainText);
                //Console.WriteLine("Cipher Text: " + Encoding.ASCII.GetString(encryptedA));
                String plainTextB = DecryptBase64(encryptedA);
                Console.WriteLine("Plaintext B: " + plainTextB);
                Console.WriteLine();
            }//end loop

            Console.Write("Press any key to continue... ");
            Console.ReadKey();
        }//end method

        /// <summary>
        /// Gets the decrypted data. 
        /// Tested... Works... 
        /// </summary>
        /// <returns></returns>
        public static String DecryptBase64(byte[] cipherText) {
            SymmetricAlgorithm crypt = System.Security.Cryptography.Aes.Create();
            Encoding Encoding = System.Text.Encoding.UTF8;
            PaddingMode PaddingMode = System.Security.Cryptography.PaddingMode.ISO10126;

            byte[] key = Encoding.GetBytes("Madcat90".PadRight(crypt.Key.Length, '0').ToCharArray(), 0, crypt.Key.Length); ;
            byte[] iv = Encoding.GetBytes("Madcat90".PadRight(crypt.IV.Length, '0').ToCharArray(), 0, crypt.IV.Length);

            crypt.Padding = PaddingMode;

            crypt.Mode = CipherMode.CBC;

            crypt.Key = key;
            crypt.IV = iv;

            Console.WriteLine(crypt.GetType().Name);
            Console.WriteLine(crypt.Padding.ToString());
            Console.WriteLine(crypt.Mode.ToString());
            Console.WriteLine(String.Format("Key: {0}", System.Text.Encoding.UTF8.GetString(key)));
            Console.WriteLine(String.Format("IV: {0}", System.Text.Encoding.UTF8.GetString(iv)));
            Console.WriteLine(String.Format("Cipher Text: {0}", System.Text.Encoding.UTF8.GetString(cipherText)));

            byte[] decrypted = new byte[cipherText.Length];

            String result = null;
            MemoryStream cipherStream = new MemoryStream(cipherText);
            ICryptoTransform transform = new FromBase64Transform();
            CryptoStream csDecode = new CryptoStream(cipherStream, transform, CryptoStreamMode.Read);
            CryptoStream crypto = new CryptoStream(csDecode, crypt.CreateDecryptor(crypt.Key, crypt.IV), CryptoStreamMode.Read);
            StreamReader reader = new StreamReader(crypto);
            result = reader.ReadToEnd();
            reader.Close();
            crypto.Close();

            crypto.Clear();

            return result;
        }//end method

        /// <summary>
        /// Encrypt to base64 byte array. 
        /// Tested... Works... 
        /// </summary>
        /// <param name="plainText"></param>
        /// <returns></returns>
        public static byte[] EncryptBase64(String plainText) {
            SymmetricAlgorithm crypt = System.Security.Cryptography.Aes.Create();
            Encoding Encoding = System.Text.Encoding.UTF8;
            PaddingMode PaddingMode = System.Security.Cryptography.PaddingMode.ISO10126;

            byte[] key = Encoding.GetBytes("Madcat90".PadRight(crypt.Key.Length, '0').ToCharArray(), 0, crypt.Key.Length); ;
            byte[] iv = Encoding.GetBytes("Madcat90".PadRight(crypt.IV.Length, '0').ToCharArray(), 0, crypt.IV.Length);

            crypt.Padding = PaddingMode;

            crypt.Mode = CipherMode.CBC;

            Console.WriteLine(crypt.GetType().Name);
            Console.WriteLine(crypt.Padding.ToString());
            Console.WriteLine(crypt.Mode.ToString());
            Console.WriteLine(String.Format("Key: {0}", System.Text.Encoding.UTF8.GetString(key)));
            Console.WriteLine(String.Format("IV: {0}", System.Text.Encoding.UTF8.GetString(iv)));
            Console.WriteLine(String.Format("Plain Text: {0}", plainText));

            MemoryStream plainTextStream = new MemoryStream(System.Text.Encoding.ASCII.GetBytes(plainText));
            crypt.Padding = PaddingMode;
            byte[] plainTextBytes = Encoding.GetBytes(plainText);
            byte[] encrypted = null;

            crypt.Key = key;
            crypt.IV = iv;

            // encrypt the data using a CryptoStream
            MemoryStream encryptedStream = new MemoryStream();
            ICryptoTransform encoder = new ToBase64Transform();
            CryptoStream csEncoder = new CryptoStream(encryptedStream, encoder, CryptoStreamMode.Write);
            ICryptoTransform encryptor = crypt.CreateEncryptor(crypt.Key, crypt.IV);
            CryptoStream crypto = new CryptoStream(csEncoder, encryptor, CryptoStreamMode.Write);
            StreamWriter writer = new StreamWriter(crypto, Encoding);
            writer.Write(plainText);
            writer.Flush();
            crypto.FlushFinalBlock();
            encryptedStream.Position = 0;
            encrypted = encryptedStream.ToArray();

            crypto.Clear();

            return encrypted;
        }//end method

    }//end class

}//end namespace

Recommended Answers

All 7 Replies

Let me state that this is a GOOD THING. If the cypher always encoded to the same text then decryption is more likely.

Remember that you did write "the cryptography decrypts" so it's not broken.

If I understand it correctly however, the cryptography must be deterministic, therefore it varies by it's input arguments, the symmetric algorithim, the padding mode, the cipher mode, the password, and the iv (could have missed one). You should run the program and compare the hashes which I have displayed on screen. This would essentially create N folders (I have a pathing function). At least post back whether the cipher text varies on your system.

Again, I read that you don't like how the encrypted text can vary and not that it didn't decrypt.

Maybe I should use an example where the encrypted text does vary. As you are into crypto, look at the "book cipher."
Reference: https://en.wikipedia.org/wiki/Book_cipher

If I were to use said cipher I would not reuse a code. That is, for my codebook I would line out the word so I would be sending unique encrypted text so to make the code breaker's work much harder.

Well thank you very much for replying, I would like to hear from other people too if they would like to comment on it also. I am sort of new to this encryption stuff, and I do believe that this particular aspect of cryptography has never really been commented on online yet. The data security book certainly didn't mention it. I think I am going to add a lookup routine to my other code, such that it doesn't make the same directory twice. I am sort of working on a drive encryptor, which may not be feasible to finish.

For what it's worth I tried a little test in Java and the AES encrypted output was always the same for the same input values.

I'm no expert, but from my reading of a few web sites the algorithm looks like there is no dependency on anything other than the explicit inputs,
Mybe the problem lies elsewhere in your code?

I'm no cryptography expert either, but I've refactored your code. If you create all your objects once, the output is what you expect. So it has to do something with one of the properties, but no time to inspect in detail now.

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace DW535630
{
    internal class Program
    {
        static SymmetricAlgorithm crypt = System.Security.Cryptography.Aes.Create();
        static Encoding Encoding = System.Text.Encoding.UTF8;
        static PaddingMode PaddingMode = System.Security.Cryptography.PaddingMode.ISO10126;
        static byte[] key = Encoding.GetBytes("Madcat90".PadRight(crypt.Key.Length, '0').ToCharArray(), 0, crypt.Key.Length);
        static byte[] iv = Encoding.GetBytes("Madcat90".PadRight(crypt.IV.Length, '0').ToCharArray(), 0, crypt.IV.Length);

        private static void Main()
        {
            crypt.Padding = PaddingMode;
            crypt.Mode = CipherMode.CBC;
            crypt.Key = key;
            crypt.IV = iv;

            String plainText = "SomeFolder";
            byte[] encryptedA = EncryptBase64(plainText);
            for (int i = 0; i < 10; i++) {
                //Console.WriteLine("Cipher Text: " + Encoding.ASCII.GetString(encryptedA));
                String plainTextB = DecryptBase64(encryptedA);
                Console.WriteLine("Plaintext B: " + plainTextB);
                Console.WriteLine();
            }

            Console.Write("Press any key to continue... ");
            Console.ReadKey();
        }

        public static String DecryptBase64(byte[] cipherText) 
        {
            Console.WriteLine(crypt.GetType().Name);
            Console.WriteLine(crypt.Padding.ToString());
            Console.WriteLine(crypt.Mode.ToString());
            Console.WriteLine(String.Format("Key: {0}", System.Text.Encoding.UTF8.GetString(key)));
            Console.WriteLine(String.Format("IV: {0}", System.Text.Encoding.UTF8.GetString(iv)));
            Console.WriteLine(String.Format("Cipher Text: {0}", System.Text.Encoding.UTF8.GetString(cipherText)));

            byte[] decrypted = new byte[cipherText.Length];

            String result = null;
            MemoryStream cipherStream = new MemoryStream(cipherText);
            ICryptoTransform transform = new FromBase64Transform();
            CryptoStream csDecode = new CryptoStream(cipherStream, transform, CryptoStreamMode.Read);
            CryptoStream crypto = new CryptoStream(csDecode, crypt.CreateDecryptor(crypt.Key, crypt.IV), CryptoStreamMode.Read);
            StreamReader reader = new StreamReader(crypto);
            result = reader.ReadToEnd();
            reader.Close();
            crypto.Close();

            crypto.Clear();

            return result;
        }

        public static byte[] EncryptBase64(String plainText) 
        {
            Console.WriteLine(crypt.GetType().Name);
            Console.WriteLine(crypt.Padding.ToString());
            Console.WriteLine(crypt.Mode.ToString());
            Console.WriteLine(String.Format("Key: {0}", System.Text.Encoding.UTF8.GetString(key)));
            Console.WriteLine(String.Format("IV: {0}", System.Text.Encoding.UTF8.GetString(iv)));
            Console.WriteLine(String.Format("Plain Text: {0}", plainText));

            MemoryStream plainTextStream = new MemoryStream(System.Text.Encoding.ASCII.GetBytes(plainText));
            crypt.Padding = PaddingMode;
            byte[] plainTextBytes = Encoding.GetBytes(plainText);
            byte[] encrypted = null;

            MemoryStream encryptedStream = new MemoryStream();
            ICryptoTransform encoder = new ToBase64Transform();
            CryptoStream csEncoder = new CryptoStream(encryptedStream, encoder, CryptoStreamMode.Write);
            ICryptoTransform encryptor = crypt.CreateEncryptor(crypt.Key, crypt.IV);
            CryptoStream crypto = new CryptoStream(csEncoder, encryptor, CryptoStreamMode.Write);
            StreamWriter writer = new StreamWriter(crypto, Encoding);
            writer.Write(plainText);
            writer.Flush();
            crypto.FlushFinalBlock();
            encryptedStream.Position = 0;
            encrypted = encryptedStream.ToArray();

            crypto.Clear();

            return encrypted;
        }
    }
}

plainText gets updated on each pass of the loop. Should be OK, but maybe... ?

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.