간단한 안전하지 않은 양방향 데이터“난독 화”?


426

일부 데이터에 대해 매우 간단한 난독 화 (암호화 및 암호 해독과 같은 보안 기능)를 찾고 있습니다. 미션 크리티컬하지 않습니다. 나는 정직한 사람들을 정직하게 유지하기 위해 무언가가 필요하지만 ROT13 또는 Base64 보다 조금 더 강합니다 .

.NET Framework 2.0 에 이미 포함되어있는 것을 선호 하므로 외부 종속성에 대해 걱정할 필요가 없습니다.

나는 공개 / 개인 키 등을 엉망으로 만들고 싶지 않습니다. 나는 암호화에 대해 많이 알지 못하지만, 내가 쓴 것이 가치가 없다는 것을 알만큼 충분히 알고 있습니다 ... 사실, 아마 수학을 망치고 깨지기 쉬운 것으로 만들 것입니다.


3
안녕하세요 마크-문제 없습니다. 실제로 그의 솔루션을 사용했기 때문에 richdiet의 답변을 받아 들여야한다는 것이 나빴습니다. 그러나 다른 답변을 읽기 위해 계속 여기에 왔으며 귀하의 답변이 더 좋습니다. 사람들에게 그것이 작동하는 동안 무언가를 사용하라고 말할 이유는 없습니다.
매트 도디

3
시간을 절약하고 HttpServerUtility.UrlTokenEn / Decode를 사용하여 바이트 배열에서 URL 친화적 인 문자열로 앞뒤로 변환하십시오.
Praesagus

32
자신의 영리한 디자인을 굴리지 않으려면 +1하십시오. 암호화에 대해 많이 알지 못하지만 암호화에 대해 잘 모르지만 어쨌든 자신의 솔루션을 만들 수 있다고 생각하는 대부분의 개발자보다 앞서 있습니다.
Dinah

6
주의 :이 질문에 대한 대부분의 답변은 인증되지 않은 암호화입니다. 이는 공격자가 앱에 알리지 않고 데이터를 변경할 수 있음을 의미합니다 . 패딩 오라클로 인한 키가없는 해독과 같은 다른 심각한 취약점도 발생합니다. TL; DR : 당신이 그것에 대해 잘하지 않거나 내가 방금 말한 것을 이해하지 못하면 주어진 답변에 코드를 사용하지 마십시오.
usr

36
이 질문에 대한 단일 답변은 안전한 암호화를 설명하지 않습니다. 암호화 에서 jbtule의 답변을 사용 하고 대신 문자열을 해독하십시오 .
코드 InChaos

답변:


471

다른 답변은 훌륭하지만 AES는보다 안전하고 최신 암호화 알고리즘입니다. 이것은 몇 년 전에 웹 응용 프로그램에보다 친숙하도록 시간이 지남에 따라 수정 된 AES 암호화를 수행하기 위해 얻은 클래스입니다 (예 : URL 친화적 인 문자열로 작동하는 암호화 / 암호 해독 방법을 작성했습니다). 바이트 배열과 함께 작동하는 메소드도 있습니다.

참고 : Key (32 바이트) 및 Vector (16 바이트) 배열에서 다른 값을 사용해야합니다! 이 코드를있는 그대로 사용한다고 가정하여 누군가 키를 알아 내지 않기를 바랍니다! Key 및 Vector 배열에서 일부 숫자 (<= 255이어야 함)를 변경하기 만하면됩니다 (Vector 배열에 유효하지 않은 값을 남겨 두었습니다 ...). https://www.random.org/bytes/ 를 사용하여 새 세트를 쉽게 생성 할 수 있습니다.

사용하기 쉽습니다 : 클래스를 인스턴스화 한 다음 메소드로 EncryptToString (string StringToEncrypt) 및 DecryptString (string StringToDecrypt)을 호출하십시오 (일반적으로). 이 수업을 마치면 더 쉬울 수 없습니다.


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-두 번째 단락의 Mark 참고 사항과 같이 배열의 값을 변경하기 위해 의도적으로 수행되었습니다.
Pauk

42
IV를 이와 같이 사용해서는 안됩니다. 주어진 두 메시지에 대해 동일한 키와 동일한 IV로 암호화되어서는 안됩니다. IV는 각 메시지에 대해 임의적이어야하며 암호 스트림 앞에 추가되어야하며 암호 해독 전에 읽어야합니다. crypto.stackexchange.com/a/82/1934
jbtule

