"Offuscamento" dei dati bidirezionale insicuro?


426

Sto cercando funzionalità di offuscamento molto semplice (come crittografare e decrittografare ma non necessariamente sicuro) per alcuni dati. Non è mission-critical. Ho bisogno di qualcosa per mantenere oneste le persone oneste, ma qualcosa di un po 'più forte di ROT13 o Base64 .

Preferirei qualcosa che è già incluso in .NET Framework 2.0, quindi non devo preoccuparmi di dipendenze esterne.

Non voglio davvero dover fare confusione con le chiavi pubbliche / private, ecc. Non so molto sulla crittografia, ma ne so abbastanza per sapere che tutto ciò che ho scritto sarebbe meno che inutile ... In effetti, Probabilmente avrei rovinato la matematica e reso banale il crack.


3
Ciao Mark - nessun problema. Mi sentivo male per aver dovuto accettare la risposta di richdiet, poiché in realtà utilizzavo la sua soluzione e funzionava perfettamente. Tuttavia, ho continuato a tornare qui per leggere le altre risposte, e la tua è davvero migliore. Nessun motivo per dire alle persone di usare qualcosa che, mentre funziona, non è davvero un ottimo modo per fare qualcosa quando c'è una risposta migliore disponibile.
Matt Dawdy,

3
Risparmia te stesso ore e usa HttpServerUtility.UrlTokenEn / Decode per convertire avanti e indietro dagli array di byte in una stringa amichevole dell'URL.
Praesagus,

32
+1 per non aver cercato di creare il tuo design intelligente. Potresti non sapere molto sulla crittografia, ma il fatto che tu sappia che ti mette avanti anni prima della maggior parte degli sviluppatori che ho incontrato che non conoscono molto la crittografia ma pensano di poter comunque creare la propria soluzione.
Dinah,

6
Attenzione: molte delle risposte a questa domanda sono solo la crittografia non autenticata. Ciò significa che l' attaccante può modificare i dati senza che l'app se ne accorga . Porta anche ad altre gravi vulnerabilità (come la decrittazione senza chiave dovuta all'oracolo di riempimento). TL; DR: non usare il codice nelle risposte fornite se non sei d'accordo con quello o non capisci cosa ho appena detto.
usr

36
Non una sola risposta a questa domanda descrive la crittografia sicura. Usa la risposta di jbtule su Encrypt e decodifica invece una stringa .
CodesInCos

Risposte:


471

Altre risposte qui funzionano bene, ma AES è un algoritmo di crittografia più sicuro e aggiornato. Questa è una classe che ho ottenuto qualche anno fa per eseguire la crittografia AES che ho modificato nel tempo per essere più amichevole per le applicazioni Web (ad esempio, ho creato metodi di crittografia / decrittografia che funzionano con una stringa compatibile con URL). Ha anche i metodi che funzionano con array di byte.

NOTA: è necessario utilizzare valori diversi nelle matrici Key (32 byte) e Vector (16 byte)! Non vorresti che qualcuno capisse le tue chiavi semplicemente supponendo che tu abbia usato questo codice così com'è! Tutto quello che devi fare è cambiare alcuni dei numeri (devono essere <= 255) negli array Key e Vector (ho lasciato un valore non valido nell'array Vector per assicurarti di farlo ...). Puoi usare https://www.random.org/bytes/ per generare facilmente un nuovo set:

Usarlo è semplice: basta istanziare la classe e quindi chiamare (di solito) EncryptToString (stringa StringToEncrypt) e DecryptString (stringa StringToDecrypt) come metodi. Non potrebbe essere più facile (o più sicuro) una volta che hai installato questa classe.


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 - Questo è stato fatto apposta in modo da modificare i valori nelle matrici, come osserva Mark nel secondo paragrafo.
Pauk,

42
Non dovresti usare IV in questo modo. Per un dato due messaggi, non avrebbero dovuto essere crittografati con la stessa chiave e lo stesso IV. Il IV dovrebbe essere casuale per ogni messaggio, anteposto al cryptostream e letto prima della decrittazione. crypto.stackexchange.com/a/82/1934
jbtule,

