Sederhana data tidak aman dua arah "kebingungan"?

426

Saya mencari kebingungan yang sangat sederhana (seperti mengenkripsi dan mendekripsi tetapi belum tentu aman) untuk beberapa data. Itu bukan misi kritis. Saya butuh sesuatu untuk membuat orang jujur ​​jujur, tetapi sesuatu yang sedikit lebih kuat dari ROT13 atau Base64 .

Saya lebih suka sesuatu yang sudah termasuk dalam .NET framework 2.0, jadi saya tidak perlu khawatir tentang ketergantungan eksternal.

Saya benar-benar tidak ingin harus dipusingkan dengan kunci publik / pribadi, dll. Saya tidak tahu banyak tentang enkripsi, tetapi saya cukup tahu untuk mengetahui bahwa apa pun yang saya tulis akan kurang berharga ... Sebenarnya, Saya mungkin akan mengacaukan matematika dan membuatnya mudah untuk retak.

Matt Dawdy
sumber
3
Hai Tandai - tidak ada masalah. Saya merasa tidak enak karena saya harus menerima jawaban dari richdiet, karena saya benar-benar menggunakan solusinya dan itu bekerja dengan baik. Namun, saya terus datang ke sini untuk membaca jawaban yang lain, dan jawaban Anda benar-benar lebih baik. Tidak ada alasan untuk memberi tahu orang lain untuk menggunakan sesuatu yang, meskipun berfungsi, sebenarnya bukan cara yang bagus untuk melakukan sesuatu ketika ada jawaban yang lebih baik.
Matt Dawdy
3
Menghemat waktu berjam-jam dan gunakan HttpServerUtility.UrlTokenEn / Decode untuk mengkonversi bolak-balik dari array byte ke string ramah url.
Praesagus
32
+1 untuk tidak mencoba menggulung desain pintar Anda sendiri. Anda mungkin tidak tahu banyak tentang enkripsi, tetapi fakta bahwa Anda tahu itu membuat Anda lebih unggul dari sebagian besar pengembang yang saya temui yang tidak tahu banyak tentang enkripsi tetapi berpikir mereka tetap bisa membuat solusi mereka sendiri.
Dinah
6
Perhatian: Banyak jawaban dalam pertanyaan ini hanya enkripsi yang tidak diautentikasi. Ini berarti bahwa penyerang dapat mengubah data tanpa pemberitahuan aplikasi . Ini mengarah ke kerentanan serius lainnya juga (seperti dekripsi tanpa kunci karena padding oracle). TL; DR: Jangan gunakan kode dalam jawaban yang diberikan jika Anda tidak setuju dengan itu, atau tidak mengerti apa yang baru saja saya katakan.
usr
36
Tidak ada satu jawaban untuk pertanyaan ini yang menjelaskan enkripsi aman. Gunakan jawaban jbtule di Enkripsi dan dekripsi string sebagai gantinya.
CodesInChaos

Jawaban:

471

Jawaban lain di sini berfungsi dengan baik, tetapi AES adalah algoritma enkripsi yang lebih aman dan terkini. Ini adalah kelas yang saya peroleh beberapa tahun yang lalu untuk melakukan enkripsi AES yang telah saya modifikasi dari waktu ke waktu agar lebih ramah untuk aplikasi web (mis. Saya telah membangun metode Enkripsi / Dekripsi yang berfungsi dengan string URL-friendly). Ini juga memiliki metode yang bekerja dengan array byte.

CATATAN: Anda harus menggunakan nilai yang berbeda dalam array Key (32 bytes) dan Vector (16 bytes)! Anda tidak ingin seseorang mengetahui kunci Anda hanya dengan mengasumsikan bahwa Anda menggunakan kode ini apa adanya! Yang harus Anda lakukan adalah mengubah beberapa angka (harus <= 255) dalam array Kunci dan Vektor (saya meninggalkan satu nilai yang tidak valid dalam array Vektor untuk memastikan Anda melakukan ini ...). Anda dapat menggunakan https://www.random.org/bytes/ untuk menghasilkan set baru dengan mudah:

Menggunakannya mudah: cukup instantiate kelas lalu panggil (biasanya) EncryptToString (string StringToEncrypt) dan DecryptString (string StringToDecrypt) sebagai metode. Tidak mungkin lebih mudah (atau lebih aman) setelah Anda memiliki kelas ini di tempat.


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
sumber
53
@AndyMcKenna - Itu dilakukan dengan sengaja sehingga Anda mengubah nilai dalam array, seperti yang dicatat Mark pada paragraf kedua.
Pauk
42
Anda sebaiknya tidak menggunakan infus seperti ini. Untuk dua pesan yang diberikan, mereka seharusnya tidak dienkripsi dengan Kunci yang sama dan IV yang sama. IV harus acak untuk setiap pesan, diawali dengan cryptostream, dan dibacakan sebelum dekripsi. crypto.stackexchange.com/a/82/1934
jbtule
30
Menggunakan IV secara acak untuk setiap pesan tidak eksotis atau baru, hanya penting dan bagian dari desain algoritma. Menggunakan IV yang dapat diprediksi untuk setiap pesan adalah kesalahan kripto yang umum yang tidak perlu diabadikan.
jbtule
14
Perhatikan juga bahwa konsekuensi dari menggunakan CBC sebagai modenya adalah bahwa Anda cenderung rentan terhadap padding serangan oracle . Gunakan enkripsi yang diautentikasi, dan jika memungkinkan, jangan menerapkan kriptografi sendiri .
Stephen Touset
57
Peringatan Keamanan: Jangan Gunakan Kode Ini. Meskipun menjadi jawaban yang diterima, ada masalah keamanan parah yang disebutkan dalam komentar di atas yang terus diabaikan oleh penulis selama 8 tahun.
jbtule
176

Saya membersihkan SimpleAES (di atas) untuk saya gunakan. Memperbaiki metode enkripsi / dekripsi berbelit-belit; metode yang terpisah untuk mengkode byte buffer, string, dan string ramah URL; memanfaatkan perpustakaan yang ada untuk pengkodean URL.

Kode ini kecil, lebih sederhana, lebih cepat dan outputnya lebih ringkas. Misalnya, [email protected]menghasilkan:

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

Kode:

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();
    }
}
Lumpur
sumber
2
Saat mendekode, saya harus mengganti spasi dengan + agar berfungsi dengan QueryString di Chrome: (SimplerAES baru ()). Dekripsi (Request.QueryString ["myParam"]. Ganti ('', '+'));
live-love
20
Jangan pernah menggunakan Inisialisasi Vektor yang konstan, lihat: crypto.stackexchange.com/questions/66/… untuk informasi lebih lanjut tentang alasannya. Sebagai gantinya, buat IV baru untuk setiap enkripsi dan tambahkan ke cryptotext, jauh lebih baik dan tidak sulit.
Tom Heard
2
Sadarilah bahwa output dari metode EncryptToUrl dalam solusi ini (atau penggunaan string UrlEncoded 64 base secara umum) tidak akan berfungsi secara default di bawah IIS 7 bila digunakan sebagai bagian dari jalur URL (bukan string kueri), seperti pada rute ASP.NET MVC, karena pengaturan keamanan IIS 7. Untuk lebih lanjut, lihat: stackoverflow.com/a/2014121/12484
Jon Schneider
5
@ TomHeard Bagaimana cara melakukan itu, dengan kode di atas?
MKII
26
Peringatan Keamanan: Jangan Gunakan Kode Ini. Lihat komentar oleh @TomHeard
jbtule
36