30
각 메시지에 대해 임의의 IV를 사용하는 것은 이국적이지 않거나 새로운 것이 아니며, 중요하고 알고리즘 설계의 일부입니다. 모든 메시지에 예측 가능한 IV를 사용하는 것은 영구적 인 암호 실수로 영구히 적용 할 필요는 없습니다.
jbtule

14
CBC를 모드로 사용하면 패딩 오라클 공격에 취약 할 수 있습니다 . 인증 된 암호화를 사용하고 가능하면 암호화를 직접 구현하지 마십시오 .
Stephen Touset

57
보안 경고 :이 코드를 사용하지 마십시오 허용 된 답변 임에도 불구하고 위의 의견에서 저자가 8 년간 계속 무시해온 심각한 보안 문제가 있습니다.
jbtule

176

사용하기 위해 SimpleAES (위)를 정리했습니다. 고정 된 복잡한 암호화 / 복호화 방법; 바이트 버퍼, 문자열 및 URL 친화적 인 문자열을 인코딩하기위한 분리 된 메소드; URL 인코딩에 기존 라이브러리를 사용했습니다.

코드는 작고 단순하며 빠르며 출력이 더 간결합니다. 예를 들어 다음을 johnsmith@gmail.com생성합니다.

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

암호:

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
디코딩 할 때 Chrome에서 QueryString과 함께 작동하려면 공백을 +로 바꿔야했습니다. (new SimplerAES ()). Decrypt (Request.QueryString [ "myParam"]. Replace ( '', '+'));
live-love

20
상수 초기화 벡터를 사용하지 마십시오 . 이유에 대한 자세한 내용은 crypto.stackexchange.com/questions/66/… 을 참조하십시오. 대신, 각 암호화에 대해 새로운 IV를 생성하여 암호화 텍스트에 추가하십시오.
Tom Heard

2
이 솔루션의 EncryptToUrl 메소드 출력 (또는 일반적으로 UrlEncoded base 64 문자열 사용)은 URL 경로의 일부 (쿼리 문자열 아님)로 사용될 때 IIS 7에서 기본적으로 작동하지 않습니다. IIS 7 보안 설정으로 인한 ASP.NET MVC 경로 자세한 내용은 다음을 참조하십시오. stackoverflow.com/a/2014121/12484
Jon Schneider

5
@TomHeard 위의 코드로 어떻게 그렇게 할 수 있습니까?
MKII

26
보안 경고 :이 코드를 사용하지 마십시오 @TomHeard의 설명 참조
jbtule

36

