Einfache unsichere bidirektionale Datenverschleierung?


426

Ich suche nach einer sehr einfachen Verschleierungsfunktion (wie Ver- und Entschlüsseln, aber nicht unbedingt sicher) für einige Daten. Es ist nicht geschäftskritisch. Ich brauche etwas, um ehrliche Leute ehrlich zu halten, aber etwas, das etwas stärker ist als ROT13 oder Base64 .

Ich würde etwas bevorzugen, das bereits in .NET Framework 2.0 enthalten ist, damit ich mir keine Gedanken über externe Abhängigkeiten machen muss.

Ich möchte wirklich nicht mit öffentlichen / privaten Schlüsseln usw. herumspielen müssen. Ich weiß nicht viel über Verschlüsselung, aber ich weiß genug, um zu wissen, dass alles, was ich geschrieben habe, weniger als wertlos wäre ... Ich würde wahrscheinlich die Mathematik vermasseln und es trivial machen, zu knacken.


3
Hallo Markus - kein Problem. Ich fühlte mich schlecht, dass ich die Antwort von richdiet nicht akzeptieren musste, da ich tatsächlich seine Lösung verwendet habe und es gut funktioniert hat. Ich bin jedoch immer wieder hierher zurückgekommen, um die anderen Antworten zu lesen, und deine ist wirklich besser. Kein Grund, den Leuten zu sagen, dass sie etwas verwenden sollen, das zwar funktioniert, aber keine gute Möglichkeit ist, etwas zu tun, wenn eine bessere Antwort verfügbar ist.
Matt Dawdy

3
Sparen Sie sich Stunden und verwenden Sie HttpServerUtility.UrlTokenEn / Decode, um von den Byte-Arrays in eine URL-freundliche Zeichenfolge hin und her zu konvertieren.
Praesagus

32
+1, wenn Sie nicht versuchen, Ihr eigenes cleveres Design zu rollen. Sie wissen vielleicht nicht viel über Verschlüsselung, aber die Tatsache, dass Sie wissen, dass Sie damit den meisten Entwicklern, die ich getroffen habe, Lichtjahre voraus sind, die nicht viel über Verschlüsselung wissen, aber glauben, dass sie trotzdem ihre eigene Lösung erstellen können.
Dinah

6
Achtung: Viele der Antworten in dieser Frage sind nur nicht authentifizierte Verschlüsselung. Dies bedeutet, dass der Angreifer die Daten ändern kann, ohne dass die App dies bemerkt . Dies führt auch zu anderen schwerwiegenden Sicherheitslücken (z. B. Entschlüsselung ohne Schlüssel aufgrund von Padding Orakel). TL; DR: Verwenden Sie den Code nicht in den Antworten, wenn Sie damit nicht einverstanden sind oder nicht verstehen, was ich gerade gesagt habe.
usr

36
Keine einzige Antwort auf diese Frage beschreibt die sichere Verschlüsselung. Verwenden Sie die Antwort von jbtule unter Verschlüsseln und entschlüsseln Sie stattdessen eine Zeichenfolge .
CodesInChaos

Antworten:


471

Andere Antworten funktionieren hier einwandfrei, aber AES ist ein sicherer und aktueller Verschlüsselungsalgorithmus. Dies ist eine Klasse, die ich vor einigen Jahren erhalten habe, um eine AES-Verschlüsselung durchzuführen, die ich im Laufe der Zeit geändert habe, um sie für Webanwendungen benutzerfreundlicher zu gestalten (z. B. habe ich Verschlüsselungs- / Entschlüsselungsmethoden erstellt, die mit URL-freundlichen Zeichenfolgen arbeiten). Es hat auch die Methoden, die mit Byte-Arrays arbeiten.

HINWEIS: Sie sollten unterschiedliche Werte in den Arrays Key (32 Byte) und Vector (16 Byte) verwenden! Sie möchten nicht, dass jemand Ihre Schlüssel herausfindet, indem Sie einfach davon ausgehen, dass Sie diesen Code unverändert verwendet haben! Alles, was Sie tun müssen, ist, einige der Zahlen (muss <= 255 sein) in den Schlüssel- und Vektor-Arrays zu ändern (ich habe einen ungültigen Wert im Vektor-Array hinterlassen, um sicherzustellen, dass Sie dies tun ...). Sie können https://www.random.org/bytes/ verwenden , um auf einfache Weise einen neuen Satz zu generieren:

Die Verwendung ist einfach: Instanziieren Sie einfach die Klasse und rufen Sie dann (normalerweise) EncryptToString (Zeichenfolge StringToEncrypt) und DecryptString (Zeichenfolge StringToDecrypt) als Methoden auf. Es könnte nicht einfacher (oder sicherer) sein, wenn Sie diese Klasse eingerichtet haben.


using System;
using System.Data;
using System.Security.Cryptography;
using System.IO;


public class SimpleAES
{
    // Change these keys
    private byte[] Key = __Replace_Me__({ 123, 217, 19, 11, 24, 26, 85, 45, 114, 184, 27, 162, 37, 112, 222, 209, 241, 24, 175, 144, 173, 53, 196, 29, 24, 26, 17, 218, 131, 236, 53, 209 });

    // a hardcoded IV should not be used for production AES-CBC code
    // IVs should be unpredictable per ciphertext
    private byte[] Vector = __Replace_Me__({ 146, 64, 191, 111, 23, 3, 113, 119, 231, 121, 2521, 112, 79, 32, 114, 156 });


    private ICryptoTransform EncryptorTransform, DecryptorTransform;
    private System.Text.UTF8Encoding UTFEncoder;

    public SimpleAES()
    {
        //This is our encryption method
        RijndaelManaged rm = new RijndaelManaged();

        //Create an encryptor and a decryptor using our encryption method, key, and vector.
        EncryptorTransform = rm.CreateEncryptor(this.Key, this.Vector);
        DecryptorTransform = rm.CreateDecryptor(this.Key, this.Vector);

        //Used to translate bytes to text and vice versa
        UTFEncoder = new System.Text.UTF8Encoding();
    }

    /// -------------- Two Utility Methods (not used but may be useful) -----------
    /// Generates an encryption key.
    static public byte[] GenerateEncryptionKey()
    {
        //Generate a Key.
        RijndaelManaged rm = new RijndaelManaged();
        rm.GenerateKey();
        return rm.Key;
    }

    /// Generates a unique encryption vector
    static public byte[] GenerateEncryptionVector()
    {
        //Generate a Vector
        RijndaelManaged rm = new RijndaelManaged();
        rm.GenerateIV();
        return rm.IV;
    }


    /// ----------- The commonly used methods ------------------------------    
    /// Encrypt some text and return a string suitable for passing in a URL.
    public string EncryptToString(string TextValue)
    {
        return ByteArrToString(Encrypt(TextValue));
    }