30
L'uso di un IV casuale per ogni messaggio non è esotico o nuovo, è solo importante e fa parte del design dell'algoritmo. L'uso di un IV prevedibile per ogni messaggio è un errore crittografico comune che non deve essere perpetuato.
jbtule,

14
Si noti inoltre che una conseguenza dell'utilizzo di CBC come modalità è che si rischia di essere vulnerabili agli attacchi di padding oracle . Usa la crittografia autenticata e, quando possibile, non implementare la crittografia da solo .
Stephen Touset,

57
Avviso di sicurezza: non utilizzare questo codice Nonostante sia la risposta accettata, ci sono gravi problemi di sicurezza menzionati nei commenti sopra che l'autore ha continuato a ignorare per 8 anni.
jbtule,

176

Ho pulito SimpleAES (sopra) per il mio uso. Corretti metodi di crittografia / decrittografia contorti; metodi separati per codificare buffer di byte, stringhe e stringhe compatibili con URL; fatto uso di librerie esistenti per la codifica URL.

Il codice è piccolo, più semplice, più veloce e l'output è più conciso. Ad esempio, johnsmith@gmail.comproduce:

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

Codice:

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
Durante la decodifica, ho dovuto sostituire lo spazio con + per farlo funzionare con QueryString in Chrome: (new SimplerAES ()). Decrypt (Request.QueryString ["myParam"]. Replace ('', '+'));
live-love,

20
Non utilizzare mai un vettore di inizializzazione costante, consultare: crypto.stackexchange.com/questions/66/… per ulteriori informazioni sul perché. Invece, genera un nuovo IV per ogni crittografia e aggiungilo al testo crittografato, molto meglio e non troppo.
Tom Heard

2
Tenere presente che l'output del metodo EncryptToUrl in questa soluzione (o qualsiasi utilizzo di una stringa di base 64 UrlEncoded in generale) non funzionerà per impostazione predefinita in IIS 7 se utilizzato come parte di un percorso URL (non stringa di query), come in una route ASP.NET MVC, a causa di un'impostazione di sicurezza IIS 7. Per ulteriori informazioni, consultare: stackoverflow.com/a/2014121/12484
Jon Schneider,

5
@TomHeard Come si potrebbe fare per farlo, con il codice sopra?
MKII,

26
Avviso di sicurezza: non utilizzare questo codice Vedi commento di @TomHeard
jbtule

36

Sì, aggiungi l' System.Securityassembly, importa lo System.Security.Cryptographyspazio dei nomi. Ecco un semplice esempio di crittografia di un algoritmo simmetrico (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);

5
Questa è una crittografia bidirezionale piacevole e compatta. L'unica avvertenza è che il DES non è più considerato sicurezza all'avanguardia. Quel titolo ora passa all'algoritmo AES che discuterò di seguito.
Mark Brittingham,

@richdiet. Mi dispiace di non aver accettato la tua risposta. L'altra risposta con più di 37 voti perché è più attuale. Grazie per la tua risposta, in quanto è ancora valida.
Matt Dawdy,

14
@MarkBrittingham: qualsiasi cifra di blocco senza funzione di concatenamento di blocchi, vettore di inizializzazione e riempimento corretto non è sicura. L'uso di DES è il problema meno importante con questo schema.
Hubert Kario,

2
Quindi dove viene utilizzata la chiave?
Alex

22
Avviso di sicurezza: non utilizzare questo codice Vedi commento di @HubertKario
jbtule

28

Ho pensato di aggiungere che ho migliorato Mud's SimplerAES aggiungendo un IV casuale che è passato all'interno della stringa crittografata. Ciò migliora la crittografia poiché la crittografia della stessa stringa provocherà ogni volta un output diverso.

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

E test unitario 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");
}

11
1) Non utilizzare System.Randomcome RNG. 2) Questo è completamente rotto contro attacchi di testo cifrato scelto (in particolare oracoli di riempimento)
CodesInChaos,

21
Avviso di sicurezza: non utilizzare questo codice, vedi il commento sopra di @CodesInChaos
jbtule,

@jbtule, per favore, non fraintendere a tutte le persone che non vogliono semplicemente complicare la crittografia, e anche a chi non è diffidente nei confronti dell'attacco, - Per favore, non ordinare se vuoi dare un suggerimento.
Virbhadrasinh,