Ya, tambahkan System.Securityperakitan, impor System.Security.Cryptographynamespace. Berikut adalah contoh sederhana enkripsi algoritma simetris (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
sumber
5
Ini adalah enkripsi dua arah yang ringkas dan bagus. Satu-satunya peringatan adalah bahwa DES tidak lagi dianggap sebagai keamanan yang canggih. Judul itu sekarang masuk ke algoritma AES yang saya bahas di bawah ini.
Mark Brittingham
@ Richdiet. Maaf saya tidak menerima jawaban Anda. Jawaban lainnya dengan 37+ suara karena lebih terkini. Terima kasih atas jawaban Anda, karena masih bagus.
Matt Dawdy
14
@ MarkBrittingham: setiap blok sandi tanpa fungsi blok rantai, vektor inisialisasi dan padding yang tepat tidak aman. Menggunakan DES adalah masalah yang paling tidak penting dengan skema ini.
Hubert Kario
2
Jadi di mana kunci itu digunakan?
Alex
22
Peringatan Keamanan: Jangan Gunakan Kode Ini. Lihat komentar oleh @ HubertKario
jbtule
28

Hanya berpikir saya akan menambahkan bahwa saya telah meningkatkan Mud's SimplerAES dengan menambahkan IV acak yang dilewatkan kembali ke dalam string terenkripsi. Ini meningkatkan enkripsi karena mengenkripsi string yang sama akan menghasilkan output yang berbeda setiap kali.

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

Dan tes unit 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
sumber
11
1) Jangan gunakan System.Randomsebagai RNG. 2) Ini benar-benar rusak terhadap serangan ciphertext yang dipilih (khususnya padding-
oracle
21
Peringatan Keamanan: Jangan Gunakan Kode Ini, lihat komentar di atas oleh @CodesInChaos
jbtule
@ jbtule tolong jangan sesat kepada setiap orang yang tidak ingin komplikasi hanya mengenkripsi, dan juga yang tidak waspada dengan serangan itu, - Tolong jangan memesan jika Anda ingin memberikan saran.
Virbhadrasinh
@Virbhadrasinh tidak ada kesesatan di pihak saya, sebenarnya justru sebaliknya. Jika Anda akan menggunakan AES, menggunakannya dengan benar sangat penting, menggunakannya dengan salah dan mengatakan tidak apa-apa Saya tidak menggunakannya untuk sesuatu yang penting, salah arah.
jbtule
1
@Corey Tidak berteriak, dan telah mengikuti praktik terbaik untuk menangani masalah keamanan dalam jawaban stack overflow. Jika Anda menginginkan tautan, tautan itu diposting di komentar pertanyaan. Tetapi saya akan menaruhnya di sini untuk Anda juga stackoverflow.com/a/10366194/637783
jbtule
12

Varian dari Marks (excellent) answer

  • Tambahkan "menggunakan"
  • Buat kelas IDisposable
  • Hapus kode penyandian URL untuk membuat contoh lebih sederhana.
  • Tambahkan perlengkapan tes sederhana untuk menunjukkan penggunaan

Semoga ini membantu

[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
sumber
Jawaban yang bagus. Satu hal dalam metode Buang Anda harus melemparkan rijndael ke IDisposable atau Anda akan mendapatkan kesalahan tingkat perlindungan dengan memanggil Buang
John ClearZ
8
Jangan pernah menggunakan Inisialisasi Vektor yang konstan, lihat: crypto.stackexchange.com/questions/66/… untuk informasi lebih lanjut tentang alasannya. Sebagai gantinya, buat IV baru untuk setiap enkripsi dan tambahkan ke cryptotext, jauh lebih baik dan tidak sulit.
Tom Heard
5
@ Chalky Saat mengenkripsi, Anda menggunakan kelas Rijndael untuk menghasilkan IV acak untuk Anda ( msdn.microsoft.com/en-us/library/… ), lakukan enkripsi, lalu ambil IV dari instance Rijndael menggunakan properti IV. . Anda kemudian menambahkan (atau menambahkan, berfungsi selama mendekripsi Anda mengambilnya dari sisi yang sama) ke teks crypto Anda. Pada dekripsi, Anda kemudian menarik IV dari data yang diterima (Ukuran properti IV sama dengan properti BlockSize dibagi 8), lalu meneruskannya ke contoh dekripsi Anda sebelum mendekripsi.
Tom Heard
2
@ Chalky Perhatikan bahwa IV tidak perlu dirahasiakan, hanya perlu unik untuk setiap pesan yang dikirim.
Tom Heard
20
Peringatan Keamanan: Jangan Gunakan Kode Ini Lihat Komentar di atas oleh @TomHeard
jbtule
8

[EDIT] Bertahun-tahun kemudian, saya kembali untuk mengatakan: jangan lakukan ini! Lihat Apa yang salah dengan enkripsi XOR? untuk detail.

Enkripsi dua arah yang sangat sederhana dan mudah adalah enkripsi XOR.

  1. Munculkan kata sandi. Mari kita lakukan mypass.
  2. Ubah kata sandi menjadi biner (sesuai dengan ASCII). Kata sandi menjadi 01101101 01111001 01110000 01100001 01110011 01110011.
  3. Ambil pesan yang ingin Anda enkode. Ubah itu menjadi biner, juga.
  4. Lihatlah panjang pesannya. Jika panjang pesan 400 byte, ubah kata sandi menjadi string 400 byte dengan mengulanginya berulang kali. Ini akan menjadi 01101101 01111001 01110000 01100001 01110011 01110011 01101101 01111001 01110000 01110011 01110011 01101101 01111001 01110000 01100001 01110011 01110011 ... (atau mypassmypassmypass...)
  5. XOR pesan dengan kata sandi panjang.
  6. Kirimkan hasilnya.
  7. Lain waktu, XOR pesan terenkripsi dengan kata sandi yang sama ( mypassmypassmypass...).
  8. Itu pesanmu!
stalepretzel
sumber
10
@Ryan Tidak setiap situasi membutuhkan hash yang aman secara kriptografis atau cipher Rijndael. "Enkripsi 2 arah sederhana" mungkin sebenarnya berarti sederhana , yang menunjukkan xor atau bahkan ROT13.
1
@Ryan: AES dengan kunci enkripsi statis, tidak ada vektor inisialisasi dan tidak ada fungsi rantai blok hanya nama mewah untuk enkripsi XOR, Anda hanya menggunakan KDF yang benar-benar mewah ...
Hubert Kario
17
Peringatan Keamanan: Jangan Gunakan Kode Ini. Enkripsi XOR dengan kunci berulang sangat mudah retak.
jbtule
7

Saya menggabungkan apa yang saya temukan yang terbaik dari beberapa jawaban dan komentar.

  • Vektor inisialisasi acak yang ditambahkan ke teks crypto (@jbtule)
  • Gunakan TransformFinalBlock () bukan MemoryStream (@RenniePet)
  • Tidak ada kunci yang diisi sebelumnya untuk menghindari siapa pun menyalin & menempel bencana
  • Buang dan gunakan pola dengan benar

Kode:

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

Pembaruan 2015-07-18: Memperbaiki kesalahan dalam metode Encrypt () pribadi dengan komentar @bpsilver dan @Evereq. IV sengaja dienkripsi, sekarang ditulis dalam teks yang jelas seperti yang diharapkan oleh Decrypt ().

angularsen
sumber
Anda harus mengenkripsi seluruh inputBuffer dengan IV terlebih dahulu jika tidak, 16 karakter pertama dari string-ke-enkripsi hilang. Jadi kode Anda harus membaca:return _encryptor.TransformFinalBlock(inputBuffer, 0, inputBuffer.Length);
bpsilver
2
Dalam hal ini:byte [] inputBuffer = _encryptor.TransformFinalBlock(buffer, 0, buffer.Length); return _rijndael.IV.Concat(inputBuffer).ToArray();
bpsilver
1
Itu akan melakukan hal yang sama dengan implementasi saat ini, bukan?
angularsen
1
"FILL ME WITH 16, 24 ATAU 32 CHARS" well, tidak, tidak sebelum base 64 decoding. Dan kunci harus acak. Benar-benar acak.
Maarten Bodewes
1
Saya perhatikan bahwa @bpsilver benar, dan kode yang disediakan tidak akan berfungsi tanpa perbaikannya: metode mengenkripsi mengembalikan data terenkripsi tanpa IV (pertama-tama menambahkan IV ke inputbuffer, tetapi selanjutnya mengenkripsi dan mengembalikan data tanpa itu). Jadi jika mungkin perbarui saja jawabannya dengan kodenya. (Catatan: Saya hanya menguji metode dengan parameter byte [], bukan string). Terima kasih!
Evereq
6

Jika Anda hanya ingin enkripsi sederhana (yaitu, mungkin untuk cracker yang ditentukan untuk istirahat, tetapi mengunci sebagian besar pengguna biasa), cukup pilih dua frasa sandi dengan panjang yang sama, katakan:

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

dan xor data Anda dengan keduanya (lewati kata sandi jika perlu) (a) . Sebagai contoh:

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

Seseorang yang mencari biner Anda mungkin berpikir bahwa string DNA adalah kunci, tetapi mereka tidak akan berpikir bahwa kode C adalah apa pun selain memori yang tidak diinisialisasi yang disimpan dengan biner Anda.


(a) Perlu diingat bahwa ini adalah enkripsi yang sangat sederhana dan, dengan beberapa definisi, mungkin tidak dianggap sebagai enkripsi sama sekali (karena maksud dari enkripsi adalah untuk mencegah akses yang tidak sah daripada hanya membuatnya lebih sulit). Meskipun, tentu saja, bahkan enkripsi terkuat tidak aman ketika seseorang berdiri di atas pemegang kunci dengan pipa baja.

Seperti yang dinyatakan dalam kalimat pertama, ini adalah sarana untuk membuatnya cukup sulit bagi penyerang kasual yang akan mereka jalani. Ini mirip dengan mencegah pencurian di rumah Anda - Anda tidak perlu membuatnya tidak bisa ditembus, Anda hanya perlu membuatnya lebih tidak bisa hamil daripada rumah di sebelah :-)

paxdiablo
sumber
3
Ide yang menarik. Saya tidak yakin saya akan "percaya" kode sumber dalam biner - tetapi bagaimana mengadaptasi ide untuk menggunakan pesan kesalahan sebagai frasa sandi?
Jon Skeet
1
Saya lebih suka menggunakan hash md5 dari beberapa string cleartext yang sudah ada dalam aplikasi (pesan kesalahan atau lebih).
Treb
2
Mengapa mereka harus memiliki panjang yang sama? Sebenarnya tampak lebih baik jika panjangnya berbeda. Dengan begitu, panjang operan XOR efektif Anda adalah LCM (length1, length2), bukan hanya length1 (= length2). Yang tentu saja menjadi length1 * length2 jika panjangnya relatif prima.
Fantius
15
Peringatan Keamanan: Jangan Gunakan Kode Ini. Kunci berulang XOR mudah dipecahkan hanya dengan pengetahuan umum tentang data yang dienkripsi.
jbtule
3
@ jbtule, jika Anda membaca pertanyaan, Anda akan menyadari bahwa enkripsi yang lebih aman sama sekali tidak diperlukan. Khususnya referensi untuk 'enkripsi sederhana', 'bukan misi kritis' dan hanya 'menjaga orang jujur ​​jujur'. Anda juga harus membaca paragraf pertama saya yang secara eksplisit menyebut fakta bahwa itu tidak akan mengunci penyerang yang ditentukan.
paxdiablo
5

Enkripsi mudah: seperti yang telah ditunjukkan orang lain, ada kelas-kelas di namespace System.Security.Cryptography yang melakukan semua pekerjaan untuk Anda. Gunakan mereka daripada solusi buatan sendiri.

Tapi dekripsi juga mudah. Masalah yang Anda miliki bukan algoritma enkripsi, tetapi melindungi akses ke kunci yang digunakan untuk dekripsi.

Saya akan menggunakan salah satu solusi berikut:

  • DPAPI menggunakan kelas ProtectedData dengan cakupan CurrentUser. Ini mudah karena Anda tidak perlu khawatir tentang kunci. Data hanya dapat didekripsi oleh pengguna yang sama, jadi tidak baik untuk berbagi data antar pengguna atau mesin.

  • DPAPI menggunakan kelas ProtectedData dengan cakupan LocalMachine. Baik untuk misalnya melindungi data konfigurasi pada satu server aman. Tapi siapa pun yang bisa masuk ke mesin bisa mengenkripsi itu, jadi tidak ada gunanya kecuali server aman.

  • Algoritma simetris apa pun. Saya biasanya menggunakan metode SymmetricAlgorithm.Create () statis jika saya tidak peduli algoritma apa yang digunakan (sebenarnya itu adalah Rijndael secara default). Dalam hal ini Anda perlu melindungi kunci Anda. Misalnya Anda dapat mengaburkan dalam beberapa cara dan menyembunyikannya di kode Anda. Namun ketahuilah bahwa siapa pun yang cukup pintar untuk mendekompilasi kode Anda kemungkinan akan dapat menemukan kuncinya.

Joe
sumber
5

Saya ingin memposting solusi saya karena tidak ada solusi di atas yang semudah milik saya. Biarkan aku tahu apa yang Anda pikirkan:

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

Pilihan

Ini mengasumsikan bahwa MachineKey dari server yang digunakan untuk mengenkripsi nilai sama dengan yang digunakan untuk mendekripsi nilai. Jika diinginkan, Anda dapat menentukan MachineKey statis di Web.config sehingga aplikasi Anda dapat mendekripsi / mengenkripsi data di mana pun dijalankan (mis. Pengembangan vs. server produksi). Anda dapat membuat kunci mesin statis mengikuti instruksi ini .

William
sumber
perhatikan bahwa pendekatan ini hanya dapat digunakan untuk aplikasi ASP.NET.
Feru
2

Namespace System.Security.Cryptographyberisi TripleDESCryptoServiceProviderdan RijndaelManagedkelas - kelas

Jangan lupa untuk menambahkan referensi ke System.Securitymajelis.

Mitch Wheat
sumber
8
Bukannya saya downvoted, tapi mengapa usia pertanyaan itu penting saat memilih?
user247702
2

Menggunakan TripleDESCryptoServiceProvider di 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
sumber
1

Saya mengubah ini :

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

untuk ini:

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

Menggunakan pustaka Kriptografi .Net bawaan, contoh ini menunjukkan cara menggunakan 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;

        }
    }
}
Mat
sumber
0