    /// Encrypt some text and return an encrypted byte array.
    public byte[] Encrypt(string TextValue)
    {
        //Translates our text value into a byte array.
        Byte[] bytes = UTFEncoder.GetBytes(TextValue);

        //Used to stream the data in and out of the CryptoStream.
        MemoryStream memoryStream = new MemoryStream();

        /*
         * We will have to write the unencrypted bytes to the stream,
         * then read the encrypted result back from the stream.
         */
        #region Write the decrypted value to the encryption stream
        CryptoStream cs = new CryptoStream(memoryStream, EncryptorTransform, CryptoStreamMode.Write);
        cs.Write(bytes, 0, bytes.Length);
        cs.FlushFinalBlock();
        #endregion

        #region Read encrypted value back out of the stream
        memoryStream.Position = 0;
        byte[] encrypted = new byte[memoryStream.Length];
        memoryStream.Read(encrypted, 0, encrypted.Length);
        #endregion

        //Clean up.
        cs.Close();
        memoryStream.Close();

        return encrypted;
    }

    /// The other side: Decryption methods
    public string DecryptString(string EncryptedString)
    {
        return Decrypt(StrToByteArray(EncryptedString));
    }

    /// Decryption when working with byte arrays.    
    public string Decrypt(byte[] EncryptedValue)
    {
        #region Write the encrypted value to the decryption stream
        MemoryStream encryptedStream = new MemoryStream();
        CryptoStream decryptStream = new CryptoStream(encryptedStream, DecryptorTransform, CryptoStreamMode.Write);
        decryptStream.Write(EncryptedValue, 0, EncryptedValue.Length);
        decryptStream.FlushFinalBlock();
        #endregion

        #region Read the decrypted value from the stream.
        encryptedStream.Position = 0;
        Byte[] decryptedBytes = new Byte[encryptedStream.Length];
        encryptedStream.Read(decryptedBytes, 0, decryptedBytes.Length);
        encryptedStream.Close();
        #endregion
        return UTFEncoder.GetString(decryptedBytes);
    }

    /// Convert a string to a byte array.  NOTE: Normally we'd create a Byte Array from a string using an ASCII encoding (like so).
    //      System.Text.ASCIIEncoding encoding = new System.Text.ASCIIEncoding();
    //      return encoding.GetBytes(str);
    // However, this results in character values that cannot be passed in a URL.  So, instead, I just
    // lay out all of the byte values in a long string of numbers (three per - must pad numbers less than 100).
    public byte[] StrToByteArray(string str)
    {
        if (str.Length == 0)
            throw new Exception("Invalid string value in StrToByteArray");

        byte val;
        byte[] byteArr = new byte[str.Length / 3];
        int i = 0;
        int j = 0;
        do
        {
            val = byte.Parse(str.Substring(i, 3));
            byteArr[j++] = val;
            i += 3;
        }
        while (i < str.Length);
        return byteArr;
    }

    // Same comment as above.  Normally the conversion would use an ASCII encoding in the other direction:
    //      System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
    //      return enc.GetString(byteArr);    
    public string ByteArrToString(byte[] byteArr)
    {
        byte val;
        string tempStr = "";
        for (int i = 0; i <= byteArr.GetUpperBound(0); i++)
        {
            val = byteArr[i];
            if (val < (byte)10)
                tempStr += "00" + val.ToString();
            else if (val < (byte)100)
                tempStr += "0" + val.ToString();
            else
                tempStr += val.ToString();
        }
        return tempStr;
    }
}

53
@AndyMcKenna - Dies geschieht absichtlich, damit Sie die Werte in den Arrays ändern, wie Mark im zweiten Absatz bemerkt.
Pauk

42
Sie sollten die IV nicht so verwenden. Für zwei gegebene Nachrichten sollten sie nicht mit demselben Schlüssel und derselben IV verschlüsselt worden sein. Die IV sollte für jede Nachricht zufällig sein, dem Kryptostream vorangestellt und vor der Entschlüsselung ausgelesen werden. crypto.stackexchange.com/a/82/1934
jbtule

30
Die Verwendung einer zufälligen IV für jede Nachricht ist nicht exotisch oder neu, sondern nur wichtig und Teil des Entwurfs des Algorithmus. Die Verwendung einer vorhersehbaren IV für jede Nachricht ist ein häufiger Kryptofehler, der nicht fortbestehen muss.
jbtule

14
Beachten Sie auch, dass die Verwendung von CBC als Modus zur Folge hat, dass Sie wahrscheinlich anfällig für Padding-Orakelangriffe sind . Verwenden Sie authentifizierte Verschlüsselung und implementieren Sie Kryptografie nach Möglichkeit nicht selbst .
Stephen Touset

57
Sicherheitswarnung: Verwenden Sie diesen Code nicht Obwohl dies die akzeptierte Antwort ist, werden in den obigen Kommentaren schwerwiegende Sicherheitsprobleme erwähnt, die der Autor seit 8 Jahren ignoriert.
8.

176

Ich habe SimpleAES (oben) für meinen Gebrauch aufgeräumt. Problem mit verschlungenen Verschlüsselungs- / Entschlüsselungsmethoden behoben; getrennte Methoden zum Codieren von Bytepuffern, Zeichenfolgen und URL-freundlichen Zeichenfolgen; vorhandene Bibliotheken für die URL-Codierung verwendet.

Der Code ist klein, einfacher, schneller und die Ausgabe ist präziser. Zum Beispiel johnsmith@gmail.comerzeugt:

SimpleAES: "096114178117140150104121138042115022037019164188092040214235183167012211175176167001017163166152"
SimplerAES: "YHKydYyWaHmKKnMWJROkvFwo1uu3pwzTr7CnARGjppg%3d"

Code:

public class SimplerAES
{
    private static byte[] key = __Replace_Me__({ 123, 217, 19, 11, 24, 26, 85, 45, 114, 184, 27, 162, 37, 112, 222, 209, 241, 24, 175, 144, 173, 53, 196, 29, 24, 26, 17, 218, 131, 236, 53, 209 });

    // a hardcoded IV should not be used for production AES-CBC code
    // IVs should be unpredictable per ciphertext
    private static byte[] vector = __Replace_Me_({ 146, 64, 191, 111, 23, 3, 113, 119, 231, 121, 221, 112, 79, 32, 114, 156 });

    private ICryptoTransform encryptor, decryptor;
    private UTF8Encoding encoder;

    public SimplerAES()
    {
        RijndaelManaged rm = new RijndaelManaged();
        encryptor = rm.CreateEncryptor(key, vector);
        decryptor = rm.CreateDecryptor(key, vector);
        encoder = new UTF8Encoding();
    }

    public string Encrypt(string unencrypted)
    {
        return Convert.ToBase64String(Encrypt(encoder.GetBytes(unencrypted)));
    }

    public string Decrypt(string encrypted)
    {
        return encoder.GetString(Decrypt(Convert.FromBase64String(encrypted)));
    }

    public byte[] Encrypt(byte[] buffer)
    {
        return Transform(buffer, encryptor);
    }