@Virbhadrasinh non ci sono errori da parte mia, in realtà è esattamente il contrario. Se hai intenzione di usare AES, usarlo nel modo giusto è abbastanza importante, usarlo in modo errato e dire che va bene non lo sto usando per qualcosa di importante, è sbagliato.
jbtule,

1
@Corey Non urlava e aveva seguito le migliori pratiche per gestire i problemi di sicurezza nelle risposte di overflow dello stack. Se si desidera un collegamento, è stato pubblicato nei commenti alla domanda. Ma mi metterò qui per voi pure stackoverflow.com/a/10366194/637783
jbtule

12

Una variante della risposta Marks (eccellente)

  • Aggiungi "using" s
  • Rendi la classe IDisposable
  • Rimuovere il codice di codifica URL per semplificare l'esempio.
  • Aggiungi un semplice dispositivo di prova per dimostrare l'utilizzo

Spero che sia di aiuto

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

Buona risposta. Una cosa nel metodo Dispose dovrai lanciare rijndael su IDisposable o otterrai un errore di livello di protezione chiamando Dispose
John ClearZ,

8
Non utilizzare mai un vettore di inizializzazione costante, consultare: crypto.stackexchange.com/questions/66/… per ulteriori informazioni sul perché. Invece, genera un nuovo IV per ogni crittografia e aggiungilo al testo crittografato, molto meglio e non troppo.
Tom Heard

5
@Chalky Al momento della crittografia, usi la classe Rijndael per generare un IV casuale per te ( msdn.microsoft.com/en-us/library/… ), esegui la tua crittografia, quindi prendi il IV dall'istanza di Rijndael usando la proprietà IV . Quindi anteponi (o aggiungi, o funziona fintanto che il tuo decrittografo lo prende dallo stesso lato) al tuo testo crittografico. Al momento della decrittografia, estrarre il IV dai dati ricevuti (la dimensione della proprietà IV è la stessa della proprietà BlockSize divisa per 8), quindi passarlo all'istanza di decrittografia prima di decrittografare.
Tom Heard,

2
@Chalky Nota che IV non deve essere segreto, deve solo essere unico per ogni messaggio inviato.
Tom Heard,

20
Avviso di sicurezza: non utilizzare questo codice Vedi i commenti sopra di @TomHeard
jbtule

8

[EDIT] Anni dopo, sono tornato a dire: non farlo! Vedi cosa c'è di sbagliato con la crittografia XOR?per dettagli.

Un'encrytpion bidirezionale molto semplice e facile è la crittografia XOR.

  1. Vieni con una password. Facciamolo mypass.
  2. Converti la password in binario (secondo ASCII). La password diventa 01101101 01111001 01110000 01100001 01110011 01110011.
  3. Prendi il messaggio che vuoi codificare. Converti anche quello in binario.
  4. Guarda la lunghezza del messaggio. Se la lunghezza del messaggio è di 400 byte, trasforma la password in una stringa di 400 byte ripetendola ripetutamente. Diventerebbe 01101101 01111001 01110000 01100001 01110011 01110011 01101101 01111001 01110000 01100001 01110011 01110011 01101101 01111001 01110000 01100001 01110011 01110011 ... (o mypassmypassmypass...)
  5. XOR il messaggio con la password lunga.
  6. Invia il risultato
  7. Un'altra volta, XOR il messaggio crittografato con la stessa password ( mypassmypassmypass...).
  8. C'è il tuo messaggio!

10
@Ryan Non tutte le situazioni richiedono hash crittograficamente sicuri o cifre di Rijndael. "Crittografia semplice a 2 vie" potrebbe in realtà significare semplice , il che suggerisce xor o persino ROT13.

1
@Ryan: AES con chiave di crittografia statica, nessun vettore di inizializzazione e nessuna funzione di concatenamento di blocchi è solo un nome di fantasia per la crittografia XOR, stai solo usando KDF davvero di fantasia ...
Hubert Kario

17
Avviso di sicurezza: non utilizzare questo codice La crittografia XOR con una chiave ripetuta è banalmente incrinata.
jbtule

7

