«Obfuscation» de données bidirectionnelles non sécurisées simples?

426

Je recherche des fonctionnalités d'obfuscation très simples (comme crypter et décrypter mais pas nécessairement sécurisées) pour certaines données. Ce n'est pas essentiel à la mission. J'ai besoin de quelque chose pour garder les honnêtes gens honnêtes, mais quelque chose d'un peu plus fort que ROT13 ou Base64 .

Je préfère quelque chose qui est déjà inclus dans le .NET Framework 2.0, donc je n'ai pas à me soucier des dépendances externes.

Je ne veux vraiment pas avoir à jouer avec les clés publiques / privées, etc. Je bousillerais probablement les maths et le rendrais banal.

Matt Dawdy
la source
3
Salut Mark - pas de problème. Je me sentais mal de devoir accepter la réponse de richdiet, car j'ai effectivement utilisé sa solution et cela a très bien fonctionné. Cependant, je revenais ici pour lire les autres réponses, et la vôtre est vraiment meilleure. Aucune raison de dire aux gens d'utiliser quelque chose qui, bien que cela fonctionne, n'est pas vraiment un excellent moyen de faire quelque chose lorsqu'une meilleure réponse est disponible.
Matt Dawdy
3
Gagnez des heures et utilisez HttpServerUtility.UrlTokenEn / Decode pour effectuer des conversions aller-retour à partir des tableaux d'octets en une chaîne adaptée aux URL.
Praesagus
32
+1 pour ne pas avoir essayé de lancer votre propre design intelligent. Vous ne savez peut-être pas grand-chose sur le cryptage, mais le fait que vous sachiez que cela vous donne des années-lumière d'avance sur la plupart des développeurs que j'ai rencontrés qui ne connaissent pas grand-chose au cryptage mais pensent qu'ils peuvent de toute façon créer leur propre solution.
Dinah
6
Attention: la plupart des réponses à cette question concernent uniquement le chiffrement non authentifié. Cela signifie que l' attaquant peut modifier les données sans que l'application ne s'en rende compte . Cela conduit également à d'autres vulnérabilités graves (comme le décryptage sans clé en raison de l'oracle de remplissage). TL; DR: N'utilisez pas le code dans les réponses données si vous n'êtes pas d'accord avec cela, ou ne comprenez pas ce que je viens de dire.
usr
36
Pas une seule réponse à cette question ne décrit le cryptage sécurisé. Utilisez la réponse de jbtule sur Encrypt et déchiffrez une chaîne à la place.
CodesInChaos

Réponses:

471

D'autres réponses fonctionnent bien, mais AES est un algorithme de chiffrement plus sécurisé et à jour. Il s'agit d'une classe que j'ai obtenue il y a quelques années pour effectuer le cryptage AES que j'ai modifié au fil du temps pour être plus convivial pour les applications Web (par exemple, j'ai construit des méthodes Encrypt / Decrypt qui fonctionnent avec une chaîne compatible URL). Il a également les méthodes qui fonctionnent avec les tableaux d'octets.

REMARQUE: vous devez utiliser différentes valeurs dans les tableaux Clé (32 octets) et Vecteur (16 octets)! Vous ne voudriez pas que quelqu'un comprenne vos clés en supposant simplement que vous avez utilisé ce code tel quel! Tout ce que vous avez à faire est de modifier certains des nombres (qui doivent être <= 255) dans les tableaux de clés et de vecteurs (j'ai laissé une valeur non valide dans le tableau de vecteurs pour vous assurer de le faire ...). Vous pouvez utiliser https://www.random.org/bytes/ pour générer facilement un nouvel ensemble:

Son utilisation est simple: il suffit d'instancier la classe, puis d'appeler (généralement) EncryptToString (chaîne StringToEncrypt) et DecryptString (chaîne StringToDecrypt) comme méthodes. Cela ne pourrait pas être plus facile (ou plus sûr) une fois que cette classe est en place.


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;
    }
}
Mark Brittingham
la source
53
@AndyMcKenna - C'est fait exprès pour que vous changiez les valeurs dans les tableaux, comme le note Mark dans le deuxième paragraphe.
Pauk
42
Vous ne devriez pas utiliser le IV comme ça. Pour deux messages donnés, ils ne devraient pas avoir été chiffrés avec la même clé et le même IV. L'IV doit être aléatoire pour chaque message, ajouté au cryptostream et lu avant le décryptage. crypto.stackexchange.com/a/82/1934
jbtule
30
L'utilisation d'un IV aléatoire pour chaque message n'est pas exotique ou nouvelle, juste importante et fait partie de la conception de l'algorithme. L'utilisation d'un IV prévisible pour chaque message est une erreur de cryptographie courante qui n'a pas besoin d'être perpétuée.
jbtule
14
Notez également qu'une conséquence de l'utilisation de CBC comme mode est que vous êtes susceptible d'être vulnérable à des attaques oracle de remplissage . Utilisez un cryptage authentifié et, dans la mesure du possible, n'implémentez pas vous-même la cryptographie .
Stephen Touset
57
Avertissement de sécurité: n'utilisez pas ce code Bien qu'il s'agisse de la réponse acceptée, il y a de graves problèmes de sécurité mentionnés dans les commentaires ci-dessus que l'auteur a continué d'ignorer pendant 8 ans.
jbtule
176