    public byte[] Decrypt(byte[] buffer)
    {
        return Transform(buffer, decryptor);
    }

    protected byte[] Transform(byte[] buffer, ICryptoTransform transform)
    {
        MemoryStream stream = new MemoryStream();
        using (CryptoStream cs = new CryptoStream(stream, transform, CryptoStreamMode.Write))
        {
            cs.Write(buffer, 0, buffer.Length);
        }
        return stream.ToArray();
    }
}

2
Beim Decodieren musste ich Leerzeichen durch + ersetzen, damit es mit QueryString in Chrome funktioniert: (neues SimplerAES ()). Decrypt (Request.QueryString ["myParam"]. Replace ('', '+'));
Live-Liebe

20
Verwenden Sie niemals einen konstanten Initialisierungsvektor. Weitere Informationen dazu finden Sie unter: crypto.stackexchange.com/questions/66/… . Generieren Sie stattdessen für jede Verschlüsselung eine neue IV und hängen Sie sie an den Kryptotext an, viel besser und nicht zu schwer.
Tom Heard

2
Beachten Sie, dass die Ausgabe der EncryptToUrl-Methode in dieser Lösung (oder die Verwendung einer UrlEncoded Base 64-Zeichenfolge im Allgemeinen) unter IIS 7 nicht standardmäßig funktioniert, wenn sie als Teil eines URL-Pfads (keine Abfragezeichenfolge) verwendet wird, wie in eine ASP.NET MVC-Route aufgrund einer IIS 7-Sicherheitseinstellung. Weitere Informationen finden
Jon Schneider

5
@ TomHeard Wie würde man das mit dem obigen Code machen?
MKII

26
Sicherheitswarnung: Verwenden Sie diesen Code nicht Siehe Kommentar von @TomHeard
jbtule

36

Ja, fügen Sie die System.SecurityAssembly hinzu und importieren Sie den System.Security.CryptographyNamespace. Hier ist ein einfaches Beispiel für eine symmetrische (DES) Algorithmusverschlüsselung:

DESCryptoServiceProvider des = new DESCryptoServiceProvider();
des.GenerateKey();
byte[] key = des.Key; // save this!

ICryptoTransform encryptor = des.CreateEncryptor();
// encrypt
byte[] enc = encryptor.TransformFinalBlock(new byte[] { 1, 2, 3, 4 }, 0, 4);

ICryptoTransform decryptor = des.CreateDecryptor();

// decrypt
byte[] originalAgain = decryptor.TransformFinalBlock(enc, 0, enc.Length);
Debug.Assert(originalAgain[0] == 1);

5
Dies ist eine schöne, kompakte Zwei-Wege-Verschlüsselung. Die einzige Einschränkung ist, dass DES nicht mehr als Sicherheit auf dem neuesten Stand der Technik gilt. Dieser Titel geht jetzt an den AES-Algorithmus, den ich unten diskutiere.
Mark Brittingham

@richdiet. Es tut mir leid, dass ich Ihre Antwort nicht akzeptiert habe. Die andere Antwort mit 37+ Stimmen, weil es aktueller ist. Vielen Dank für Ihre Antwort, da es immer noch eine gute ist.
Matt Dawdy

14
@ MarkBrittingham: Jede Blockverschlüsselung ohne Blockverkettungsfunktion, Initialisierungsvektor und ordnungsgemäße Auffüllung ist unsicher. Die Verwendung von DES ist das am wenigsten wichtige Problem bei diesem Schema.
Hubert Kario

2
Wo wird der Schlüssel verwendet?
Alex

22
Sicherheitswarnung: Verwenden Sie diesen Code nicht Siehe Kommentar von @HubertKario
jbtule

28

Ich dachte nur, ich würde hinzufügen, dass ich Muds SimplerAES verbessert habe, indem ich eine zufällige IV hinzugefügt habe, die innerhalb der verschlüsselten Zeichenfolge zurückgegeben wird. Dies verbessert die Verschlüsselung, da die Verschlüsselung derselben Zeichenfolge jedes Mal zu einer anderen Ausgabe führt.

public class StringEncryption
{
    private readonly Random random;
    private readonly byte[] key;
    private readonly RijndaelManaged rm;
    private readonly UTF8Encoding encoder;

    public StringEncryption()
    {
        this.random = new Random();
        this.rm = new RijndaelManaged();
        this.encoder = new UTF8Encoding();
        this.key = Convert.FromBase64String("Your+Secret+Static+Encryption+Key+Goes+Here=");
    }

    public string Encrypt(string unencrypted)
    {
        var vector = new byte[16];
        this.random.NextBytes(vector);
        var cryptogram = vector.Concat(this.Encrypt(this.encoder.GetBytes(unencrypted), vector));
        return Convert.ToBase64String(cryptogram.ToArray());
    }

    public string Decrypt(string encrypted)
    {
        var cryptogram = Convert.FromBase64String(encrypted);
        if (cryptogram.Length < 17)
        {
            throw new ArgumentException("Not a valid encrypted string", "encrypted");
        }

        var vector = cryptogram.Take(16).ToArray();
        var buffer = cryptogram.Skip(16).ToArray();
        return this.encoder.GetString(this.Decrypt(buffer, vector));
    }

    private byte[] Encrypt(byte[] buffer, byte[] vector)
    {
        var encryptor = this.rm.CreateEncryptor(this.key, vector);
        return this.Transform(buffer, encryptor);
    }

    private byte[] Decrypt(byte[] buffer, byte[] vector)
    {
        var decryptor = this.rm.CreateDecryptor(this.key, vector);
        return this.Transform(buffer, decryptor);
    }

    private byte[] Transform(byte[] buffer, ICryptoTransform transform)
    {
        var stream = new MemoryStream();
        using (var cs = new CryptoStream(stream, transform, CryptoStreamMode.Write))
        {
            cs.Write(buffer, 0, buffer.Length);
        }

        return stream.ToArray();
    }
}

Und Bonus-Unit-Test

[Test]
public void EncryptDecrypt()
{
    // Arrange
    var subject = new StringEncryption();
    var originalString = "Testing123!£$";

    // Act
    var encryptedString1 = subject.Encrypt(originalString);
    var encryptedString2 = subject.Encrypt(originalString);
    var decryptedString1 = subject.Decrypt(encryptedString1);
    var decryptedString2 = subject.Decrypt(encryptedString2);

    // Assert
    Assert.AreEqual(originalString, decryptedString1, "Decrypted string should match original string");
    Assert.AreEqual(originalString, decryptedString2, "Decrypted string should match original string");
    Assert.AreNotEqual(originalString, encryptedString1, "Encrypted string should not match original string");
    Assert.AreNotEqual(encryptedString1, encryptedString2, "String should never be encrypted the same twice");
}

11
1) Nicht System.Randomals RNG verwenden. 2) Dies ist völlig gegen ausgewählte Chiffretext-Angriffe (insbesondere Padding-Orakel)
gebrochen