Saya tahu Anda mengatakan Anda tidak peduli seberapa amannya, tetapi jika Anda memilih DES, Anda sebaiknya menggunakan AES itu adalah metode enkripsi yang lebih mutakhir.

Harald Scheirich
sumber
0

Saya telah menggunakan jawaban yang diterima oleh Mark Brittingham dan itu banyak membantu saya. Baru-baru ini saya harus mengirim teks terenkripsi ke organisasi yang berbeda dan di situlah beberapa masalah muncul. OP tidak memerlukan opsi ini tetapi karena ini adalah pertanyaan populer, saya memposting modifikasi saya ( Encryptdan Decryptfungsi yang dipinjam dari sini ):

  1. IV berbeda untuk setiap pesan - Menggabungkan byte IV ke byte sandi sebelum mendapatkan hex. Tentu saja ini adalah konvensi yang perlu disampaikan kepada pihak-pihak yang menerima teks sandi.
  2. Mengizinkan dua konstruktor - satu untuk RijndaelManagednilai default , dan satu di mana nilai properti dapat ditentukan (berdasarkan kesepakatan bersama antara pihak enkripsi dan dekripsi)

Inilah kelasnya (sampel uji di akhir):

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

dan..

Berikut adalah contoh uji:

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

masukkan deskripsi gambar di sini

joym8
sumber
-2

Saya pikir ini adalah dunia yang paling sederhana!

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

Uji

 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
Guntur
sumber
ROT ... 1? Betulkah? OP bahkan menyebut ROT13 sebagai contoh dari apa yang tidak ingin dia lakukan.
user812786