Ho combinato ciò che ho trovato il meglio da diverse risposte e commenti.

  • Vettore di inizializzazione casuale anteposto al testo crittografico (@jbtule)
  • Usa TransformFinalBlock () invece di MemoryStream (@RenniePet)
  • Nessuna chiave precompilata per evitare che qualcuno copi e incolli un disastro
  • Smaltire e utilizzare correttamente i modelli

Codice:

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

Aggiornamento 18/07/2015: errore risolto nel metodo Encrypt () privato mediante commenti di @bpsilver e @Evereq. IV è stato accidentalmente crittografato, ora è anteposto in chiaro come previsto da Decrypt ().


Dovresti crittografare l'intero inputBuffer con IV anteposto, altrimenti i primi 16 caratteri della stringa da crittografare vanno persi. Quindi il tuo codice dovrebbe essere:return _encryptor.TransformFinalBlock(inputBuffer, 0, inputBuffer.Length);
bpsilver,

2
In tal caso:byte [] inputBuffer = _encryptor.TransformFinalBlock(buffer, 0, buffer.Length); return _rijndael.IV.Concat(inputBuffer).ToArray();
bpsilver,

1
Ciò farebbe la stessa cosa dell'attuale implementazione, no?
angularsen,

1
"FILL ME WITH 16, 24 OR 32 CHARS" beh, no, non prima della decodifica base 64. E una chiave dovrebbe essere casuale. Davvero casuale.
Maarten Bodewes,

1
Ho notato che @bpsilver ha ragione, e il codice fornito non funzionerà senza la sua correzione: il metodo encrypt restituisce dati crittografati senza IV (prima aggiunge IV a inputbuffer, ma poi crittografa e restituisce dati senza di essa). Quindi, se possibile, aggiorna la risposta con il suo codice. (Nota: collaudo solo metodi con parametri byte [], non stringhe). Grazie!
Evereq,

6

Se vuoi solo una semplice crittografia (cioè, possibile che un determinato cracker si rompa, ma blocca la maggior parte degli utenti occasionali), scegli due passphrase di uguale lunghezza, dì:

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

e xor i tuoi dati con entrambi (ciclo delle passphrase se necessario) (a) . Per esempio:

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

Qualcuno che cerca nel tuo binario potrebbe pensare che la stringa del DNA sia una chiave, ma è improbabile che il codice C sia qualcosa di diverso dalla memoria non inizializzata salvata con il tuo binario.


(a) Tieni presente che si tratta di una crittografia molto semplice e, secondo alcune definizioni, potrebbe non essere considerata affatto crittografia (poiché l'intento della crittografia è di impedire l'accesso non autorizzato piuttosto che renderlo più difficile). Anche se, naturalmente, anche la crittografia più forte è insicura quando qualcuno sta in piedi sopra i portachiavi con un tubo d'acciaio.

Come affermato nella prima frase, questo è un mezzo per rendere abbastanza difficile per l'attaccante occasionale che passeranno. È simile alla prevenzione dei furti con scasso nella tua casa: non è necessario renderlo inespugnabile, devi solo renderlo meno incinta della casa accanto :-)


3
Idea interessante. Non sono sicuro di "credere" al codice sorgente in un file binario, ma che ne dici di adattare l'idea per usare un messaggio di errore come passphrase?
Jon Skeet,

1
Preferisco usare un hash md5 di una stringa in chiaro che esiste già nell'applicazione (messaggio di errore o giù di lì).
Treb,

2
Perché devono avere la stessa lunghezza? In realtà sembra meglio se hanno lunghezze diverse. In questo modo, la lunghezza dell'operando XOR effettivo è LCM (lunghezza1, lunghezza2), anziché solo lunghezza1 (= lunghezza2). Che ovviamente diventa length1 * length2 se le lunghezze sono relativamente prime.
Fanzio,

15
Avviso di sicurezza: non utilizzare questo codice La ripetizione della chiave XOR è facilmente crackabile con solo una conoscenza generale dei dati crittografati.
jbtule,

3
@jbtule, se leggessi la domanda, ti accorgeresti che non era richiesta alcuna crittografia più sicura. In particolare il riferimento a "crittografia semplice", "non di importanza critica" e solo "mantenere oneste le persone oneste". Dovresti anche leggere il mio primo paragrafo che dice esplicitamente che non bloccherà determinati aggressori.
paxdiablo,

