Problem z szyfrowaniem ciągu cyfr za pomocą AES

0

Witam. Piszę aplikację, która wykorzystuje szyfrowanie AES. Gdy szyfruję za jej pomocą ciągi znaków zawierające choćby 1 znak inny niż cyfra, deszyfrowanie daje dobry wynik, lecz gdy szyfruję i deszyfruję ciąg cyfr, otrzymuję lekko dziwny wynik. Jako kodowania znaków używam Unicode, do oddzielania danych w ciągu znaku ¶, tak samo (może nie jest to dobry sposób) używam Unicode do szyfrowania klucza i IV (bo ciąg szyfrowany może zawierać znaki Unicode), a przesyłam wszystko w jednym pakiecie. Jeśli byłoby coś jeszcze potrzebne, podeślę. Pozdrawiam :).

0

pokaż kod.
i zdajesz sobie sprawę, że liczba zapisana binarnie to nie to samo co liczba jako tekst?

0

Klient:

Byte[] data = Encoding.Unicode.GetBytes(textBox1.Text + "¶" + Encoding.Unicode.GetString(encrypt(textBox2.Text, aes.Key, aes.IV)) + "¶" + Encoding.Unicode.GetString(aes.Key) + "¶" + Encoding.Unicode.GetString(aes.IV));

static byte[] encrypt(string plainText, byte[] Key, byte[] IV)
        {
            if (plainText == null || plainText.Length <= 0)
                throw new ArgumentNullException("plainText");
            if (Key == null || Key.Length <= 0)
                throw new ArgumentNullException("Key");
            if (IV == null || IV.Length <= 0)
                throw new ArgumentNullException("Key");

            MemoryStream msEncrypt = null;
            CryptoStream csEncrypt = null;
            StreamWriter swEncrypt = null;

            RijndaelManaged aesAlg = null;

            try
            {
                aesAlg = new RijndaelManaged();
                aesAlg.Key = Key;
                aesAlg.IV = IV;

                ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);

                msEncrypt = new MemoryStream();
                csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write);
                swEncrypt = new StreamWriter(csEncrypt);

                swEncrypt.Write(plainText);

            }
            finally
            {
                if (swEncrypt != null)
                    swEncrypt.Close();
                if (csEncrypt != null)
                    csEncrypt.Close();
                if (msEncrypt != null)
                    msEncrypt.Close();

                if (aesAlg != null)
                    aesAlg.Clear();
            }

            return msEncrypt.ToArray();

        }

Serwer:

                Aes aes = AesManaged.Create();
                aes.Key = Encoding.Unicode.GetBytes(encodedData[2]);
                aes.IV = Encoding.Unicode.GetBytes(encodedData[3]);

                Boolean isLogged = false;

                while (sqlDataReader.Read())
                {
                    MessageBox.Show(decrypt(Encoding.Unicode.GetBytes(encodedData[1]), Encoding.Unicode.GetBytes(encodedData[2]), Encoding.Unicode.GetBytes(encodedData[3])).Trim() + "\n" + sqlDataReader[1].ToString());
                    if (sqlDataReader[0].ToString() == encodedData[0] && decrypt(Encoding.Unicode.GetBytes(encodedData[1]), Encoding.Unicode.GetBytes(encodedData[2]), Encoding.Unicode.GetBytes(encodedData[3])).Trim() == sqlDataReader[1].ToString())
                    {
                        networkStream.Write(Encoding.Unicode.GetBytes("1"), 0, Encoding.Unicode.GetBytes("1").Length);
                        users.Add(new TechnicUser(ref tcpClient, ref networkStream, (int)sqlDataReader[2]));

                        isLogged = true;

                        sqlDataReader.Close();
                        break;
                    }
                }

static string decrypt(byte[] cipherText, byte[] Key, byte[] IV)
        {
            if (cipherText == null || cipherText.Length <= 0)
                throw new ArgumentNullException("cipherText");
            if (Key == null || Key.Length <= 0)
                throw new ArgumentNullException("Key");
            if (IV == null || IV.Length <= 0)
                throw new ArgumentNullException("Key");

            MemoryStream msDecrypt = null;
            CryptoStream csDecrypt = null;
            StreamReader srDecrypt = null;

            RijndaelManaged aesAlg = null;

            string plaintext = null;

            try
            {
                aesAlg = new RijndaelManaged();
                aesAlg.Padding = PaddingMode.None;
                aesAlg.Key = Key;
                aesAlg.IV = IV;

                ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);

                msDecrypt = new MemoryStream(cipherText);
                csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read);
                srDecrypt = new StreamReader(csDecrypt);

                plaintext = srDecrypt.ReadToEnd();
            }
            finally
            {
                if (srDecrypt != null)
                    srDecrypt.Close();
                if (csDecrypt != null)
                    csDecrypt.Close();
                if (msDecrypt != null)
                    msDecrypt.Close();

                if (aesAlg != null)
                    aesAlg.Clear();
            }

            return plaintext;
        }

Liczby szyfruję jako string, więc nie powinno być problemu.

1

Strasznie zagmatwane to co napisałeś, przynajmniej dla mnie można cała procedurę zoptymalizować do kilku linijek kodu, wiem bo ostatnio pisałem klasę która szyfruje, odszyfrowuje oraz serializuje, deserializuje, wrzuca za razem do pamięci lub zapisuje do pliku XML. Klasa została przetestowana na różne sposoby i nie wykryłem błędów, logika szyfrowania i odszyfrowania danych poniżej:

SZYFROWANIE:

        private byte[] EncryptData(string DataToEncrypt, string Key)
        {
            const int rsa = 1;
            var cspParameters = new CspParameters(rsa);
            cspParameters.Flags = CspProviderFlags.UseMachineKeyStore;
            cspParameters.KeyContainerName = Key;
            var rsaCryptoServiceProvider = new RSACryptoServiceProvider(cspParameters);
            return rsaCryptoServiceProvider.Encrypt(new UnicodeEncoding().GetBytes(DataToEncrypt), true);
        }

ODSZYFROWANIE:

        private string DecryptData(string Key)
        {
            const int rsa = 1;
            var cspParameters = new CspParameters(rsa);
            cspParameters.Flags = CspProviderFlags.UseMachineKeyStore;
            cspParameters.KeyContainerName = Key;
            var rsaCryptoServiceProvider = new RSACryptoServiceProvider(cspParameters);
            var decrypted = rsaCryptoServiceProvider.Decrypt(this.DataEncrypt, true);
            var result = new UnicodeEncoding().GetString(decrypted);
            return result;
        }
 

Oprócz tego jest naturalnie dodana cała logika obsługi błędów (w tym podania złego klucza przy deszyfrowaniu informacji itp...). Mam nadzieje że pomogłem. Pozdrawiam Oskar Oleszkiewicz

0

Aha i nie rozumiem dlaczego np klucz szyfrowania/ odszyfrowania przekazujesz w tak nienaturalny sposób jako byte[]? Nie prościej stworzyć taki sposób komunikacji z obiektami/ metodami aby było to jak najbardziej naturalne? U mnie taki klucz można wklepać z palca pobrać z textboxa po prostu jest to ciąg znaków...

1 użytkowników online, w tym zalogowanych: 0, gości: 1