J'ai nettoyé SimpleAES (ci-dessus) pour mon usage. Correction des méthodes de chiffrement / déchiffrement alambiquées; des méthodes séparées pour coder les tampons d'octets, les chaînes et les chaînes compatibles avec les URL; fait usage des bibliothèques existantes pour le codage des URL.

Le code est petit, plus simple, plus rapide et la sortie est plus concise. Par exemple, [email protected]produit:

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();
    }
}
Boue
la source
2
Lors du décodage, j'ai dû remplacer l'espace par + pour qu'il fonctionne avec QueryString dans Chrome: (nouveau SimplerAES ()). Decrypt (Request.QueryString ["myParam"]. Replace ('', '+'));
live-love
20
N'utilisez jamais un vecteur d'initialisation constant, voir: crypto.stackexchange.com/questions/66/… pour plus d'informations sur pourquoi. Au lieu de cela, générez un nouveau IV pour chaque cryptage et ajoutez-le au cryptotexte, tellement mieux et pas trop fort.
Tom Heard
2
Sachez que la sortie de la méthode EncryptToUrl dans cette solution (ou toute utilisation d'une chaîne UrlEncoded base 64 en général) ne fonctionnera pas par défaut sous IIS 7 lorsqu'elle est utilisée dans le cadre d'un chemin URL (pas une chaîne de requête), comme dans une route ASP.NET MVC, en raison d'un paramètre de sécurité IIS 7. Pour plus d'informations, voir: stackoverflow.com/a/2014121/12484
Jon Schneider
5
@TomHeard Comment pourrait-on s'y prendre avec le code ci-dessus?
MKII
26
Avertissement de sécurité: n'utilisez pas ce code Voir le commentaire de @TomHeard
jbtule
36

Oui, ajoutez l' System.Securityassembly, importez l' System.Security.Cryptographyespace de noms. Voici un exemple simple de chiffrement d'algorithme symétrique (DES):

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);
ZeroBugBounce
la source
5
Il s'agit d'un cryptage bidirectionnel agréable et compact. La seule mise en garde est que le DES n'est plus considéré comme une sécurité de pointe. Ce titre revient maintenant à l'algorithme AES dont je parle ci-dessous.
Mark Brittingham,
@richdiet. Je suis désolé d'avoir refusé votre réponse. L'autre réponse avec 37+ votes car c'est plus courant. Merci pour votre réponse, car elle est toujours bonne.
Matt Dawdy
14
@MarkBrittingham: tout chiffrement de bloc sans fonction de chaînage de bloc, vecteur d'initialisation et remplissage correct n'est pas sécurisé. L'utilisation de DES est le problème le moins important avec ce schéma.
Hubert Kario
2
Alors, où est la clé utilisée?
Alex
22
Avertissement de sécurité: n'utilisez pas ce code Voir le commentaire de @HubertKario
jbtule
28

Je pensais juste ajouter que j'ai amélioré SimplerAES de Mud en ajoutant un IV aléatoire qui est renvoyé à l'intérieur de la chaîne cryptée. Cela améliore le cryptage car le cryptage de la même chaîne entraînera une sortie différente à chaque fois.

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

Et test unitaire bonus