21
Sicherheitswarnung: Verwenden Sie diesen Code nicht, siehe obigen Kommentar von @CodesInChaos
jbtule

@jbtule Bitte führen Sie nicht jede Person in die Irre, die keine Komplikationen nur verschlüsseln möchte und auch nicht vorsichtig mit dem Angriff ist. - Bitte bestellen Sie nicht, wenn Sie Vorschläge machen möchten.
Virbhadrasinh

@Virbhadrasinh gibt es keine Fehlleitung von meiner Seite, in der Tat ist es genau das Gegenteil. Wenn Sie AES verwenden möchten, ist es ziemlich wichtig, es richtig zu verwenden. Wenn Sie es falsch verwenden und sagen, dass es in Ordnung ist, dass ich es nicht für etwas Wichtiges verwende, ist dies falsch.
Jbtule

1
@Corey Schreit nicht und hat die Best Practice für den Umgang mit Sicherheitsproblemen bei Stapelüberlaufantworten befolgt. Wenn Sie einen Link möchten, wurde dieser in den Fragenkommentaren veröffentlicht. Aber ich werde es auch hier für Sie setzen stackoverflow.com/a/10366194/637783
jbtule

12

Eine Variante von Marks (ausgezeichnete) Antwort

  • Fügen Sie "using" s hinzu
  • Machen Sie die Klasse IDisposable
  • Entfernen Sie den URL-Codierungscode, um das Beispiel zu vereinfachen.
  • Fügen Sie eine einfache Testvorrichtung hinzu, um die Verwendung zu demonstrieren

Hoffe das hilft

[TestFixture]
public class RijndaelHelperTests
{
    [Test]
    public void UseCase()
    {
        //These two values should not be hard coded in your code.
        byte[] key = {251, 9, 67, 117, 237, 158, 138, 150, 255, 97, 103, 128, 183, 65, 76, 161, 7, 79, 244, 225, 146, 180, 51, 123, 118, 167, 45, 10, 184, 181, 202, 190};
        byte[] vector = {214, 11, 221, 108, 210, 71, 14, 15, 151, 57, 241, 174, 177, 142, 115, 137};

        using (var rijndaelHelper = new RijndaelHelper(key, vector))
        {
            var encrypt = rijndaelHelper.Encrypt("StringToEncrypt");
            var decrypt = rijndaelHelper.Decrypt(encrypt);
            Assert.AreEqual("StringToEncrypt", decrypt);
        }
    }
}

public class RijndaelHelper : IDisposable
{
    Rijndael rijndael;
    UTF8Encoding encoding;

    public RijndaelHelper(byte[] key, byte[] vector)
    {
        encoding = new UTF8Encoding();
        rijndael = Rijndael.Create();
        rijndael.Key = key;
        rijndael.IV = vector;
    }

    public byte[] Encrypt(string valueToEncrypt)
    {
        var bytes = encoding.GetBytes(valueToEncrypt);
        using (var encryptor = rijndael.CreateEncryptor())
        using (var stream = new MemoryStream())
        using (var crypto = new CryptoStream(stream, encryptor, CryptoStreamMode.Write))
        {
            crypto.Write(bytes, 0, bytes.Length);
            crypto.FlushFinalBlock();
            stream.Position = 0;
            var encrypted = new byte[stream.Length];
            stream.Read(encrypted, 0, encrypted.Length);
            return encrypted;
        }
    }

    public string Decrypt(byte[] encryptedValue)
    {
        using (var decryptor = rijndael.CreateDecryptor())
        using (var stream = new MemoryStream())
        using (var crypto = new CryptoStream(stream, decryptor, CryptoStreamMode.Write))
        {
            crypto.Write(encryptedValue, 0, encryptedValue.Length);
            crypto.FlushFinalBlock();
            stream.Position = 0;
            var decryptedBytes = new Byte[stream.Length];
            stream.Read(decryptedBytes, 0, decryptedBytes.Length);
            return encoding.GetString(decryptedBytes);
        }
    }

    public void Dispose()
    {
        if (rijndael != null)
        {
            rijndael.Dispose();
        }
    }
}

Gute Antwort. Eine Sache in der Dispose-Methode müssen Sie rijndael in IDisposable umwandeln, oder Sie erhalten einen Fehler der Schutzstufe, wenn Sie Dispose
John ClearZ

8
Verwenden Sie niemals einen konstanten Initialisierungsvektor. Weitere Informationen dazu finden Sie unter: crypto.stackexchange.com/questions/66/…. Generieren Sie stattdessen für jede Verschlüsselung eine neue IV und hängen Sie sie an den Kryptotext an, viel besser und nicht zu schwer.
Tom Heard

5
@Chalky Beim Verschlüsseln verwenden Sie die Rijndael-Klasse, um eine zufällige IV für Sie zu generieren ( msdn.microsoft.com/en-us/library/… ), verschlüsseln und dann die IV mithilfe der IV-Eigenschaft aus der Rijndael-Instanz abrufen . Sie stellen es dann Ihrem Kryptotext voran (oder hängen an, funktioniert entweder, solange Ihre Entschlüsselung es von derselben Seite erfasst). Beim Entschlüsseln ziehen Sie dann die IV aus den empfangenen Daten (die Größe der IV-Eigenschaft entspricht der BlockSize-Eigenschaft geteilt durch 8) und übergeben sie vor dem Entschlüsseln an Ihre Entschlüsselungsinstanz.
Tom Heard

2
@Chalky Beachten Sie, dass die IV nicht geheim sein muss, sondern nur für jede gesendete Nachricht eindeutig sein muss.
Tom Heard

20
Sicherheitswarnung: Verwenden Sie diesen Code nicht Siehe oben Kommentare von @TomHeard
jbtule

8

[BEARBEITEN] Jahre später bin ich zurückgekommen, um zu sagen: Tu das nicht! Siehe Was stimmt nicht mit der XOR-Verschlüsselung? für Details.

Eine sehr einfache, einfache bidirektionale Verschlüsselung ist die XOR-Verschlüsselung.

  1. Überlegen Sie sich ein Passwort. Lass es uns sein mypass.
  2. Konvertieren Sie das Passwort in eine Binärdatei (gemäß ASCII). Das Passwort lautet 01101101 01111001 01110000 01100001 01110011 01110011.
  3. Nehmen Sie die Nachricht, die Sie codieren möchten. Konvertieren Sie das auch in binär.
  4. Schauen Sie sich die Länge der Nachricht an. Wenn die Nachrichtenlänge 400 Byte beträgt, wandeln Sie das Kennwort in eine 400-Byte-Zeichenfolge um, indem Sie es immer wieder wiederholen. Es würde 01101101 01111001 01110000 01100001 01110011 01110011 01101101 01111001 01110000 01100001 01110011 01110011 01101101 01111001 01110000 01100001 01110011 01110011 ... (odermypassmypassmypass... )
  5. XOR die Nachricht mit dem langen Passwort.
  6. Senden Sie das Ergebnis.
  7. Ein anderes Mal XOR die verschlüsselte Nachricht mit dem gleichen Passwort (mypassmypassmypass... ).
  8. Da ist deine Nachricht!