예, System.Security어셈블리를 추가 하고 System.Security.Cryptography네임 스페이스를 가져옵니다 . 다음은 대칭 (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
이것은 훌륭하고 컴팩트 한 양방향 암호화입니다. 유일한 경고는 DES가 더 이상 최신 보안으로 간주되지 않는다는 것입니다. 그 제목은 이제 아래에서 논의하는 AES 알고리즘으로갑니다.
Mark Brittingham

@richdiet. 답변을받지 못해서 죄송합니다. 다른 답변은 최신 투표이므로 37 개 이상의 투표로 답변합니다. 여전히 좋은 답변이므로 답변 해 주셔서 감사합니다.
Matt Dawdy

14
@MarkBrittingham : 블록 체인 기능, 초기화 벡터 및 적절한 패딩이없는 모든 블록 암호는 안전하지 않습니다. 이 체계에서 DES를 사용하는 것이 가장 중요합니다.
허버트 카리오

2
열쇠는 어디에 사용됩니까?
Alex

22
보안 경고 :이 코드를 사용하지 마십시오 @HubertKario의 코멘트를보십시오
jbtule

28

방금 암호화 된 문자열 내부로 전달되는 임의의 IV를 추가하여 Mud의 SimplerAES를 개선했다고 덧붙였습니다. 동일한 문자열을 암호화하면 매번 다른 출력이 생성되므로 암호화가 향상됩니다.

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

그리고 보너스 단위 테스트

[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) System.RandomRNG로 사용하지 마십시오 . 2) 이것은 완전히) 특히 패딩-신탁에서 (선택-암호문 공격에 대한 고장
CodesInChaos

21
보안 경고 :이 코드를 사용하지 마십시오 @CodesInChaos의 위 주석 참조
jbtule

@jbtule은 합병증을 원하지 않는 모든 사람에게 잘못 안내하지 말고 공격에 대해 신경 쓰지 않는 사람에게도 잘못 안내하지 마십시오 .- 제안을 원하면 주문하지 마십시오.
Virbhadrasinh 2016 년

@ Virbhadrasinh 내 입장에는 오해가 없으며 실제로는 정반대입니다. AES를 사용하려는 경우 올바르게 사용하는 것이 중요합니다. 잘못 사용하고 중요한 것으로 사용하지 않는 것이 좋다고 말하는 것은 잘못 안내됩니다.
jbtule

1
@Corey 고함을 지르지 않았으며 스택 오버플로 답변의 보안 문제를 다루는 모범 사례를 따랐습니다. 링크를 원하면 질문 의견에 링크가 게시되었습니다. 하지만 난뿐만 아니라 당신을 위해 여기를 놓을 게요 stackoverflow.com/a/10366194/637783
jbtule

12

마크의 변형 (우수) 답변

  • "사용 중"추가
  • 클래스 IDisposable 만들기
  • 예제를 더 간단하게하려면 URL 인코딩 코드를 제거하십시오.
  • 사용법을 보여주기 위해 간단한 테스트 픽스처 추가

도움이 되었기를 바랍니다

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

좋은 답변입니다. Dispose 메서드의 한 가지 방법은 rijndael을 IDisposable로 캐스팅하거나 Dispose를 호출하여 보호 수준 오류를 발생시키는 것입니다
John ClearZ

8
상수 초기화 벡터를 사용하지 마십시오. 이유에 대한 자세한 내용은 crypto.stackexchange.com/questions/66/…을 참조하십시오. 대신, 각 암호화에 대해 새로운 IV를 생성하여 암호화 텍스트에 추가하십시오.
Tom Heard

5
@Chalky 암호화시 Rijndael 클래스를 사용하여 임의 IV를 생성하고 ( msdn.microsoft.com/en-us/library/… ) 암호화 한 다음 IV 속성을 사용하여 Rijndael 인스턴스에서 IV를 가져옵니다. . 그런 다음 암호문에 암호문을 붙입니다 (또는 암호 해독이 같은 쪽에서 가져 오는 한 작동합니다). 해독시 수신 된 데이터에서 IV를 가져오고 (IV 속성의 크기는 8로 나눈 BlockSize 속성과 동일) 해독 전에 해독 인스턴스로 전달합니다.
Tom Heard

2
@Chalky IV는 비밀 일 필요는 없으며 전송 된 각 메시지마다 고유해야합니다.
Tom Heard

20
보안 경고 :이 코드를 사용하지 마십시오 위의 설명 @TomHeard의 설명
jbtule

8

[편집] 몇 년 후, 나는 다시 이렇게 말했습니다 . XOR 암호화의 문제점을 참조하십시오 . 자세한 내용은.

매우 간단하고 쉬운 양방향 암호화는 XOR 암호화입니다.

  1. 비밀번호를 제시하십시오. 하자 mypass.
  2. 비밀번호를 바이너리로 변환하십시오 (ASCII에 따름). 암호는 01101101 01111001 01110000 01100001 01110011 01110011이됩니다.
  3. 인코딩하려는 메시지를 가져옵니다. 또한 이진수로 변환하십시오.
  4. 메시지의 길이를보십시오. 메시지 길이가 400 바이트 인 경우 암호를 반복해서 400 바이트 문자열로 바꾸십시오. 01101101 01111001 01110000 01100001 01110011 01110011 01101101 01111001 01110000 01100001 01110011 01110011 01101101 01111001 01110000 01100001 01110011 01110011 ... (또는 mypassmypassmypass...)
  5. 긴 비밀번호로 메시지를 XOR하십시오.
  6. 결과를 보내십시오.
  7. 또 다른 경우, 동일한 비밀번호 ( mypassmypassmypass...)로 암호화 된 메시지를 XOR하십시오 .
  8. 당신의 메시지가 있습니다!

10
@Ryan 모든 상황에서 암호로 안전한 해시 나 Rijndael 암호가 필요한 것은 아닙니다. "단순 양방향 암호화"는 실제로 단순함을 의미 할 수 있으며, 이는 xor 또는 ROT13을 나타냅니다.

1
@Ryan : 정적 암호화 키, 초기화 벡터 및 블록 체인 기능이없는 AES는 XOR 암호화를위한 멋진 이름입니다.
Hubert Kario

17
보안 경고 : 반복 키가있는 이 코드 XOR 암호화는 사소하게 금이 간 것입니다.
jbtule

7

나는 여러 답변과 의견에서 내가 찾은 것을 결합했습니다.

  • 암호화 텍스트 앞에 붙은 임의의 초기화 벡터 (@jbtule)
  • MemoryStream (@RenniePet) 대신 TransformFinalBlock () 사용
  • 재난을 복사하여 붙여 넣는 사람을 피하기 위해 미리 채워진 키가 없음
  • 적절한 폐기 및 패턴 사용

암호:

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

2015-07-18 업데이트 : @bpsilver 및 @Evereq의 의견으로 개인 Encrypt () 메서드의 실수를 수정했습니다. IV가 실수로 암호화되었으므로 이제 Decrypt ()에서 예상 한대로 일반 텍스트가 앞에 붙습니다.


IV를 앞에 추가하여 전체 inputBuffer를 암호화해야합니다. 그렇지 않으면 문자열-암호화의 첫 16자가 유실됩니다. 따라서 코드는 다음과 같아야합니다.return _encryptor.TransformFinalBlock(inputBuffer, 0, inputBuffer.Length);
bpsilver

2
이 경우 :byte [] inputBuffer = _encryptor.TransformFinalBlock(buffer, 0, buffer.Length); return _rijndael.IV.Concat(inputBuffer).ToArray();
bpsilver

1
그것은 현재 구현과 똑같은 일을 할 것입니까?
angularsen

1
"16, 24 또는 32 문자로 채워주십시오" . 기본 64 디코딩 전에는 안됩니다 . 그리고 키는 임의적이어야합니다. 정말 무작위입니다.
Maarten Bodewes

1
@bpsilver가 맞으며 제공된 코드는 수정없이 작동하지 않습니다. encrypt 메소드는 IV 없이 암호화 된 데이터 반환합니다 (먼저 IV를 입력 버퍼에 추가하지만 다음은 암호화하지 않고 데이터를 암호화하고 반환합니다). 따라서 가능하면 코드로 답변을 업데이트하십시오. (참고 : 문자열이 아닌 byte [] 매개 변수를 사용하는 메서드 만 테스트합니다). 감사!
Evereq

6

간단한 암호화를 원한다면 (즉, 결정된 크래커가 깨질 수 있지만 대부분의 일반 사용자를 잠글 수 있음) 길이가 같은 두 개의 암호를 선택하십시오.

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

두 데이터를 모두 사용하여 데이터를 xor하십시오 (필요한 경우 암호문 반복) (a) . 예를 들면 다음과 같습니다.

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

바이너리를 검색하는 누군가가 DNA 문자열이 핵심이라고 생각할 수도 있지만 C 코드가 바이너리로 저장된 초기화되지 않은 메모리 이외의 다른 것으로 생각하지는 않습니다.


(a) 이것은 매우 간단한 암호화이며, 일부 정의에 따르면 전혀 암호화로 간주되지 않을 수 있습니다 (암호화의 목적은 무단 액세스 를 방지하기 보다는 무단 액세스 를 방지 하기 때문에). 물론 누군가가 강관으로 키홀더 위에 서있을 때는 가장 강력한 암호화조차 안전하지 않습니다.

첫 번째 문장에서 언급했듯이, 이것은 일반 공격자가 공격하기가 충분히 어려워지는 수단입니다. 그것은 집에서 도둑질을 방지하는 것과 비슷합니다-당신이 그것을 불 침투로 만들 필요가 없으며, 옆집 집보다 덜 눈에 띄게 만들어야합니다 :-)


