Entwickler-Ecke

Sonstiges (.NET) - RSA-Verschlüsselung mit Zertifikaten


Määx - Di 15.10.13 10:49
Titel: RSA-Verschlüsselung mit Zertifikaten
Hallo zusammen,

ich möchte gerne die Übertragung meiner Daten via RSA verschlüsseln. Hierzu habe ihc mir eine Zertifikat (RSA 2048) erstellt und auf dem Client den PublicKey installiert, auf dem Server den PrivateKey.
Um das ganze zu ver/entschlüsseln habe ich folgende Methoden verwendet:

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
public static string  encrypt(string text)
        {
            X509Certificate2 cert = LoadCert(EnumCipheringTarget.ClientServer);
            RSACryptoServiceProvider publicprovider = (RSACryptoServiceProvider)cert.PublicKey.Key;
            byte[] encrypted = publicprovider.Encrypt(GetBytes(text), false);
            return GetString(encrypted);
        }
public static string decrypt(string text)
        {
            X509Certificate2 cert = LoadCert(EnumCipheringTarget.ClientServer);
            RSACryptoServiceProvider provider = (RSACryptoServiceProvider)cert.PrivateKey;
            byte[] decryptedBytes = provider.Decrypt(GetBytes(text), false);
            return GetString(decryptedBytes);
        }

Um das Zertifikat auszuwählen habe ich folgendes gemacht:

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
private static X509Certificate2 LoadCert(EnumCipheringTarget cipherTarget)
        {
            X509Store store = new X509Store(StoreLocation.CurrentUser);
            store.Open(OpenFlags.ReadOnly);
            X509Certificate2Collection certCollection = store.Certificates;
            X509Certificate2 cert = null;

            string certSubject = "";
            switch (cipherTarget)
            {
                case EnumCipheringTarget.ClientServer:
                    certSubject = "CN=MY_CERT_TO_SERVER";
                    break;
                case EnumCipheringTarget.ServerDB:
                    certSubject = "CN=MY_CERT_TO_DB";
                    break;

                default:
                    return null;
            }

            foreach (X509Certificate2 c in certCollection)
            {
                if (c.Subject == certSubject)
                {
                    cert = c;
                    break;
                }
            }
            store.Close();
            return cert;
        }

Zur Umwanldung in die String/Byte[]:

C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
static byte[] GetBytes(string str)
        {
            byte[] bytes = new byte[str.Length * sizeof(char)];
            System.Buffer.BlockCopy(str.ToCharArray(), 0, bytes, 0, bytes.Length);
            return bytes;
        }
static string GetString(byte[] bytes)
        {
            char[] chars = new char[bytes.Length / sizeof(char)];
            System.Buffer.BlockCopy(bytes, 0, chars, 0, bytes.Length);
            return new string(chars);
        }


Das Funktioniert auch sehr gut wenn ich kurze Texte nehme wie "Hallo" o.ä. eingebe (zumindestens bekomme ich dann ein Wirrwar von Zeichen und nach dem Decrypt wiede rmeinen Text). Aber sobald der Text länger wird bekomme ich die Fehlermeldung, dass die zulässige Länge überschirtten wurde! Woran liegt das? Es muss doch auch möglich sein lange Texte zu verschlüsseln??

Vielen Dank für eure Hilfe!
Määx


Ralf Jansen - Di 15.10.13 11:17

RSA ist eher nicht geeignet für große Datenmengen, ist einfach zu langsam. Beim RSACryptoServiceProvider muß die zu verschlüsselnde Datenmenge kürzer als der Schlüssel(minus minimalem Padding) sein.

Wenn du große Datenmengen verschlüsseln willst nimm ein symmetrisches Verfahren. Wenn du ein Schlüsselauustausch Problem hast dann kombiniere RSA mit einem symmetrischen Verfahren. Und wenn du das nicht selbst implementieren willst nimm SSL das gibts fertig im Framework.