poniedziałek, 4 lutego 2013

70-516 Szyfrowanie danych

1. Szyfrowanie symetryczne
 

Szyfrowanie symetryczne opiera się na jednym kluczu użytym zarówno do szyfrowania jak i deszyfrowania danych. Obecnie zalecane jest używanie algorytmu Rijndael - dokładny opis można znaleźć w wikipedii: http://en.wikipedia.org/wiki/Advanced_Encryption_Standard


Code:
    class Program
    {
        static void Main(string[] args)
        {
            using (var rm = new RijndaelManaged())
            {
                byte[] encrypted = EncryptRijndaelManaged("Ala ma kota", rm.Key, rm.IV);
                string decrypted = DecryptRijndaelManaged(encrypted, rm.Key, rm.IV);
                Console.WriteLine(decrypted);
            }
        }

        public static byte[] EncryptRijndaelManaged(string input, byte[] key, byte[] IV)
        {
            byte[] encrypted;
            using (var rm = new RijndaelManaged())
            {
                rm.Key = key;
                rm.IV = IV;
                ICryptoTransform encryptor = rm.CreateEncryptor(rm.Key, rm.IV);
                using (var ms = new MemoryStream())
                {
                    using (var cs = new CryptoStream(ms, encryptor, CryptoStreamMode.Write))
                    {
                        using (var swEncrypt = new StreamWriter(cs))
                        {
                            swEncrypt.Write(input);
                        }
                        encrypted = ms.ToArray();
                    }
                }
            }

            return encrypted;
        }

        public static string DecryptRijndaelManaged(byte[] input, byte[] key, byte[] IV)
        {
            string decrypted;
            using (var rm = new RijndaelManaged())
            {
                rm.Key = key;
                rm.IV = IV;
                ICryptoTransform decryptor = rm.CreateDecryptor(rm.Key, rm.IV);
                using (var ms = new MemoryStream(input))
                {
                    using (var cs = new CryptoStream(ms, decryptor, CryptoStreamMode.Read))
                    {
                        using (var swDecrypt = new StreamReader(cs))
                        {
                            decrypted = swDecrypt.ReadToEnd();
                        }
                    }
                }
            }

            return decrypted;
        }
    }



2. Szyfrowanie asymetryczne


Jest to dużo bardziej bezpieczne rozwiązanie. Tworzone są dwa klucze:

  • prywatny - trzymany na serwerze w bezpiecznym i niedostępnym miejscy
  • publiczny - wysyłany do zainteresowanych
Szyfrowanie odbywa się za pomocą jednego z tych kluczy, a odszyfrowanie za pomocą drugiego. Jednym z najpopularniejszych algorytmów asymetrycznych jest RSA. Przykład szyfrowania i deszyfrowania:

Code:
        public static byte[] EncryptRsa(string input)
        {
            const int rsa = 1;
            var cspParameters = new CspParameters(rsa);
            cspParameters.Flags = CspProviderFlags.UseMachineKeyStore;
            cspParameters.KeyContainerName = "My Keys";
            var rsaCryptoServiceProvider = new RSACryptoServiceProvider(cspParameters);
            byte[] encrypted = rsaCryptoServiceProvider.Encrypt(new UnicodeEncoding().GetBytes(input), true);

            return encrypted;
        }

        public static string DecryptRsa(byte[] input)
        {
            const int rsa = 1;
            var cspParameters = new CspParameters(rsa);
            cspParameters.Flags = CspProviderFlags.UseMachineKeyStore;
            cspParameters.KeyContainerName = "My Keys";
            var rsaCryptoServiceProvider = new RSACryptoServiceProvider(cspParameters);
            var decrypted = rsaCryptoServiceProvider.Decrypt(input, true);

            return new UnicodeEncoding().GetString(decrypted);
        }



3. Hashowanie
Hashowanie jest procesem jednokierunkowym, to znaczy hashujemy podany ciąg znaków zmieniając je w kod, jednak w drugą stronę nie jesteśmy już w stanie (w prosty sposób) odczytać stworzonego hasha.
Istnieje jednak ryzyko, że hashując np. hasło w bazie pojawią się dwa podobne wpisy. Rozwiązaniem tego problemu jest dodanie tzw. soli (Salt) którą dodaje się np. do hasła i taki ciąg znaków dopiero zostaje hashowany. Dzięki takiemu rozwiązaniu mamy znikome prawdopodobieństwo powtórzenia się hashy.
Obecnie zalecane jest stosowane algorytmu SHA256. Przykład użycia algorytmu:

Code:
        public static string Sha256Encryption(string input, string salt)
        {
            byte[] data = new UnicodeEncoding().GetBytes(input + salt);
            var sha256Managed = new SHA256Managed();
            var computeHash = sha256Managed.ComputeHash(data);

            return ToHex(computeHash);
        }

        private static string ToHex(byte[] computeHash)
        {
            var hex = new StringBuilder();
            foreach (var b in computeHash)
            {
                hex.AppendFormat("{0:x2}", b);
            }

            return hex.ToString();
        }



4. Cyfrowy podpis
Cyfrowy podpis gwarantuje, że wiadomość została niezmieniona i wysłana przez daną instytucję.
Przykład implementacji:

Code:
        public static byte[] CreateSignature(string input)
        {
            const int rsa = 24;
            var cspParameters = new CspParameters(24);
            cspParameters.Flags = CspProviderFlags.UseMachineKeyStore;
            cspParameters.KeyContainerName = "My Keys";
            var rsaCryptoServiceProvider = new RSACryptoServiceProvider(cspParameters);

            return rsaCryptoServiceProvider.SignData(new UnicodeEncoding().GetBytes(input), "SHA256");
        }

        public static bool CheckSign(string input, byte[] signature)
        {
            const int rsa = 24;
            var cspParameters = new CspParameters();
            cspParameters.Flags = CspProviderFlags.UseMachineKeyStore;
            cspParameters.KeyContainerName = "My Keys";
            var rsaCryptoServiceProvider = new RSACryptoServiceProvider(cspParameters);

            return rsaCryptoServiceProvider.VerifyData(new UnicodeEncoding().GetBytes(input), "SHA256", signature);
        }


1 komentarz:

  1. return rsaCryptoServiceProvider.SignData(new UnicodeEncoding().GetBytes(input), "SHA256");

    to zwraca 128 bajtów a nie 256 :(

    więc chyba coś nie tak ...

    OdpowiedzUsuń