Sonntag, 1. März 2015

RSA Verschlüsselung

Nachdem ich vor kurzem AES als Beispiel einer symmetrischen Verschlüsselung beschrieben habe, möchte ich heute nun RSA als Beispiel einer asymmetrischen Verschlüsselung beschreiben. Solche Verfahren sind, auf Grund ihrer Funktionsweise, auch unter dem Namen Public-Key-Verschlüsselungsverfahren bekannt. Denn nun gibt es nicht nur einen Schlüssel zur Ver- und Entschlüsselung, sondern zwei: Einen öffentlichen zur Verschlüsselung und einen privaten zur Entschlüsselung. Der öffentliche Schlüssel kann frei weitergegeben werden und muss dem Sender bekannt sein. Dieser verschlüsselt mit dem öffentlichen Schlüssel des Empfängers und schickt die Nachricht an den Empfänger. Dieser kann diese nun mit dem dazugehörigen privaten Schlüssel entschlüsseln, der private Schlüssel sollte also nicht weitergegeben werden.
Dies zeigt direkt einen wesentlichen Vorteil der asymmetrischen Verschlüsselung: Bei symmetrischen Verfahren muss man sich irgendwie auf einen Schlüssel einigen, in dem zum Beispiel ein Teilnehmer diesen aussucht und dann dem anderen mitteilt. Dieses Mitteilen in irgendeiner Form kann auch abgehört werden, wenn es in unverschlüsselter Form erfolgt, und wir haben nichts erreicht. Bei asymmetrischen Verfahren fällt dieser Schritt nun weg! Wir müssen nur unseren öffentlichen Schlüssel zur Verfügung stellen, was auch jeder mithören kann (der Verteilungsweg muss allerdings immer noch authentisch sein!). Den privaten Schlüssel müssen wir nie weiterschicken und können ihn irgendwo sicher verwahren / wegschließen.
Ein Nachteil asymmetrischer Verschlüsselung ist die Geschwindigkeit, Ver- und Entschlüsseln ist meistens deutlicher langsamer als bei symmetrischen Verfahren.
Asymmetrische Verfahren basieren auf sogenannten Einwegfunktionen, bei denen eine Richtung leicht zu berechnen ist, die andere jedoch hart.

Hier möchte ich die Implementierung des RSA Verfahrens in C# beschreiben. RSA basiert auf der vermuteten Härte der Primfaktorzerlegung. Zur Schlüsselerzeugung werden 2 Primzahlen p und q gewählt und deren Produkt n berechnet. Berechne φ(n) = (p - 1)(q - 1) und wähle e teilerfremd zu φ(n). Berechne dann das multiplikative Inverse d von e bezüglich φ(n). Der öffentliche Schlüssel ist dann (e, n) und der private (d, n). Die verschlüsselte Nachricht berechnet sich dann zu c = m^e mod n, das Entschlüsseln erfolgt mit m = c^d mod n.

Damit genug zur Theorie, kommen wir zum Code. In C# steht uns dafür die Klasse RSACryptoServiceProvider zur Verfügung. Die Benutzung dieser ist allerdings deutlich anders die Verwendung von Code für symmetrische Verschlüsselungen, auf Grund der anderen Verwendung: Bei RSA muss zuerst der öffentliche / private Schlüssel erzeugt werden. Dann leiten wir unserem Kommunikationspartner unseren öffentlichen Schlüssel zu, sodass dieser für uns verschlüsseln kann. Anschließend entschlüsseln wir mit unserem privaten Schlüssel.

Beim Anlegen einer neuen Instanz der Klasse RSACryptoServiceProvider wird automatisch ein Schlüsselpaar angelegt, im Konstruktor können wir optional dessen Größe etc. angeben. Mit der Funktion ExportParameters() können wir (u.A.) unsere Schlüssel exportieren. Diese Funktion erwartet einen Boolean Parameter, welcher angibt, ob wir die privaten Informationen mit exportieren wollen. Dies tuen wir z.B. dann, wenn wir diese an unsere Entschlüsselungsfunktion schicken. Die andere Variante wählen wir, um unserem Kommunikationspartner unseren öffentlichen Schlüssel zu schicken. Mit ImportParameters() kann eine RSACryptoServiceProvider Instanz die Parameter importieren.

Und hier der Code:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

using System.Security.Cryptography;

namespace RSA2
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            byte[] dataToEncrypt = System.Text.Encoding.Unicode.GetBytes("This is a secret.");
            byte[] encryptedData;
            byte[] decryptedData;

            RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();

            encryptedData = RSAEncrypt(dataToEncrypt, RSA.ExportParameters(false));

            MessageBox.Show("Encrypted: " + System.Text.Encoding.Unicode.GetString(encryptedData));

            decryptedData = RSADecrypt(encryptedData, RSA.ExportParameters(true));

            MessageBox.Show("Decrypted: " + System.Text.Encoding.Unicode.GetString(decryptedData));
        }


        static public byte[] RSAEncrypt(byte[] DataToEncrypt, RSAParameters RSAKeyInfo)
        {
            byte[] encryptedData;

            RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
            RSA.ImportParameters(RSAKeyInfo);

            encryptedData = RSA.Encrypt(DataToEncrypt, false);

            return encryptedData;
        }

        static public byte[] RSADecrypt(byte[] DataToDecrypt, RSAParameters RSAKeyInfo)
        {
            byte[] decryptedData;

            RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
            RSA.ImportParameters(RSAKeyInfo);

            decryptedData = RSA.Decrypt(DataToDecrypt, false);

            return decryptedData;
        }
    }
}

Kommentare:

  1. Hinzuzufügen ist noch, dass das Verschlüsseln der eigentlichen Nachricht nicht mehr praktiziert wird/werden sollte, da dies wie bereits geschrieben unfass Aufwändig z.B.: bei E-Mail (10.000+ Zeichen) werden kann. Hierfür kann man z.B.: die Kombination eine symmetrischen und asymmetrischen Verschlüsslungsverfahren verwenden, wodurch die Nachricht symmetrisch Verschlüsselt wird und nur der symmetrische Schlüssel mithilfe der asymmetrischen Verschlüsslung übertragen wird. Siehe Wikipedia: Pretty Good Privacy

    https://de.wikipedia.org/wiki/Pretty_Good_Privacy

    AntwortenLöschen
    Antworten
    1. Ich korrigiere mich und nehme die Aussage "...nicht mehr praktiziert wird/werden sollte..." zurück. Jedoch ist der andere Aspekt nicht außenvor zu lassen.

      Löschen