10
@ Ryan Nicht jede Situation erfordert kryptografisch sichere Hashes oder Rijndael-Chiffren. "Einfache 2-Wege-Verschlüsselung" könnte tatsächlich einfach bedeuten , was auf xor oder sogar ROT13 hindeutet.

1
@ Ryan: AES mit statischem Verschlüsselungsschlüssel, ohne Initialisierungsvektor und ohne Blockverkettungsfunktion ist nur ein ausgefallener Name für die XOR-Verschlüsselung, Sie verwenden nur wirklich ausgefallene KDF ...
Hubert Kario

17
Sicherheitswarnung: Verwenden Sie diesen Code nicht. Die XOR-Verschlüsselung mit einem sich wiederholenden Schlüssel ist trivial geknackt.
Jbtule

7

Ich habe das, was ich am besten fand, aus mehreren Antworten und Kommentaren kombiniert.

  • Zufälliger Initialisierungsvektor vor Kryptotext (@jbtule)
  • Verwenden Sie TransformFinalBlock () anstelle von MemoryStream (@RenniePet).
  • Keine vorgefüllten Schlüssel, um zu vermeiden, dass jemand eine Katastrophe kopiert und einfügt
  • Ordnungsgemäße Entsorgung und Verwendung von Mustern

Code:

/// <summary>
/// Simple encryption/decryption using a random initialization vector
/// and prepending it to the crypto text.
/// </summary>
/// <remarks>Based on multiple answers in http://stackoverflow.com/questions/165808/simple-two-way-encryption-for-c-sharp </remarks>
public class SimpleAes : IDisposable
{
    /// <summary>
    ///     Initialization vector length in bytes.
    /// </summary>
    private const int IvBytes = 16;

    /// <summary>
    ///     Must be exactly 16, 24 or 32 bytes long.
    /// </summary>
    private static readonly byte[] Key = Convert.FromBase64String("FILL ME WITH 24 (2 pad chars), 32 OR 44 (1 pad char) RANDOM CHARS"); // Base64 has a blowup of four-thirds (33%)

    private readonly UTF8Encoding _encoder;
    private readonly ICryptoTransform _encryptor;
    private readonly RijndaelManaged _rijndael;

    public SimpleAes()
    {
        _rijndael = new RijndaelManaged {Key = Key};
        _rijndael.GenerateIV();
        _encryptor = _rijndael.CreateEncryptor();
        _encoder = new UTF8Encoding();
    }

    public string Decrypt(string encrypted)
    {
        return _encoder.GetString(Decrypt(Convert.FromBase64String(encrypted)));
    }

    public void Dispose()
    {
        _rijndael.Dispose();
        _encryptor.Dispose();
    }

    public string Encrypt(string unencrypted)
    {
        return Convert.ToBase64String(Encrypt(_encoder.GetBytes(unencrypted)));
    }

    private byte[] Decrypt(byte[] buffer)
    {
        // IV is prepended to cryptotext
        byte[] iv = buffer.Take(IvBytes).ToArray();
        using (ICryptoTransform decryptor = _rijndael.CreateDecryptor(_rijndael.Key, iv))
        {
            return decryptor.TransformFinalBlock(buffer, IvBytes, buffer.Length - IvBytes);
        }
    }

    private byte[] Encrypt(byte[] buffer)
    {
        // Prepend cryptotext with IV
        byte [] inputBuffer = _encryptor.TransformFinalBlock(buffer, 0, buffer.Length); 
        return _rijndael.IV.Concat(inputBuffer).ToArray();
    }
}

Update 18.07.2015: Fehler in der privaten Encrypt () -Methode durch Kommentare von @bpsilver und @Evereq behoben. IV wurde versehentlich verschlüsselt und wird nun wie von Decrypt () erwartet im Klartext vorangestellt.


Sie sollten den gesamten inputBuffer mit vorangestelltem IV verschlüsseln, da sonst die ersten 16 Zeichen der zu verschlüsselnden Zeichenfolge verloren gehen. Ihr Code sollte also lauten:return _encryptor.TransformFinalBlock(inputBuffer, 0, inputBuffer.Length);
bpsilver

2
In diesem Fall:byte [] inputBuffer = _encryptor.TransformFinalBlock(buffer, 0, buffer.Length); return _rijndael.IV.Concat(inputBuffer).ToArray();
Bpsilver

1
Das würde das Gleiche tun wie die aktuelle Implementierung, nicht wahr?
Angularsen

1
"FÜLL MICH MIT 16, 24 ODER 32 CHARS" Nun, nein, nicht vor der Decodierung der Basis 64. Und ein Schlüssel sollte zufällig sein. Wirklich zufällig.
Maarten Bodewes

1
Ich stelle fest, dass @bpsilver richtig ist und der bereitgestellte Code ohne sein Update nicht funktioniert: Die Verschlüsselungsmethode gibt verschlüsselte Daten ohne IV zurück (sie fügt zuerst IV zum Eingabepuffer hinzu, verschlüsselt und gibt dann Daten ohne IV zurück). Wenn möglich, aktualisieren Sie einfach die Antwort mit seinem Code. (Hinweis: Ich teste nur Methoden mit Byte [] -Parametern, keine Zeichenfolgen). Vielen Dank!
Evereq

6

Wenn Sie nur eine einfache Verschlüsselung wünschen (dh ein entschlossener Cracker kann brechen, aber die meisten Gelegenheitsbenutzer ausschließen), wählen Sie einfach zwei Passphrasen gleicher Länge aus, z. B.:

deoxyribonucleicacid
while (x>0) { x-- };

und xoder Ihre Daten mit beiden (Schleifen der Passphrasen, falls erforderlich) (a) . Zum Beispiel:

1111-2222-3333-4444-5555-6666-7777
deoxyribonucleicaciddeoxyribonucle
while (x>0) { x-- };while (x>0) { 

Jemand, der Ihre Binärdatei durchsucht, glaubt möglicherweise, dass der DNA-String ein Schlüssel ist, aber es ist unwahrscheinlich, dass der C-Code etwas anderes als nicht initialisierter Speicher ist, der mit Ihrer Binärdatei gespeichert wurde.


(a) Beachten Sie, dass dies eine sehr einfache Verschlüsselung ist und nach einigen Definitionen überhaupt nicht als Verschlüsselung angesehen werden kann (da die Absicht der Verschlüsselung darin besteht, dies zu verhindern unbefugten Zugriff anstatt ihn nur zu erschweren). Obwohl natürlich selbst die stärkste Verschlüsselung unsicher ist, wenn jemand mit einem Stahlrohr über den Schlüsselhaltern steht.

Wie im ersten Satz erwähnt, ist dies ein Mittel, um es dem zufälligen Angreifer so schwer zu machen, dass er weiterziehen wird. Es ist ähnlich wie bei der Verhinderung von Einbrüchen in Ihrem Haus - Sie müssen es nicht uneinnehmbar machen, Sie müssen es nur weniger schwanger machen als das Haus nebenan :-)