[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");
}
Andy C
la source
11
1) Ne pas utiliser System.Randomcomme RNG. 2) Ceci est totalement rompu contre les attaques de texte chiffré choisi (en particulier les oracles de remplissage)
CodesInChaos
21
Avertissement de sécurité: n'utilisez pas ce code voir le commentaire ci-dessus par @CodesInChaos
jbtule
@jbtule s'il vous plaît ne vous trompez pas pour toutes les personnes qui ne veulent pas de complications, mais qui ne se méfient pas de l'attaque, - Veuillez ne pas commander si vous voulez donner une suggestion.
Virbhadrasinh
@Virbhadrasinh il n'y a aucun malentendu de ma part, en fait c'est tout le contraire. Si vous allez utiliser AES, il est très important de l'utiliser correctement, de l'utiliser de manière incorrecte et de dire que ça va, je ne l'utilise pas pour quelque chose d'important, c'est une erreur.
jbtule
1
@Corey Ne crie pas et a suivi la meilleure pratique pour traiter les problèmes de sécurité dans les réponses de débordement de pile. Si vous voulez un lien, il a été publié dans les commentaires de la question. Mais je vais le mettre ici pour vous aussi stackoverflow.com/a/10366194/637783
jbtule
12

Une variante de Marks (excellente) réponse

  • Ajouter des "utilisant"
  • Rendre la classe IDisposable
  • Supprimez le code d'encodage URL pour simplifier l'exemple.
  • Ajouter un appareil de test simple pour démontrer l'utilisation

J'espère que cela t'aides

[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();
        }
    }
}
Simon
la source
Bonne réponse. Une chose dans la méthode Dispose vous devrez convertir rijndael en IDisposable ou vous obtiendrez une erreur de niveau de protection en appelant Dispose
John ClearZ
8
N'utilisez jamais un vecteur d'initialisation constant, voir: crypto.stackexchange.com/questions/66/… pour plus d'informations sur pourquoi. Au lieu de cela, générez un nouveau IV pour chaque cryptage et ajoutez-le au cryptotexte, tellement mieux et pas trop fort.
Tom Heard
5
@Chalky On encrypt, vous utilisez la classe Rijndael pour générer un IV aléatoire pour vous ( msdn.microsoft.com/en-us/library/… ), faites votre cryptage, puis récupérez l'IV de l'instance de Rijndael en utilisant la propriété IV . Vous ajoutez ensuite (ou ajoutez, soit fonctionne tant que votre décryptage le prend du même côté) à votre texte crypté. Lors du déchiffrement, vous extrayez ensuite l'IV des données reçues (la taille de la propriété IV est la même que la propriété BlockSize divisée par 8), puis la transmettez à votre instance de déchiffrement avant de déchiffrer.
Tom Heard
2
@Chalky Notez que l'IV n'a pas besoin d'être secret, il doit juste être unique pour chaque message envoyé.
Tom Heard le
20
Avertissement de sécurité: n'utilisez pas ce code Voir ci-dessus Commentaires de @TomHeard
jbtule
8

[EDIT] Des années plus tard, je suis revenu pour dire: ne fais pas ça! Voir Qu'est-ce qui ne va pas avec le cryptage XOR?pour plus de détails.

Un cryptage bidirectionnel très simple et facile est le cryptage XOR.

  1. Trouvez un mot de passe. Que ce soit mypass.
  2. Convertissez le mot de passe en binaire (selon ASCII). Le mot de passe devient 01101101 01111001 01110000 01100001 01110011 01110011.
  3. Prenez le message que vous souhaitez encoder. Convertissez aussi cela en binaire.
  4. Regardez la longueur du message. Si la longueur du message est de 400 octets, transformez le mot de passe en une chaîne de 400 octets en le répétant encore et encore. Il deviendrait 01101101 01111001 01110000 01100001 01110011 01110011 01101101 01111001 01110000 01100001 01110011 01110011 01101101 01111001 01110000 01100001 01110011 01110011 ... (ou mypassmypassmypass...)
  5. OU le message avec le mot de passe long.
  6. Envoyez le résultat.
  7. Une autre fois, XOR le message chiffré avec le même mot de passe ( mypassmypassmypass...).
  8. Voilà votre message!
stalepretzel
la source
10
@Ryan Toutes les situations ne nécessitent pas de hachage cryptographique sécurisé ou de chiffrement Rijndael. «Cryptage simple à 2 voies» pourrait en fait signifier simple , ce qui suggère xor ou même ROT13.
1
@Ryan: AES avec clé de chiffrement statique, pas de vecteur d'initialisation et pas de fonction de chaînage de blocs est juste un nom de fantaisie pour le chiffrement XOR, vous utilisez juste du KDF vraiment fantaisiste ...
Hubert Kario
17
Avertissement de sécurité: n'utilisez pas ce code Le cryptage XOR avec une clé répétitive est trivialement fissuré.
jbtule
7

