C# 简单不安全的双向数据”;混淆;?
我正在寻找一些数据的非常简单的模糊处理(如加密和解密,但不一定是安全的)功能。这不是关键任务。我需要一些能让诚实的人保持诚实的东西,但要比或强一点 我更喜欢框架2.0中已经包含的东西,所以我不必担心任何外部依赖C# 简单不安全的双向数据”;混淆;?,c#,obfuscation,C#,Obfuscation,我正在寻找一些数据的非常简单的模糊处理(如加密和解密,但不一定是安全的)功能。这不是关键任务。我需要一些能让诚实的人保持诚实的东西,但要比或强一点 我更喜欢框架2.0中已经包含的东西,所以我不必担心任何外部依赖 我真的不想乱搞公钥/私钥等。我对加密知之甚少,但我知道我写的任何东西都毫无价值。。。事实上,我可能会把数学搞砸,让它变得微不足道。名称空间System.Security.Cryptography包含TripledScryptoServiceProvider和RijndaelManaged
我真的不想乱搞公钥/私钥等。我对加密知之甚少,但我知道我写的任何东西都毫无价值。。。事实上,我可能会把数学搞砸,让它变得微不足道。名称空间
System.Security.Cryptography
包含TripledScryptoServiceProvider
和RijndaelManaged
类
不要忘记添加对
System.Security
程序集的引用。是的,添加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);
如果您只需要简单的加密(即,一个确定的破解程序可能会被破解,但会锁定大多数临时用户),只需选择两个长度相等的密码,比如:
deoxyribonucleicacid
while (x>0) { x-- };
并将您的数据与它们进行异或(必要时循环密码短语)(a)。例如:
1111-2222-3333-4444-5555-6666-7777
deoxyribonucleicaciddeoxyribonucle
while (x>0) { x-- };while (x>0) {
搜索二进制文件的人可能会认为DNA字符串是一个键,但他们不太可能认为C代码不是二进制文件保存的未初始化内存
(a) 请记住,这是一种非常简单的加密,根据某些定义,可能根本不被视为加密(因为加密的目的是防止未经授权的访问,而不仅仅是增加访问的难度)。当然,当有人拿着钢管站在密钥持有者上方时,即使是最强大的加密也是不安全的
如第一句所述,这是一种使偶然的攻击者难以继续前进的手段。这类似于防止你家的入室盗窃-你不需要让它牢不可破,你只需要让它比隔壁的房子更不容易怀孕:-)我知道你说过你不在乎它有多安全,但是,如果您选择了,您也可以采用更为最新的加密方法。加密很简单:正如其他人所指出的,System.Security.Cryptography命名空间中的类为您完成了所有工作。使用它们,而不是任何国产解决方案 但解密也很容易。您遇到的问题不是加密算法,而是保护对用于解密的密钥的访问 我将使用以下解决方案之一:
- DPAPI使用具有CurrentUser作用域的ProtectedData类。这很容易,因为您不需要担心钥匙。数据只能由同一用户解密,因此不利于在用户或机器之间共享数据
- DPAPI使用具有LocalMachine作用域的ProtectedData类。适用于保护单个安全服务器上的配置数据。但是任何可以登录到这台机器的人都可以对它进行加密,因此,除非服务器是安全的,否则没有任何好处
- 任何对称算法。如果我不在乎使用什么算法(事实上,默认情况下它是Rijndael),我通常会使用静态Symmetrialgorithm.Create()方法。在这种情况下,您需要以某种方式保护您的密钥。例如,您可以以某种方式混淆它,并将其隐藏在代码中。但是请注意,任何足够聪明的人,只要能够反编译您的代码,都有可能找到密钥
注意:您应该在键(32字节)和向量(16字节)数组中使用不同的值!你不会希望有人通过假设你按原样使用这段代码来找出你的密钥!您所要做的就是更改一些数字(必须是[EDIT]年后,我回来告诉您:不要这样做!有关详细信息,请参阅 一个非常简单、简单的双向加密是XOR加密
mypass
mypassmypass…
)mypassmypass…
)。johnsmith@gmail.com
产生:
SimpleAES: "096114178117140150104121138042115022037019164188092040214235183167012211175176167001017163166152"
SimplerAES: "YHKydYyWaHmKKnMWJROkvFwo1uu3pwzTr7CnARGjppg%3d"
代码:
分数的变体(优秀)答案
- 添加“使用”s
- 使类IDisposable
- 删除URL编码代码以简化示例
- 将一个简单的测试夹具添加到
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; }
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(); } }
[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(); } } }
/// <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(); } }
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
// 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))); }
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; } } }
/// <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; } }
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); } }