Feedback

C# - Encrypt and Decrypt Strings

Veröffentlicht von am 18.08.2006
(11 Bewertungen)
This class encrypt and decrypt strings using the Rijndael algorithm .
using System;
using System.IO;
using System.Security.Cryptography;

/// <summary>
/// encrypt and decrypt strings
/// </summary>
public class Encryption
{
    /// <summary>
    /// Encrypts the string.
    /// </summary>
    /// <param name="clearText">The clear text.</param>
    /// <param name="Key">The key.</param>
    /// <param name="IV">The IV.</param>
    /// <returns></returns>
    private static byte[] EncryptString(byte[] clearText, byte[] Key, byte[] IV)
    {
        MemoryStream ms = new MemoryStream();
        Rijndael alg = Rijndael.Create();
        alg.Key = Key;
        alg.IV = IV;
        CryptoStream cs = new CryptoStream(ms, alg.CreateEncryptor(), CryptoStreamMode.Write);
        cs.Write(clearText, 0, clearText.Length);
        cs.Close();
        byte[] encryptedData = ms.ToArray();
        return encryptedData;
    }

    /// <summary>
    /// Encrypts the string.
    /// </summary>
    /// <param name="clearText">The clear text.</param>
    /// <param name="Password">The password.</param>
    /// <returns></returns>
    public static string EncryptString(string clearText, string Password)
    {
        byte[] clearBytes = System.Text.Encoding.Unicode.GetBytes(clearText);
        PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
        byte[] encryptedData = EncryptString(clearBytes, pdb.GetBytes(32), pdb.GetBytes(16));
        return Convert.ToBase64String(encryptedData);
    }

    /// <summary>
    /// Decrypts the string.
    /// </summary>
    /// <param name="cipherData">The cipher data.</param>
    /// <param name="Key">The key.</param>
    /// <param name="IV">The IV.</param>
    /// <returns></returns>
    private static byte[] DecryptString(byte[] cipherData, byte[] Key, byte[] IV)
    {
        MemoryStream ms = new MemoryStream();
        Rijndael alg = Rijndael.Create();
        alg.Key = Key;
        alg.IV = IV;
        CryptoStream cs = new CryptoStream(ms, alg.CreateDecryptor(), CryptoStreamMode.Write);
        cs.Write(cipherData, 0, cipherData.Length);
        cs.Close();
        byte[] decryptedData = ms.ToArray();
        return decryptedData;
    }

    /// <summary>
    /// Decrypts the string.
    /// </summary>
    /// <param name="cipherText">The cipher text.</param>
    /// <param name="Password">The password.</param>
    /// <returns></returns>
    public static string DecryptString(string cipherText, string Password)
    {
        byte[] cipherBytes = Convert.FromBase64String(cipherText);
        PasswordDeriveBytes pdb = new PasswordDeriveBytes(Password, new byte[] { 0x49, 0x76, 0x61, 0x6e, 0x20, 0x4d, 0x65, 0x64, 0x76, 0x65, 0x64, 0x65, 0x76 });
        byte[] decryptedData = DecryptString(cipherBytes, pdb.GetBytes(32), pdb.GetBytes(16));
        return System.Text.Encoding.Unicode.GetString(decryptedData);
    }
}

7 Kommentare zum Snippet

Rainbird schrieb am 04.11.2006:
Schade, dass das Snippet nicht Dokumentiert ist (Kein XML-Doku-Tags, keine Kommentare).
soxxing schrieb am 28.01.2008:
Danke, Vielen Dank
Genau sowas habe ich gesucht.
Leider keine Kommentare, naja man kann nich alles haben ;).
Jan Welker schrieb am 28.01.2008:
Ich habe XML Kommentare hinzugefügt.
thomas3577 schrieb am 16.12.2009:
Ich kenne mich mit dem Thema nicht so aus aber muss man für "cipherText" einfach irgend eine belibige Zeichenfolge wählen? Und muss bei "clearText" die gleiche Zeichenfolge stehen?
dariusarnold schrieb am 07.02.2013:
Hey, Ho..
Ich wüsste jetzt auch nicht wirklich was in den cipherText soll..
Kanns grad nicht ausprobiern weil ich grad nur mit dem Eier-Pad on bin..
Kann mir jemand weiterhelfen??
Vielleicht ja Herr Welker persönlich?! ;) ;)
dariusarnold schrieb am 08.02.2013:
Ups! Ist ja logisch..
Ich wollt's grad ausprobieren und hab mich gefragt, woher weiß die Methode eigentlich was sie Entschlüsseln soll..??
>>Cipher Text<< :D Naja.. kommt vor. Einfach auf dem Schlauch gestanden.
AI schrieb am 29.01.2026:
Das Snippet ist von 2006 und zeigt einen damals verbreiteten Ansatz: Rijndael per CryptoStream, Key und IV werden als Byte-Arrays übergeben und der resultierende Ciphertext als Byte[] zurückgegeben. Inhaltlich ist „String verschlüsseln/entschlüsseln“ weiterhin ein Standard-Problem, aber die damalige Umsetzung lässt heute zu viele wichtige Details offen (Authentizität, Key-Derivation, IV-Handling, Fehlermodi) und lädt in realen Anwendungen schnell zu unsicheren Nutzungsweisen ein.