3
Interessante Idee. Ich bin mir nicht sicher, ob ich den Quellcode in einer Binärdatei "glauben" würde - aber wie wäre es, wenn Sie die Idee anpassen, eine Fehlermeldung als Passphrase zu verwenden?
Jon Skeet

1
Ich bevorzuge die Verwendung eines MD5-Hashs einer Klartextzeichenfolge, die bereits in der Anwendung vorhanden ist (Fehlermeldung oder so).
Treb

2
Warum müssen sie gleich lang sein? Es scheint tatsächlich besser, wenn sie unterschiedlich lang sind. Auf diese Weise beträgt die Länge Ihres effektiven XOR-Operanden LCM (Länge1, Länge2) anstelle von nur Länge1 (= Länge2). Was natürlich zu Länge1 * Länge2 wird, wenn die Längen relativ prim sind.
Fantius

15
Sicherheitswarnung: Verwenden Sie diesen Code nicht. Der Wiederholungsschlüssel XOR kann leicht geknackt werden, wenn nur einige allgemeine Kenntnisse über die zu verschlüsselnden Daten vorliegen.
jbtule

3
@jbtule, wenn Sie die Frage lesen würden, würden Sie feststellen, dass keine sicherere Verschlüsselung erforderlich ist. Insbesondere der Hinweis auf "einfache Verschlüsselung", "nicht geschäftskritisch" und nur "ehrliche Menschen ehrlich halten". Sie sollten auch meinen ersten Absatz lesen, in dem ausdrücklich darauf hingewiesen wird, dass er entschlossene Angreifer nicht ausschließt.
Paxdiablo

5

Die Verschlüsselung ist einfach: Wie andere bereits betont haben, gibt es im System.Security.Cryptography-Namespace Klassen, die die gesamte Arbeit für Sie erledigen. Verwenden Sie sie anstelle einer selbst entwickelten Lösung.

Die Entschlüsselung ist aber auch einfach. Das Problem, das Sie haben, ist nicht der Verschlüsselungsalgorithmus, sondern der Schutz des Zugriffs auf den zur Entschlüsselung verwendeten Schlüssel.

Ich würde eine der folgenden Lösungen verwenden:

  • DPAPI unter Verwendung der ProtectedData-Klasse mit CurrentUser-Bereich. Dies ist einfach, da Sie sich keine Sorgen um einen Schlüssel machen müssen. Daten können nur von demselben Benutzer entschlüsselt werden, daher ist es nicht gut, Daten zwischen Benutzern oder Computern auszutauschen.

  • DPAPI unter Verwendung der ProtectedData-Klasse mit LocalMachine-Bereich. Gut zum Beispiel zum Schutz von Konfigurationsdaten auf einem einzelnen sicheren Server. Aber jeder, der sich am Computer anmelden kann, kann ihn verschlüsseln, was nur dann gut ist, wenn der Server sicher ist.

  • Beliebiger symmetrischer Algorithmus. Normalerweise verwende ich die statische SymmetricAlgorithm.Create () -Methode, wenn es mir egal ist, welcher Algorithmus verwendet wird (tatsächlich ist es standardmäßig Rijndael). In diesem Fall müssen Sie Ihren Schlüssel irgendwie schützen. Zum Beispiel können Sie es auf irgendeine Weise verschleiern und in Ihrem Code verstecken. Beachten Sie jedoch, dass jeder, der klug genug ist, Ihren Code zu dekompilieren, wahrscheinlich den Schlüssel finden kann.


5

Ich wollte meine Lösung veröffentlichen, da keine der oben genannten Lösungen so einfach ist wie meine. Lass mich wissen was du denkst:

 // This will return an encrypted string based on the unencrypted parameter
 public static string Encrypt(this string DecryptedValue)
 {
      HttpServerUtility.UrlTokenEncode(MachineKey.Protect(Encoding.UTF8.GetBytes(DecryptedValue.Trim())));
 }

 // This will return an unencrypted string based on the parameter
 public static string Decrypt(this string EncryptedValue)
 {
      Encoding.UTF8.GetString(MachineKey.Unprotect(HttpServerUtility.UrlTokenDecode(EncryptedValue)));
 }

Optional

Dies setzt voraus, dass der MachineKey des Servers, der zum Verschlüsseln des Werts verwendet wird, mit demjenigen identisch ist, der zum Entschlüsseln des Werts verwendet wird. Falls gewünscht, können Sie in der Web.config einen statischen MachineKey angeben, damit Ihre Anwendung Daten unabhängig davon entschlüsseln / verschlüsseln kann, unabhängig davon, wo sie ausgeführt werden (z. B. Entwicklung vs. Produktionsserver). Sie können einen statischen Maschinenschlüssel gemäß diesen Anweisungen generieren .


Beachten Sie, dass dieser Ansatz nur für die ASP.NET-App verwendet werden kann.
Feru

2

Der Namespace System.Security.Cryptographyenthält das TripleDESCryptoServiceProviderundRijndaelManaged Klassen

Vergessen Sie nicht, einen Verweis auf die System.SecurityBaugruppe hinzuzufügen .


8
Nicht dass ich abgelehnt hätte, aber warum sollte das Alter einer Frage bei der Abstimmung eine Rolle spielen?
user247702

2

Verwenden von TripleDESCryptoServiceProvider in System.Security.Cryptography :

public static class CryptoHelper
{
    private const string Key = "MyHashString";
    private static TripleDESCryptoServiceProvider GetCryproProvider()
    {
        var md5 = new MD5CryptoServiceProvider();
        var key = md5.ComputeHash(Encoding.UTF8.GetBytes(Key));
        return new TripleDESCryptoServiceProvider() { Key = key, Mode = CipherMode.ECB, Padding = PaddingMode.PKCS7 };
    }

    public static string Encrypt(string plainString)
    {
        var data = Encoding.UTF8.GetBytes(plainString);
        var tripleDes = GetCryproProvider();
        var transform = tripleDes.CreateEncryptor();
        var resultsByteArray = transform.TransformFinalBlock(data, 0, data.Length);
        return Convert.ToBase64String(resultsByteArray);
    }

    public static string Decrypt(string encryptedString)
    {
        var data = Convert.FromBase64String(encryptedString);
        var tripleDes = GetCryproProvider();
        var transform = tripleDes.CreateDecryptor();
        var resultsByteArray = transform.TransformFinalBlock(data, 0, data.Length);
        return Encoding.UTF8.GetString(resultsByteArray);
    }
}

1

Ich änderte dies :

public string ByteArrToString(byte[] byteArr)
{
    byte val;
    string tempStr = "";
    for (int i = 0; i <= byteArr.GetUpperBound(0); i++)
    {
        val = byteArr[i];
        if (val < (byte)10)
            tempStr += "00" + val.ToString();
        else if (val < (byte)100)
            tempStr += "0" + val.ToString();
        else
            tempStr += val.ToString();
    }
    return tempStr;
}