3
재미있는 생각. 바이너리에서 소스 코드를 "믿습니다"라고 확신 할 수 없지만 오류 메시지를 암호 문구로 사용하도록 아이디어를 수정하는 방법은 무엇입니까?
Jon Skeet

1
응용 프로그램에 이미 존재하는 일부 일반 텍스트 문자열의 md5 해시를 사용하는 것이 좋습니다 (오류 메시지 등).
Treb

2
왜 같은 길이 여야합니까? 길이가 다르면 실제로 더 좋아 보입니다. 이렇게하면 효과적인 XOR 피연산자의 길이는 length1 (= length2)이 아니라 LCM (length1, length2)입니다. 길이가 상대적으로 소수이면 길이 1 * 길이 2가됩니다.
Fantius

15
보안 경고 :이 코드를 사용하지 마십시오 반복 키 XOR은 암호화되는 데이터에 대한 일반적인 지식만으로 쉽게 해독 할 수 있습니다.
jbtule

3
@jbtule, 질문을 읽으면 더 안전한 암호화가 필요하지 않다는 것을 알게 될 것입니다. 특히 '간단한 암호화', '미션 크리티컬하지 않은'및 '정직한 사람들을 정직하게 유지'하는 것에 대한 언급. 또한 결정된 공격자를 차단하지 않는다는 사실을 명시 적으로 언급하는 첫 번째 단락도 읽어야합니다.
paxdiablo

5

