443 Stimmen

Einfache, unsichere Zwei-Wege-Daten-"Verschleierung"?

Ich bin auf der Suche nach sehr einfachen Verschleierung (wie verschlüsseln und entschlüsseln, aber nicht unbedingt sicher) Funktionalität für einige Daten. Es ist nicht geschäftskritisch. Ich brauche etwas, um ehrliche Leute ehrlich zu halten, aber etwas, das ein wenig stärker ist als ROT13 o Base64 .

Ich würde etwas bevorzugen, das bereits in der Datenbank enthalten ist. .NET Framework 2.0, so dass ich mich nicht um externe Abhängigkeiten kümmern muss.

Ich möchte wirklich nicht mit öffentlichen/privaten Schlüsseln usw. herumhantieren müssen. Ich weiß nicht viel über Verschlüsselung, aber ich weiß genug, um zu wissen, dass alles, was ich schreiben würde, weniger als wertlos wäre... Wahrscheinlich würde ich sogar die Berechnungen vermasseln, so dass es leicht zu knacken wäre.

11voto

angularsen Punkte 7545

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

  • Zufälliger Initialisierungsvektor, der dem Kryptotext vorangestellt wird (@jbtule)
  • TransformFinalBlock() anstelle von MemoryStream verwenden (@RenniePet)
  • Keine vorausgefüllten Tasten, um zu verhindern, dass jemand durch Kopieren und Einfügen ein Desaster verursacht.
  • Richtiges Entsorgen und Verwenden 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 2015-07-18: Fehler in privater Encrypt()-Methode durch Kommentare von @bpsilver und @Evereq behoben. IV wurde versehentlich verschlüsselt, wird jetzt im Klartext vorangestellt, wie von Decrypt() erwartet.

10voto

Ashkan S Punkte 8690

Verwendung von TripleDESCryptoServiceProvider in System.Sicherheit.Kryptographie :

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);
    }
}

8voto

stalepretzel Punkte 14832

(EDIT) Jahre später bin ich zurückgekommen, um zu sagen: Tun Sie das nicht! Siehe Was ist falsch an der XOR-Verschlüsselung? für Einzelheiten.

Eine sehr einfache, leicht zu handhabende Zweiwege-Verschlüsselung ist die XOR-Verschlüsselung.

  1. Denken Sie sich ein Passwort aus. Es soll lauten mypass .

  2. Konvertiert das Passwort in das Binärformat (nach ASCII). Das Passwort lautet dann 01101101 01111001 01110000 01100001 01110011 01110011.

  3. Nehmen Sie die Nachricht, die Sie kodieren wollen. Konvertieren Sie diese ebenfalls in das Binärformat.

  4. Achten Sie auf die Länge der Nachricht. Wenn die Nachricht 400 Byte lang ist, verwandeln Sie das Kennwort in eine 400-Byte-Zeichenkette, indem Sie es immer wieder wiederholen. Es würde zu 01101101 01111001 01110000 01100001 01110011 01110011 01101101 01111001 01110000 01100001 01110011 01110011 01101101 01111001 01110000 01100001 01110011 01110011... (oder mypassmypassmypass... )

  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. Das ist Ihre Botschaft!

5voto

Joe Punkte 117971

Verschlüsselung ist einfach: Wie bereits erwähnt, gibt es Klassen im System.Security.Cryptography-Namensraum, die die ganze Arbeit für Sie erledigen. Verwenden Sie diese, anstatt eine selbstentwickelte Lösung zu verwenden.

Aber auch die Entschlüsselung ist einfach. Das Problem, das Sie haben, ist nicht der Verschlüsselungsalgorithmus, sondern der Schutz des Zugangs zum Schlüssel für die Entschlüsselung.

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 Gedanken über einen Schlüssel machen müssen. Die Daten können nur von demselben Benutzer entschlüsselt werden, so dass sie nicht für die gemeinsame Nutzung von Daten durch andere Benutzer oder Maschinen geeignet sind.

  • DPAPI unter Verwendung der ProtectedData-Klasse mit LocalMachine-Bereich. Dies eignet sich z.B. für den Schutz von Konfigurationsdaten auf einem einzigen sicheren Server. Aber jeder, der sich bei der Maschine anmelden kann, kann die Daten verschlüsseln, was nur dann sinnvoll ist, wenn der Server sicher ist.

  • Jeder symmetrische Algorithmus. Normalerweise verwende ich die statische Methode SymmetricAlgorithm.Create(), wenn es mir egal ist, welcher Algorithmus verwendet wird (standardmäßig ist es Rijndael). In diesem Fall müssen Sie Ihren Schlüssel irgendwie schützen. Sie können ihn z.B. auf irgendeine Weise verschleiern und in Ihrem Code verstecken. Aber seien Sie sich bewusst, dass jeder, der schlau genug ist, Ihren Code zu dekompilieren, wahrscheinlich in der Lage sein wird, den Schlüssel zu finden.

5voto

paxdiablo Punkte 809679

Wenn Sie nur eine einfache Verschlüsselung wünschen (d. h., die ein entschlossener Cracker knacken kann, die aber die meisten Gelegenheitsnutzer ausschließt), wählen Sie einfach zwei gleich lange Passphrasen aus, zum Beispiel:

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

und xorieren Sie Ihre Daten mit beiden (ggf. mit einer Schleife der Passphrasen) (a) . Zum Beispiel:

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

Jemand, der Ihre Binärdatei durchsucht, könnte die DNA-Zeichenkette für einen Schlüssel halten, aber es ist unwahrscheinlich, dass er den C-Code für etwas anderes als nicht initialisierten Speicher hält, der mit Ihrer Binärdatei gespeichert wurde.


(a) Denken Sie daran, dass es sich um sehr einfache Verschlüsselung und kann nach einigen Definitionen überhaupt nicht als Verschlüsselung angesehen werden (da der Zweck der Verschlüsselung darin besteht, die verhindern. Unbefugten den Zugang zu erschweren). Aber natürlich ist auch die stärkste Verschlüsselung unsicher, wenn jemand mit einem Stahlrohr über den Schlüsselbesitzern steht.

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

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X