dazu:

    public string ByteArrToString(byte[] byteArr)
    {
        string temp = "";
        foreach (byte b in byteArr)
            temp += b.ToString().PadLeft(3, '0');
        return temp;
    }

1

In diesem Beispiel wird anhand der integrierten .Net Cryptography-Bibliothek die Verwendung des Advanced Encryption Standard (AES) gezeigt.

using System;
using System.IO;
using System.Security.Cryptography;

namespace Aes_Example
{
    class AesExample
    {
        public static void Main()
        {
            try
            {

                string original = "Here is some data to encrypt!";

                // Create a new instance of the Aes
                // class.  This generates a new key and initialization 
                // vector (IV).
                using (Aes myAes = Aes.Create())
                {

                    // Encrypt the string to an array of bytes.
                    byte[] encrypted = EncryptStringToBytes_Aes(original, myAes.Key, myAes.IV);

                    // Decrypt the bytes to a string.
                    string roundtrip = DecryptStringFromBytes_Aes(encrypted, myAes.Key, myAes.IV);

                    //Display the original data and the decrypted data.
                    Console.WriteLine("Original:   {0}", original);
                    Console.WriteLine("Round Trip: {0}", roundtrip);
                }

            }
            catch (Exception e)
            {
                Console.WriteLine("Error: {0}", e.Message);
            }
        }
        static byte[] EncryptStringToBytes_Aes(string plainText, byte[] Key,byte[] IV)
        {
            // Check arguments.
            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");
            byte[] encrypted;
            // Create an Aes object
            // with the specified key and IV.
            using (Aes aesAlg = Aes.Create())
            {
                aesAlg.Key = Key;
                aesAlg.IV = IV;

                // Create a decrytor to perform the stream transform.
                ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);

                // Create the streams used for encryption.
                using (MemoryStream msEncrypt = new MemoryStream())
                {
                    using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                    {
                        using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                        {

                            //Write all data to the stream.
                            swEncrypt.Write(plainText);
                        }
                        encrypted = msEncrypt.ToArray();
                    }
                }
            }


            // Return the encrypted bytes from the memory stream.
            return encrypted;

        }

        static string DecryptStringFromBytes_Aes(byte[] cipherText, byte[] Key, byte[] IV)
        {
            // Check arguments.
            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");

            // Declare the string used to hold
            // the decrypted text.
            string plaintext = null;

            // Create an Aes object
            // with the specified key and IV.
            using (Aes aesAlg = Aes.Create())
            {
                aesAlg.Key = Key;
                aesAlg.IV = IV;

                // Create a decrytor to perform the stream transform.
                ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);

                // Create the streams used for decryption.
                using (MemoryStream msDecrypt = new MemoryStream(cipherText))
                {
                    using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                    {
                        using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                        {

                            // Read the decrypted bytes from the decrypting stream
                            // and place them in a string.
                            plaintext = srDecrypt.ReadToEnd();
                        }
                    }
                }

            }

            return plaintext;

        }
    }
}

0

Ich weiß, dass Sie gesagt haben, dass es Ihnen egal ist, wie sicher es ist, aber wenn Sie sich für DES entschieden haben, können Sie auch AES wählen, es ist die aktuellere Verschlüsselungsmethode.


0

Ich habe die akzeptierte Antwort von Mark Brittingham verwendet und sie hat mir sehr geholfen. Vor kurzem musste ich verschlüsselten Text an eine andere Organisation senden, und dort traten einige Probleme auf. Das OP benötigt diese Optionen nicht, aber da dies eine beliebte Frage ist, veröffentliche ich meine Änderung ( Encryptund Decryptdie von hier ausgeliehenen Funktionen ):

  1. Unterschiedliche IV für jede Nachricht - Verkettet IV-Bytes mit den Verschlüsselungsbytes, bevor das Hex erhalten wird. Dies ist natürlich eine Konvention, die den Parteien, die den Chiffretext erhalten, mitgeteilt werden muss.
  2. Ermöglicht zwei Konstruktoren - einen für Standardwerte RijndaelManagedund einen, in dem Eigenschaftswerte angegeben werden können (basierend auf der gegenseitigen Vereinbarung zwischen Verschlüsselungs- und Entschlüsselungsparteien).

Hier ist die Klasse (Testbeispiel am Ende):

/// <summary>
/// Based on https://msdn.microsoft.com/en-us/library/system.security.cryptography.rijndaelmanaged(v=vs.110).aspx
/// Uses UTF8 Encoding
///  http://security.stackexchange.com/a/90850
/// </summary>
public class AnotherAES : IDisposable
{
    private RijndaelManaged rijn;

    /// <summary>
    /// Initialize algo with key, block size, key size, padding mode and cipher mode to be known.
    /// </summary>
    /// <param name="key">ASCII key to be used for encryption or decryption</param>
    /// <param name="blockSize">block size to use for AES algorithm. 128, 192 or 256 bits</param>
    /// <param name="keySize">key length to use for AES algorithm. 128, 192, or 256 bits</param>
    /// <param name="paddingMode"></param>
    /// <param name="cipherMode"></param>
    public AnotherAES(string key, int blockSize, int keySize, PaddingMode paddingMode, CipherMode cipherMode)
    {
        rijn = new RijndaelManaged();
        rijn.Key = Encoding.UTF8.GetBytes(key);
        rijn.BlockSize = blockSize;
        rijn.KeySize = keySize;
        rijn.Padding = paddingMode;
        rijn.Mode = cipherMode;
    }

    /// <summary>
    /// Initialize algo just with key
    /// Defaults for RijndaelManaged class: 
    /// Block Size: 256 bits (32 bytes)
    /// Key Size: 128 bits (16 bytes)
    /// Padding Mode: PKCS7
    /// Cipher Mode: CBC
    /// </summary>
    /// <param name="key"></param>
    public AnotherAES(string key)
    {
        rijn = new RijndaelManaged();
        byte[] keyArray = Encoding.UTF8.GetBytes(key);
        rijn.Key = keyArray;
    }

    /// <summary>
    /// Based on https://msdn.microsoft.com/en-us/library/system.security.cryptography.rijndaelmanaged(v=vs.110).aspx
    /// Encrypt a string using RijndaelManaged encryptor.
    /// </summary>
    /// <param name="plainText">string to be encrypted</param>
    /// <param name="IV">initialization vector to be used by crypto algorithm</param>
    /// <returns></returns>
    public byte[] Encrypt(string plainText, byte[] IV)
    {
        if (rijn == null)
            throw new ArgumentNullException("Provider not initialized");

        // Check arguments.
        if (plainText == null || plainText.Length <= 0)
            throw new ArgumentNullException("plainText cannot be null or empty");
        if (IV == null || IV.Length <= 0)
            throw new ArgumentNullException("IV cannot be null or empty");
        byte[] encrypted;

        // Create a decrytor to perform the stream transform.
        using (ICryptoTransform encryptor = rijn.CreateEncryptor(rijn.Key, IV))
        {
            // Create the streams used for encryption.
            using (MemoryStream msEncrypt = new MemoryStream())
            {
                using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
                {
                    using (StreamWriter swEncrypt = new StreamWriter(csEncrypt))
                    {
                        //Write all data to the stream.
                        swEncrypt.Write(plainText);
                    }
                    encrypted = msEncrypt.ToArray();
                }
            }
        }
        // Return the encrypted bytes from the memory stream.
        return encrypted;
    }//end EncryptStringToBytes