암호화는 쉽습니다. 다른 사람들이 지적했듯이 System.Security.Cryptography 네임 스페이스에는 모든 작업을 수행하는 클래스가 있습니다. 집에서 만든 솔루션 대신 사용하십시오.

그러나 해독도 쉽습니다. 문제는 암호화 알고리즘이 아니라 암호 해독에 사용되는 키에 대한 액세스를 보호하는 것입니다.

다음 솔루션 중 하나를 사용합니다.

  • CurrentUser 범위와 함께 ProtectedData 클래스를 사용하는 DPAPI 키에 대해 걱정할 필요가 없으므로 쉽습니다. 동일한 사용자 만 데이터를 해독 할 수 있으므로 사용자 또는 컴퓨터간에 데이터를 공유하는 데 적합하지 않습니다.

  • LocalMachine 범위와 함께 ProtectedData 클래스를 사용하는 DPAPI 예를 들어 단일 보안 서버에서 구성 데이터를 보호하는 데 적합합니다. 그러나 컴퓨터에 로그인 할 수있는 사람은 누구나 암호화 할 수 있으므로 서버가 안전하지 않으면 좋지 않습니다.

  • 모든 대칭 알고리즘. 어떤 알고리즘이 사용되는지 상관하지 않으면 일반적으로 정적 SymmetricAlgorithm.Create () 메서드를 사용합니다 (실제로는 기본적으로 Rijndael 임). 이 경우 어떻게 든 키를 보호해야합니다. 예를 들어 어떤 식 으로든 난독 화하고 코드에서 숨길 수 있습니다. 그러나 코드를 디 컴파일 할만큼 똑똑한 사람이라면 누구나 열쇠를 찾을 수있을 것입니다.


5

위의 솔루션 중 어느 것도 내 것만 큼 간단하지 않으므로 솔루션을 게시하고 싶었습니다. 당신이 무슨 생각을하는지 제게 알려주세요:

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

선택 과목

이는 값을 암호화하는 데 사용되는 서버의 MachineKey가 값을 해독하는 데 사용 된 것과 동일하다고 가정합니다. 원하는 경우 응용 프로그램이 데이터의 실행 위치 (예 : 개발 대 프로덕션 서버)에 관계없이 데이터를 해독 / 암호화 할 수 있도록 Web.config에서 정적 MachineKey를 지정할 수 있습니다. 이 지침에 따라 정적 시스템 키를 생성 할 수 있습니다 .


이 방법은 ASP.NET 앱에만 사용할 수 있습니다.
Feru

2

네임 스페이스가 System.Security.Cryptography포함 TripleDESCryptoServiceProvider하고RijndaelManaged 클래스

System.Security어셈블리에 대한 참조를 추가하는 것을 잊지 마십시오 .


8
내가 투표를하지 않았지만 투표 할 때 왜 질문의 나이가 중요합니까?
user247702

2

System.Security.Cryptography 에서 TripleDESCryptoServiceProvider 사용 :

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

나는 변경 :

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

이에:

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

1

기본 제공 .Net Cryptography 라이브러리를 사용하여이 예는 AES (Advanced Encryption Standard)를 사용하는 방법을 보여줍니다.

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

나는 당신이 그것이 얼마나 안전한지 신경 쓰지 않는다고 말했지만, DES 를 선택했다면 AES를 취할 수도 있습니다. 이는 최신 암호화 방법입니다.


0

Mark Brittingham의 대답을 사용하여 많은 도움을 받았습니다 . 최근에 다른 조직에 암호화 된 텍스트를 보내야했으며 여기에서 몇 가지 문제가 발생했습니다. OP에는 이러한 옵션이 필요하지 않지만 이것은 인기있는 질문이므로 수정 사항을 게시 Encrypt하고 Decrypt있습니다. 여기 .

  1. 모든 메시지에 대해 다른 IV-16 진을 얻기 전에 IV 바이트를 암호 바이트로 연결합니다. 물론 이것은 암호문을받는 당사자들에게 전달되어야하는 협약입니다.
  2. 두 개의 생성자를 허용합니다. 하나는 기본입니다. RijndaelManaged 이고 다른 하나는 속성 값을 지정할 수있는 곳입니다 (암호화 및 암호 해독 당사자 간의 상호 동의를 기반으로 함)

다음은 클래스입니다 (마지막에 테스트 샘플).

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

과..

테스트 샘플은 다음과 같습니다.

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

여기에 이미지 설명을 입력하십시오


-2

나는 이것이 세상에서 가장 간단한 것 같아요!

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

테스트

 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

로트 ... 1? 정말? OP는 자신이 원하지 않는 일의 예로 ROT13을 불렀습니다 .
user812786
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.