문제
일부 데이터에 대해 매우 간단한 난독 화 (암호화 및 암호 해독이지만 반드시 안전 할 필요는없는) 기능을 찾고 있습니다. 그것은 미션 비판적이 아닙니다. 정직한 사람들을 정직하게 유지하기 위해 무언가가 필요하지만 rot13 또는 베이스 64.
나는 이미 포함 된 것을 선호합니다 .그물 프레임 워크 2.0이므로 외부 종속성에 대해 걱정할 필요가 없습니다.
나는 정말로 공개/개인 키 등을 엉망으로 만들고 싶지 않습니다. 나는 암호화에 대해 많이 알지 못하지만, 내가 쓴 것이 쓸모없는 것보다 적다는 것을 충분히 알고 있습니다. 나는 아마 수학을 망쳐 놓고 갈라지기가 사소하게 만들었습니다.
해결책
여기서 다른 답변은 잘 작동하지만 AES는보다 안전하고 최신 암호화 알고리즘입니다. 이것은 몇 년 전에 시간이 지남에 따라 웹 애플리케이션에 더 친숙하기 위해 수정 한 AES 암호화를 수행하기 위해 얻은 클래스입니다 (E, G. URL 친화적 인 문자열과 함께 작동하는 암호화/해독 방법을 구축했습니다). 또한 바이트 어레이와 함께 작동하는 메소드도 있습니다.
참고 : 키 (32 바이트) 및 벡터 (16 바이트) 배열에서 다른 값을 사용해야합니다! 이 코드를 사용했다고 가정하여 누군가가 키를 알아내는 것을 원하지 않을 것입니다! 키와 벡터 배열에서 숫자 중 일부 (<= 255 여야 함)를 변경하면 벡터 배열에 하나의 유효하지 않은 값을 남겼습니다. 당신이 사용할 수있는 https://www.random.org/bytes/ 새 세트를 쉽게 생성하려면 :
사용하기 쉬운 경우 : 클래스를 인스턴스화 한 다음 (일반적으로) 암호화 (String StringToenCrypt) 및 decryptString (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;
}
}
다른 팁
나는 내가 사용하기 위해 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();
}
}
예, 추가하십시오 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);
암호화 된 문자열 안에 다시 전달되는 임의의 IV를 추가하여 Mud의 단순함을 개선했다고 덧붙였다. 이렇게하면 동일한 문자열을 암호화하면 매번 다른 출력이 발생하므로 암호화가 향상됩니다.
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");
}
마크의 변형 (우수한) 답변
- "사용"을 추가하십시오
- 클래스를 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();
}
}
}
편집] 몇 년 후, 나는 다시 말했다. 이것을하지 마십시오! 보다 XOR 암호화에 무슨 문제가 있습니까? 자세한 내용은.
매우 간단하고 쉬운 양방향 암호화는 XOR 암호화입니다.
- 비밀번호를 생각해보십시오. 하자
mypass
. - 암호를 바이너리로 변환합니다 (ASCII에 따라). 암호는 01101101 01111001 01110000 01100001 01110011 01110011이됩니다.
- 인코딩하려는 메시지를 가져 오십시오. 이진으로 변환하십시오.
- 메시지의 길이를보십시오. 메시지 길이가 400 바이트 인 경우 암호를 반복해서 반복하여 암호를 400 바이트 문자열로 바꾸십시오. 01101101 01111001 01110000 01100001 01110011 01110011 01101101 01111001 01110000 01100001 01110011 01110011 01101101 01111001 01110000 0110010010011 01110011 ... (또는 또는 또는
mypassmypassmypass...
) - 긴 암호로 메시지를 xor.
- 결과를 보내십시오.
- 또 다른 시간에, 동일한 비밀번호로 암호화 된 메시지를 xor (
mypassmypassmypass...
). - 당신의 메시지가 있습니다!
나는 몇 가지 답과 의견에서 내가 가장 잘 찾은 것을 결합했습니다.
- 임의의 초기화 벡터는 암호화 텍스트 (@JBTULE)로 선정되었습니다.
- MemoryStream (@renniepet) 대신 변형 finalBlock ()을 사용하십시오.
- 재난을 복사하고 붙여 넣는 사람을 피하기 위해 미리 채워진 열쇠 없음
- 적절한 처분 및 패턴 사용
암호:
/// <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의 의견에 따라 개인 암호화 () 메소드의 실수 고정 실수. IV는 실수로 암호화되었으며 이제 Decrypt ()에서 예상대로 명확한 텍스트로 선정되었습니다.
간단한 암호화를 원한다면 (즉, 결정된 크래커가 파손될 수 있지만 대부분의 캐주얼 사용자를 잠그는 경우), 동일한 길이의 두 개의 암호를 선택하십시오.
deoxyribonucleicacid
while (x>0) { x-- };
그리고 두 가지와 함께 데이터를 xor (필요한 경우 암호를 반복하십시오).(ㅏ). 예를 들어:
1111-2222-3333-4444-5555-6666-7777
deoxyribonucleicaciddeoxyribonucle
while (x>0) { x-- };while (x>0) {
이진을 검색하는 사람이 DNA 문자열이 핵심이라고 생각할 수도 있지만 C 코드가 이진과 함께 저장된 비 초기의 메모리가 아닌 다른 것이라고 생각하지는 않습니다.
(ㅏ) 이건 명심하십시오 매우 간단한 암호화 및 일부 정의에 따르면 암호화의 의도는 다음과 같은 암호화로 간주되지 않을 수 있습니다. 예방하다 단순히 어렵게 만드는 것이 아니라 무단 액세스. 물론, 누군가가 강관을 사용하여 키 보유자 위에 서있을 때 가장 강력한 암호화조차도 안전하지 않습니다.
첫 번째 문장에서 언급 한 바와 같이, 이것은 캐주얼 공격자가 계속 움직일 정도로 어려운 수단입니다. 그것은 집에서 도둑질을 막는 것과 비슷합니다 - 당신은 그것을 함침 할 수 없게 만들 필요가 없으며, 옆집에있는 집보다 임신하기 어려운 것만으로도 필요합니다 :-)
암호화는 쉽습니다 : 다른 사람들이 지적했듯이 System.security.Cryptography 네임 스페이스에는 모든 작업을 수행하는 클래스가 있습니다. 집에서 재배 한 솔루션보다는 사용하십시오.
그러나 암호 해독도 쉽습니다. 당신이 가진 문제는 암호화 알고리즘이 아니라 암호 해독에 사용되는 키에 대한 액세스를 보호하는 것입니다.
다음 솔루션 중 하나를 사용합니다.
CurrentUser 범위와 함께 ProtectedData 클래스를 사용하는 DPAPI. 키에 대해 걱정할 필요가 없으므로 쉽습니다. 동일한 사용자가 데이터를 해독 할 수 있으므로 사용자 나 기계간에 데이터를 공유하는 데 적합하지 않습니다.
LocalMachine 범위와 함께 ProtectedData 클래스를 사용하는 DPAPI. 예를 들어 단일 보안 서버에서 구성 데이터를 보호하는 데 좋습니다. 그러나 기계에 로그인 할 수있는 사람은 누구나 암호화 할 수 있으므로 서버가 안전하지 않으면 좋지 않습니다.
모든 대칭 알고리즘. 나는 일반적으로 어떤 알고리즘이 사용되는지 신경 쓰지 않으면 정적 symmetricalgorithm.create () 메소드를 사용합니다 (실제로 기본적으로 Rijndael). 이 경우 어떻게 든 키를 보호해야합니다. 예를 들어 어떤 식 으로든 난독 화하여 코드에 숨길 수 있습니다. 그러나 코드를 디 컴파일하기에 충분히 똑똑한 사람이라면 누구나 키를 찾을 수있을 것입니다.
위의 솔루션 중 어느 것도 내 솔루션이 단순하지 않기 때문에 솔루션을 게시하고 싶었습니다. 당신이 무슨 생각을하는지 제게 알려주세요:
// 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)));
}
선택 과목
이것은 값을 암호화하는 데 사용되는 서버의 기계 키가 값을 해독하는 데 사용되는 것과 동일하다고 가정합니다. 원하는 경우 Web.config에서 정적 머신 키를 지정하여 응용 프로그램이 실행중인 위치 (예 : 개발 대 생산 서버)에 관계없이 데이터를 해독/암호화 할 수 있습니다. 당신은 할 수 있습니다 이 지침에 따라 정적 기계 키를 생성하십시오.
TripledEscryptoserviceProvider를 사용합니다 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);
}
}
네임 스페이스 System.Security.Cryptography
포함 TripleDESCryptoServiceProvider
그리고 RijndaelManaged
클래스
에 대한 참조를 추가하는 것을 잊지 마십시오 System.Security
집회.
나는 바뀌었다 이것:
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;
}
내장 .NET 암호화 라이브러리를 사용 하여이 예제는 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;
}
}
}
나는 수락 된 답을 사용하고있다 마크 브리팅엄 그리고 그것은 저에게 많은 도움이되었습니다. 최근에 나는 암호화 된 텍스트를 다른 조직에 보내야했고 그곳에서 일부 문제가 발생했습니다. OP는 이러한 옵션이 필요하지 않지만 이것은 인기있는 질문이므로 수정을 게시하고 있습니다 (Encrypt
그리고 Decrypt
빌린 기능 여기):
- 모든 메시지에 대해 다른 IV- 육각을 얻기 전에 암호 바이트에 IV 바이트를 연결합니다. 물론 이것은 암호 텍스트를받는 당사자들에게 전달 해야하는 협약입니다.
- 두 개의 생성자 - 하나는 기본값을 허용합니다
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;
}
}
나는 이것이 세계에서 가장 단순한 세계라고 생각합니다!
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