5

La crittografia è semplice: come altri hanno sottolineato, ci sono classi nello spazio dei nomi System.Security.Cryptography che fanno tutto il lavoro per te. Usali piuttosto che qualsiasi soluzione domestica.

Ma anche la decrittazione è facile. Il problema che hai non è l'algoritmo di crittografia, ma la protezione dell'accesso alla chiave utilizzata per la decrittografia.

Vorrei utilizzare una delle seguenti soluzioni:

  • DPAPI utilizzando la classe ProtectedData con ambito CurrentUser. Questo è facile in quanto non devi preoccuparti di una chiave. I dati possono essere decifrati solo dallo stesso utente, quindi non va bene per la condivisione di dati tra utenti o macchine.

  • DPAPI utilizzando la classe ProtectedData con ambito LocalMachine. Buono per esempio per proteggere i dati di configurazione su un singolo server sicuro. Ma chiunque può accedere al computer può crittografarlo, quindi non va bene se il server non è sicuro.

  • Qualsiasi algoritmo simmetrico. In genere utilizzo il metodo statico SymmetricAlgorithm.Create () se non mi interessa quale algoritmo viene utilizzato (in realtà è Rijndael per impostazione predefinita). In questo caso è necessario proteggere la chiave in qualche modo. Ad esempio, puoi offuscarlo in qualche modo e nasconderlo nel tuo codice. Ma tieni presente che chiunque sia abbastanza intelligente da decompilare il tuo codice sarà probabilmente in grado di trovare la chiave.


5

Volevo pubblicare la mia soluzione poiché nessuna delle soluzioni precedenti è semplice come la mia. Fatemi sapere cosa ne pensate:

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

Opzionale

Ciò presuppone che MachineKey del server utilizzato per crittografare il valore sia uguale a quello utilizzato per decrittografare il valore. Se lo si desidera, è possibile specificare un MachineKey statico in Web.config in modo che l'applicazione possa decrittografare / crittografare i dati indipendentemente da dove vengono eseguiti (ad es. Server di sviluppo vs. server di produzione). È possibile generare una chiave macchina statica seguendo queste istruzioni .


nota che questo approccio può essere utilizzato solo per l'app ASP.NET.
Feru,

2

Lo spazio dei nomi System.Security.Cryptographycontiene le classi TripleDESCryptoServiceProvidereRijndaelManaged

Non dimenticare di aggiungere un riferimento System.Securityall'assembly.


8
Non che ho annullato il voto, ma perché dovrebbe essere importante l'età di una domanda al momento del voto?
user247702

2

Utilizzo di 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

Ho cambiato questo :

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

a questo:

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

1

Utilizzando la libreria di crittografia .Net integrata, questo esempio mostra come utilizzare Advanced Encryption Standard (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;

        }
    }
}

0

So che hai detto che non ti importa di quanto sia sicuro, ma se hai scelto DES potresti anche prendere AES , è il metodo di crittografia più aggiornato.


0

Ho usato la risposta accettata da Mark Brittingham e mi ha aiutato molto. Di recente ho dovuto inviare testo crittografato a un'organizzazione diversa ed è qui che sono emersi alcuni problemi. L'OP non richiede queste opzioni, ma poiché questa è una domanda frequente sto pubblicando la mia modifica ( Encrypte le Decryptfunzioni prese in prestito da qui ):

  1. IV diverso per ogni messaggio: concatena i byte IV ai byte di crittografia prima di ottenere l'esagono. Naturalmente questa è una convenzione che deve essere trasmessa alle parti che ricevono il testo cifrato.
  2. Consente due costruttori: uno per i RijndaelManagedvalori predefiniti e uno in cui è possibile specificare i valori delle proprietà (in base all'accordo reciproco tra parti crittografate e decrittanti)

Ecco la classe (campione di prova alla fine):

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

e..

Ecco l'esempio di prova:

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

inserisci qui la descrizione dell'immagine


-2

Penso che questo sia il mondo più semplice!

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

Test

 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? Veramente? OP ha anche chiamato ROT13 come esempio di ciò che non voleva fare.
user812786,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.