J'ai combiné ce que j'ai trouvé de mieux à partir de plusieurs réponses et commentaires.

  • Vecteur d'initialisation aléatoire ajouté au texte crypté (@jbtule)
  • Utilisez TransformFinalBlock () au lieu de MemoryStream (@RenniePet)
  • Aucune clé pré-remplie pour éviter que quiconque copie et colle un sinistre
  • Disposer et utiliser correctement les modèles

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

Mise à jour 2015-07-18: Correction d'une erreur dans la méthode Encrypt () privée par les commentaires de @bpsilver et @Evereq. IV a été accidentellement chiffré, est maintenant ajouté en texte clair comme prévu par Decrypt ().

angularsen
la source
Vous devez crypter l'intégralité de InputBuffer avec IV ajouté avant, sinon les 16 premiers caractères de la chaîne à crypter seront perdus. Donc, votre code devrait lire:return _encryptor.TransformFinalBlock(inputBuffer, 0, inputBuffer.Length);
bpsilver
2
Dans ce cas:byte [] inputBuffer = _encryptor.TransformFinalBlock(buffer, 0, buffer.Length); return _rijndael.IV.Concat(inputBuffer).ToArray();
bpsilver
1
Cela ferait la même chose que l'implémentation actuelle, n'est-ce pas?
angularsen
1
"REMPLIS-MOI AVEC 16, 24 OU 32 CHARS" eh bien, non, pas avant le décodage en base 64. Et une clé doit être aléatoire. Vraiment aléatoire.
Maarten Bodewes
1
Je remarque que @bpsilver a raison et que le code fourni ne fonctionnera pas sans sa correction: la méthode de chiffrement renvoie les données chiffrées sans IV (elle ajoute d'abord IV à inputbuffer, mais ensuite chiffrer et renvoyer les données sans elle). Donc, si possible, mettez à jour la réponse avec son code. (Remarque: je teste uniquement les méthodes avec des paramètres byte [], pas des chaînes). Merci!
Evereq
6

Si vous voulez simplement un chiffrement simple (c'est-à-dire, possible pour un pirate déterminé de se casser, mais en bloquant la plupart des utilisateurs occasionnels), choisissez simplement deux phrases de passe de longueur égale, dites:

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

et xor vos données avec les deux (en bouclant les phrases secrètes si nécessaire) (a) . Par exemple:

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

Quelqu'un qui recherche dans votre binaire peut penser que la chaîne d'ADN est une clé, mais il est peu probable qu'il pense que le code C est autre chose qu'une mémoire non initialisée enregistrée avec votre binaire.


(a) Gardez à l'esprit qu'il s'agit d' un cryptage très simple et, selon certaines définitions, ne peut pas du tout être considéré comme du cryptage (puisque le but du cryptage est d' empêcher l'accès non autorisé plutôt que de le rendre plus difficile). Bien sûr, même le cryptage le plus puissant n'est pas sûr lorsque quelqu'un se tient au-dessus des porte-clés avec un tuyau en acier.

Comme indiqué dans la première phrase, c'est un moyen de rendre assez difficile pour l'attaquant occasionnel de continuer. C'est similaire à la prévention des cambriolages sur votre maison - vous n'avez pas besoin de la rendre imprenable, il vous suffit de la rendre moins prégnable que la maison voisine :-)

paxdiablo
la source
3
Idée intéressante. Je ne suis pas sûr que je "croirais" le code source dans un binaire - mais que diriez-vous d'adapter l'idée pour utiliser un message d'erreur comme phrase secrète?
Jon Skeet
1
Je préfère utiliser un hachage md5 d'une chaîne en texte clair qui existe déjà dans l'application (message d'erreur ou plus).
Treb
2
Pourquoi doivent-ils être de longueur égale? En fait, cela semble mieux s’ils sont de longueurs différentes. De cette façon, la longueur de votre opérande XOR effectif est LCM (longueur1, longueur2), au lieu de simplement longueur1 (= longueur2). Ce qui bien sûr devient longueur1 * longueur2 si les longueurs sont relativement premières.
Fantius
15
Avertissement de sécurité: ne pas utiliser ce code La clé extensible XOR est facilement craquable avec juste quelques connaissances générales sur les données cryptées.
jbtule
3
@jbtule, si vous aviez lu la question, vous vous rendriez compte qu'un cryptage plus sécurisé n'était en aucun cas requis. Plus précisément, la référence au «chiffrement simple», «non critique pour la mission» et simplement «à garder les gens honnêtes honnêtes». Vous devriez également lire mon premier paragraphe qui appelle explicitement le fait qu'il ne bloquera pas les attaquants déterminés.
paxdiablo
5

Le chiffrement est facile: comme d'autres l'ont souligné, il existe des classes dans l'espace de noms System.Security.Cryptography qui font tout le travail pour vous. Utilisez-les plutôt que n'importe quelle solution maison.

Mais le déchiffrement est également facile. Le problème que vous rencontrez n'est pas l'algorithme de chiffrement, mais la protection de l'accès à la clé utilisée pour le déchiffrement.

J'utiliserais l'une des solutions suivantes:

  • DPAPI utilisant la classe ProtectedData avec la portée CurrentUser. C'est facile car vous n'avez pas à vous soucier d'une clé. Les données ne peuvent être déchiffrées que par le même utilisateur, donc pas bon pour le partage de données entre utilisateurs ou machines.

  • DPAPI utilisant la classe ProtectedData avec la portée LocalMachine. Idéal pour, par exemple, protéger les données de configuration sur un seul serveur sécurisé. Mais toute personne qui peut se connecter à la machine peut la crypter, donc rien de bien si le serveur n'est pas sécurisé.

  • Tout algorithme symétrique. J'utilise généralement la méthode statique SymmetricAlgorithm.Create () si je me fiche de l'algorithme utilisé (en fait, c'est Rijndael par défaut). Dans ce cas, vous devez en quelque sorte protéger votre clé. Par exemple, vous pouvez le masquer d'une manière ou d'une autre et le cacher dans votre code. Mais sachez que toute personne suffisamment intelligente pour décompiler votre code sera probablement en mesure de trouver la clé.

Joe
la source
5

Je voulais publier ma solution car aucune des solutions ci-dessus n'est aussi simple que la mienne. Laissez-moi savoir ce que vous pensez:

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

Optionnel

Cela suppose que la MachineKey du serveur utilisé pour chiffrer la valeur est la même que celle utilisée pour déchiffrer la valeur. Si vous le souhaitez, vous pouvez spécifier une MachineKey statique dans Web.config afin que votre application puisse décrypter / crypter les données quel que soit l'endroit où elles sont exécutées (par exemple, développement vs serveur de production). Vous pouvez générer une clé machine statique en suivant ces instructions .

William
la source
notez que cette approche ne peut être utilisée que pour l'application ASP.NET.
Feru
2

L'espace de noms System.Security.Cryptographycontient les classes TripleDESCryptoServiceProvideretRijndaelManaged

N'oubliez pas d'ajouter une référence à l' System.Securityassemblage.

Blé Mitch
la source
8
Non pas que j'ai voté contre, mais pourquoi l'âge d'une question devrait-il être important lors du vote?
user247702
2

Utilisation de TripleDESCryptoServiceProvider dans 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);
    }
}
Ashkan Sirous
la source
1