    /// <summary>
    /// Based on https://msdn.microsoft.com/en-us/library/system.security.cryptography.rijndaelmanaged(v=vs.110).aspx
    /// </summary>
    /// <param name="cipherText">bytes to be decrypted back to plaintext</param>
    /// <param name="IV">initialization vector used to encrypt the bytes</param>
    /// <returns></returns>
    public string Decrypt(byte[] cipherText, byte[] IV)
    {
        if (rijn == null)
            throw new ArgumentNullException("Provider not initialized");

        // Check arguments.
        if (cipherText == null || cipherText.Length <= 0)
            throw new ArgumentNullException("cipherText cannot be null or empty");
        if (IV == null || IV.Length <= 0)
            throw new ArgumentNullException("IV cannot be null or empty");

        // Declare the string used to hold the decrypted text.
        string plaintext = null;

        // Create a decrytor to perform the stream transform.
        using (ICryptoTransform decryptor = rijn.CreateDecryptor(rijn.Key, IV))
        {
            // Create the streams used for decryption.
            using (MemoryStream msDecrypt = new MemoryStream(cipherText))
            {
                using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
                {
                    using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                    {
                        // Read the decrypted bytes from the decrypting stream and place them in a string.
                        plaintext = srDecrypt.ReadToEnd();
                    }
                }
            }
        }

        return plaintext;
    }//end DecryptStringFromBytes

    /// <summary>
    /// Generates a unique encryption vector using RijndaelManaged.GenerateIV() method
    /// </summary>
    /// <returns></returns>
    public byte[] GenerateEncryptionVector()
    {
        if (rijn == null)
            throw new ArgumentNullException("Provider not initialized");

        //Generate a Vector
        rijn.GenerateIV();
        return rijn.IV;
    }//end GenerateEncryptionVector


    /// <summary>
    /// Based on https://stackoverflow.com/a/1344255
    /// Generate a unique string given number of bytes required.
    /// This string can be used as IV. IV byte size should be equal to cipher-block byte size. 
    /// Allows seeing IV in plaintext so it can be passed along a url or some message.
    /// </summary>
    /// <param name="numBytes"></param>
    /// <returns></returns>
    public static string GetUniqueString(int numBytes)
    {
        char[] chars = new char[62];
        chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890".ToCharArray();
        byte[] data = new byte[1];
        using (RNGCryptoServiceProvider crypto = new RNGCryptoServiceProvider())
        {
            data = new byte[numBytes];
            crypto.GetBytes(data);
        }
        StringBuilder result = new StringBuilder(numBytes);
        foreach (byte b in data)
        {
            result.Append(chars[b % (chars.Length)]);
        }
        return result.ToString();
    }//end GetUniqueKey()

    /// <summary>
    /// Converts a string to byte array. Useful when converting back hex string which was originally formed from bytes.
    /// </summary>
    /// <param name="hex"></param>
    /// <returns></returns>
    public static byte[] StringToByteArray(String hex)
    {
        int NumberChars = hex.Length;
        byte[] bytes = new byte[NumberChars / 2];
        for (int i = 0; i < NumberChars; i += 2)
            bytes[i / 2] = Convert.ToByte(hex.Substring(i, 2), 16);
        return bytes;
    }//end StringToByteArray

    /// <summary>
    /// Dispose RijndaelManaged object initialized in the constructor
    /// </summary>
    public void Dispose()
    {
        if (rijn != null)
            rijn.Dispose();
    }//end Dispose()
}//end class

und..

Hier ist das Testbeispiel:

class Program
{
    string key;
    static void Main(string[] args)
    {
        Program p = new Program();

        //get 16 byte key (just demo - typically you will have a predetermined key)
        p.key = AnotherAES.GetUniqueString(16);

        string plainText = "Hello World!";

        //encrypt
        string hex = p.Encrypt(plainText);

        //decrypt
        string roundTrip = p.Decrypt(hex);

        Console.WriteLine("Round Trip: {0}", roundTrip);
    }

    string Encrypt(string plainText)
    {
        Console.WriteLine("\nSending (encrypt side)...");
        Console.WriteLine("Plain Text: {0}", plainText);
        Console.WriteLine("Key: {0}", key);
        string hex = string.Empty;
        string ivString = AnotherAES.GetUniqueString(16);
        Console.WriteLine("IV: {0}", ivString);
        using (AnotherAES aes = new AnotherAES(key))
        {
            //encrypting side
            byte[] IV = Encoding.UTF8.GetBytes(ivString);

            //get encrypted bytes (IV bytes prepended to cipher bytes)
            byte[] encryptedBytes = aes.Encrypt(plainText, IV);
            byte[] encryptedBytesWithIV = IV.Concat(encryptedBytes).ToArray();

            //get hex string to send with url
            //this hex has both IV and ciphertext
            hex = BitConverter.ToString(encryptedBytesWithIV).Replace("-", "");
            Console.WriteLine("sending hex: {0}", hex);
        }

        return hex;
    }

    string Decrypt(string hex)
    {
        Console.WriteLine("\nReceiving (decrypt side)...");
        Console.WriteLine("received hex: {0}", hex);
        string roundTrip = string.Empty;
        Console.WriteLine("Key " + key);
        using (AnotherAES aes = new AnotherAES(key))
        {
            //get bytes from url
            byte[] encryptedBytesWithIV = AnotherAES.StringToByteArray(hex);

            byte[] IV = encryptedBytesWithIV.Take(16).ToArray();

            Console.WriteLine("IV: {0}", System.Text.Encoding.Default.GetString(IV));

            byte[] cipher = encryptedBytesWithIV.Skip(16).ToArray();

            roundTrip = aes.Decrypt(cipher, IV);
        }
        return roundTrip;
    }
}

Geben Sie hier die Bildbeschreibung ein


-2

Ich denke, das ist die einfachste der Welt!

string encrypted = "Text".Aggregate("", (c, a) => c + (char) (a + 2));

Prüfung

 Console.WriteLine(("Hello").Aggregate("", (c, a) => c + (char) (a + 1)));
            //Output is Ifmmp
 Console.WriteLine(("Ifmmp").Aggregate("", (c, a) => c + (char)(a - 1)));
            //Output is Hello

ROT ... 1? "Ja wirklich?" OP rief sogar ROT13 als Beispiel dafür auf, was er nicht tun wollte.
user812786
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.