Analyse nach heutigen Kriterien:
- Sicherheit: Symmetrische Verschlüsselung ohne Authentifizierung ist gefährlich. Moderne Anwendungen sollten AEAD verwenden (z. B. AES-GCM), damit Vertraulichkeit und Integrität gemeinsam abgesichert sind.
- Korrektheit: Rijndael ist nicht automatisch AES. AES ist Rijndael mit fester Blockgröße von 128 Bit. Für Interoperabilität sollte Aes statt Rijndael.Create verwendet werden.
- Key/IV-Handling: Das Snippet überlässt Key- und IV-Erzeugung dem Aufrufer. IVs müssen pro Verschlüsselung zufällig sein, Keys aus Passwörtern müssen über PBKDF2 abgeleitet werden.
- Robustheit: Streams werden nicht deterministisch freigegeben. Fehlerpfade sind unklar, Exceptions werden nicht differenziert behandelt.
- Cloud/Container: Moderne Crypto-APIs sind plattformübergreifend verfügbar, entscheidend ist sauberes Key-Management (Secrets nicht im Code oder in Dateien ablegen).
- Thread-Safety: Pro Aufruf erzeugte Crypto-Instanzen sind thread-safe nutzbar, statische Instanzen wären problematisch.

Modernisierte Variante (AES-GCM, PBKDF2, Base64-Payload):

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

public static class StringEncryption
{
public static string EncryptToBase64(string plaintext, string password)
{
byte[] salt = RandomNumberGenerator.GetBytes(16);
byte[] nonce = RandomNumberGenerator.GetBytes(12);

using var kdf = new Rfc2898DeriveBytes(password, salt, 150_000, HashAlgorithmName.SHA256);
byte[] key = kdf.GetBytes(32);

byte[] plainBytes = Encoding.UTF8.GetBytes(plaintext);
byte[] cipherBytes = new byte[plainBytes.Length];
byte[] tag = new byte[16];

using var aes = new AesGcm(key);
aes.Encrypt(nonce, plainBytes, cipherBytes, tag);

byte[] payload = new byte[1 + salt.Length + nonce.Length + tag.Length + cipherBytes.Length];
payload[0] = 1;
Buffer.BlockCopy(salt, 0, payload, 1, salt.Length);
Buffer.BlockCopy(nonce, 0, payload, 1 + salt.Length, nonce.Length);
Buffer.BlockCopy(tag, 0, payload, 1 + salt.Length + nonce.Length, tag.Length);
Buffer.BlockCopy(cipherBytes, 0, payload, 1 + salt.Length + nonce.Length + tag.Length, cipherBytes.Length);

CryptographicOperations.ZeroMemory(key);
return Convert.ToBase64String(payload);
}

public static string DecryptFromBase64(string base64Payload, string password)
{
byte[] payload = Convert.FromBase64String(base64Payload);

int offset = 1;
byte[] salt = new byte[16];
Buffer.BlockCopy(payload, offset, salt, 0, salt.Length);
offset += salt.Length;

byte[] nonce = new byte[12];
Buffer.BlockCopy(payload, offset, nonce, 0, nonce.Length);
offset += nonce.Length;

byte[] tag = new byte[16];
Buffer.BlockCopy(payload, offset, tag, 0, tag.Length);
offset += tag.Length;

byte[] cipher = new byte[payload.Length - offset];
Buffer.BlockCopy(payload, offset, cipher, 0, cipher.Length);

using var kdf = new Rfc2898DeriveBytes(password, salt, 150_000, HashAlgorithmName.SHA256);
byte[] key = kdf.GetBytes(32);

byte[] plainBytes = new byte[cipher.Length];
using var aes = new AesGcm(key);
aes.Decrypt(nonce, cipher, tag, plainBytes);

CryptographicOperations.ZeroMemory(key);
return Encoding.UTF8.GetString(plainBytes);
}
}


Warum das heute objektiv besser ist:
- Sicherheit: Authentifizierte Verschlüsselung verhindert stille Manipulationen.
- Key-Management: Klare Strategie für Salt, Nonce und Passwort-Ableitung.
- Plattformtauglichkeit: Läuft unverändert auf Windows, Linux und macOS.
- Wartbarkeit: Versionierbares Payload-Format und klarer Verantwortungsbereich.

Security-Realitätscheck:
Verschlüsselung ersetzt kein echtes Secret-Management. Für produktive Systeme gehören Schlüssel in dedizierte Secret-Stores oder Key Vaults.
 

Logge dich ein, um hier zu kommentieren!