J'ai changé ça :

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

pour ça:

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

À l'aide de la bibliothèque de cryptographie .Net intégrée, cet exemple montre comment utiliser la norme de cryptage avancée (AES).

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;

        }
    }
}
Mat
la source
0

Je sais que vous avez dit que vous ne vous souciez pas de la sécurité, mais si vous choisissez DES, vous pourriez aussi bien prendre AES, c'est la méthode de cryptage la plus à jour.

Harald Scheirich
la source
0

J'ai utilisé la réponse acceptée par Mark Brittingham et cela m'a beaucoup aidé. Récemment, j'ai dû envoyer du texte crypté à une autre organisation et c'est là que certains problèmes sont survenus. L'OP ne nécessite pas ces options, mais comme c'est une question populaire, je poste ma modification ( Encryptet les Decryptfonctions empruntées ici ):

  1. IV différent pour chaque message - Concatène les octets IV aux octets de chiffrement avant d'obtenir l'hex. Bien sûr, il s'agit d'une convention qui doit être communiquée aux parties qui reçoivent le texte chiffré.
  2. Permet deux constructeurs - un pour les RijndaelManagedvaleurs par défaut et un où les valeurs de propriété peuvent être spécifiées (sur la base d'un accord mutuel entre les parties de chiffrement et de déchiffrement)

Voici la classe (échantillon de test à la fin):

/// <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

et..

Voici l'exemple de test:

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

entrez la description de l'image ici

joym8
la source
-2

Je pense que c'est le monde le plus simple!

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

Tester

 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
Tonnerre
la source
ROT ... 1? Vraiment? OP a même cité ROT13 comme exemple de ce qu'il ne voulait pas faire.
user812786