C#的简单不安全双向“混淆”
我正在为某些数据寻找非常简单的混淆(如加密和解密但不一定是安全的)功能。 这不是关键任务。 我需要一些东西来保持诚实的人诚实,但比ROT13或Base64强一点。
我更喜欢已经包含在.NET framework 2.0中的东西,所以我不必担心任何外部依赖。
我真的不想乱用公钥/私钥等等。我对加密知之甚少,但我知道我写的任何内容都不会毫无价值......事实上,我可能搞砸了数学并且让它变得微不足道。
#1楼
命名空间System.Security.Cryptography
包含TripleDESCryptoServiceProvider
和RijndaelManaged
类
不要忘记添加对System.Security
程序集的引用。
#2楼
是的,添加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);
#3楼
如果你只是想要简单的加密(即,确定的破解者可能会破坏,但锁定大多数临时用户),只需选择两个相等长度的密码,例如:
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)请记住,这是非常简单的加密,并且根据某些定义,可能根本不被视为加密(因为加密的目的是防止未经授权的访问而不仅仅是使其更加困难)。 当然,当有人用钢管架住钥匙扣时,即使最强的加密也是不安全的。
如第一句中所述,这是一种让偶然攻击者难以继续前进的手段。 它类似于防止你家的盗窃 - 你不需要让它变得坚不可摧,你只需要让它比隔壁的房子更难以预防:-)
#4楼
我知道你说你不关心它的安全性,但是如果你选择DES,你可能会选择AES,这是更新的加密方法。
#5楼
加密很容易:正如其他人所指出的那样,System.Security.Cryptography命名空间中有一些类可以为您完成所有工作。 使用它们而不是任何本土解决方案。
但解密也很容易。 您遇到的问题不是加密算法,而是保护对用于解密的密钥的访问。
我会使用以下解决方案之一:
使用带有CurrentUser范围的ProtectedData类的DPAPI。 这很简单,因为您不必担心密钥。 数据只能由同一用户解密,因此无法在用户或计算机之间共享数据。
使用带有LocalMachine范围的ProtectedData类的DPAPI。 适用于保护单个安全服务器上的配置数据。 但是任何可以登录机器的人都可以加密它,所以除非服务器是安全的,否则没有好处。
任何对称算法。 如果我不关心使用什么算法(实际上它默认是Rijndael),我通常使用静态SymmetricAlgorithm.Create()方法。 在这种情况下,您需要以某种方式保护您的密钥。 例如,您可以以某种方式对其进行模糊处理并将其隐藏在代码中。 但请注意,任何聪明到足以反编译代码的人都可能找到密钥。
#6楼
这里的其他答案工作正常,但AES是一种更安全和最新的加密算法。 这是我几年前用来执行AES加密的类,我已经修改了一段时间以便对Web应用程序更友好(例如,我已经构建了使用URL友好字符串的加密/解密方法)。 它还具有与字节数组一起使用的方法。
注意:您应该在Key(32字节)和Vector(16字节)数组中使用不同的值! 您不希望有人通过假设您按原样使用此代码来弄清楚您的密钥! 您所要做的就是更改Key和Vector数组中的一些数字(必须<= 255)(我在Vector数组中保留了一个无效值以确保您执行此操作...)。 您可以使用https://www.random.org/bytes/轻松生成新集:
- 生成
Key
- 生成
Vector
使用它很简单:只需实例化类,然后调用(通常)EncryptToString(string StringToEncrypt)和DecryptString(string StringToDecrypt)作为方法。 一旦你有这个课程,它就不会更容易(或更安全)。
using System;
using System.Data;
using System.Security.Cryptography;
using System.IO;public class SimpleAES
{// Change these keysprivate 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 ciphertextprivate 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 methodRijndaelManaged 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 versaUTFEncoder = 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 vectorstatic public byte[] GenerateEncryptionVector(){//Generate a VectorRijndaelManaged 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 streamCryptoStream cs = new CryptoStream(memoryStream, EncryptorTransform, CryptoStreamMode.Write);cs.Write(bytes, 0, bytes.Length);cs.FlushFinalBlock();#endregion#region Read encrypted value back out of the streammemoryStream.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 methodspublic 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 streamMemoryStream 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();#endregionreturn 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();elsetempStr += val.ToString();}return tempStr;}
}
#7楼
[编辑]多年以后,我回来说: 不要这样做! 看看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 01100001 01110011 01110011 ...(或
mypassmypassmypass...
) - 使用长密码对消息进行异或。
- 发送结果。
- 另一次,XOR加密的消息使用相同的密码(
mypassmypassmypass...
)。 - 有你的消息!
#8楼
只是想我会补充一点,我通过添加一个随机的IV来改进Mud的SimplerAES,这个随机的IV被传回加密的字符串。 这改进了加密,因为加密相同的字符串每次都会导致不同的输出。
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()
{// Arrangevar subject = new StringEncryption();var originalString = "Testing123!£$";// Actvar encryptedString1 = subject.Encrypt(originalString);var encryptedString2 = subject.Encrypt(originalString);var decryptedString1 = subject.Decrypt(encryptedString1);var decryptedString2 = subject.Decrypt(encryptedString2);// AssertAssert.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");
}
#9楼
我从几个答案和评论中结合了我发现的最好的东西。
- 随机初始化向量前置加密文本(@jbtule)
- 使用TransformFinalBlock()而不是MemoryStream(@RenniePet)
- 没有预先填写的密钥,以避免任何人复制和粘贴灾难
- 正确处置和使用模式
码:
/// <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 cryptotextbyte[] 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 IVbyte [] inputBuffer = _encryptor.TransformFinalBlock(buffer, 0, buffer.Length); return _rijndael.IV.Concat(inputBuffer).ToArray();}
}
更新2015-07-18:通过@bpsilver和@Evereq的注释修复了私有Encrypt()方法中的错误。 IV被意外加密,现在以Decrypt()预期的明文前缀。
#10楼
我认为这是世界上最简单的一个!
string encrypted = "Text".Aggregate("", (c, a) => c + (char) (a + 2));
测试
Console.WriteLine(("Hello").Aggregate("", (c, a) => c + (char) (a + 1)));//Output is IfmmpConsole.WriteLine(("Ifmmp").Aggregate("", (c, a) => c + (char)(a - 1)));//Output is Hello
#11楼
我想发布我的解决方案,因为上述解决方案都不像我的那么简单。 让我知道你的想法:
// This will return an encrypted string based on the unencrypted parameterpublic static string Encrypt(this string DecryptedValue){HttpServerUtility.UrlTokenEncode(MachineKey.Protect(Encoding.UTF8.GetBytes(DecryptedValue.Trim())));}// This will return an unencrypted string based on the parameterpublic static string Decrypt(this string EncryptedValue){Encoding.UTF8.GetString(MachineKey.Unprotect(HttpServerUtility.UrlTokenDecode(EncryptedValue)));}
可选的
这假定用于加密该值的服务器的MachineKey与用于解密该值的服务器的MachineKey相同。 如果需要,您可以在Web.config中指定静态MachineKey,以便您的应用程序可以解密/加密数据,无论数据在何处运行(例如开发与生产服务器)。 您可以按照这些说明生成静态机器密钥 。
#12楼
使用内置的.Net Cryptography库,此示例显示了如何使用高级加密标准(AES)。
using System;
using System.IO;
using System.Security.Cryptography;namespace Aes_Example
{class AesExample{public static void Main(){try{string original = "Here is some data to encrypt!";// Create a new instance of the Aes// class. This generates a new key and initialization // vector (IV).using (Aes myAes = Aes.Create()){// Encrypt the string to an array of bytes.byte[] encrypted = EncryptStringToBytes_Aes(original, myAes.Key, myAes.IV);// Decrypt the bytes to a string.string roundtrip = DecryptStringFromBytes_Aes(encrypted, myAes.Key, myAes.IV);//Display the original data and the decrypted data.Console.WriteLine("Original: {0}", original);Console.WriteLine("Round Trip: {0}", roundtrip);}}catch (Exception e){Console.WriteLine("Error: {0}", e.Message);}}static byte[] EncryptStringToBytes_Aes(string plainText, byte[] Key,byte[] IV){// Check arguments.if (plainText == null || plainText.Length <= 0)throw new ArgumentNullException("plainText");if (Key == null || Key.Length <= 0)throw new ArgumentNullException("Key");if (IV == null || IV.Length <= 0)throw new ArgumentNullException("Key");byte[] encrypted;// Create an Aes object// with the specified key and IV.using (Aes aesAlg = Aes.Create()){aesAlg.Key = Key;aesAlg.IV = IV;// Create a decrytor to perform the stream transform.ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV);// Create the streams used for encryption.using (MemoryStream msEncrypt = new MemoryStream()){using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)){using (StreamWriter swEncrypt = new StreamWriter(csEncrypt)){//Write all data to the stream.swEncrypt.Write(plainText);}encrypted = msEncrypt.ToArray();}}}// Return the encrypted bytes from the memory stream.return encrypted;}static string DecryptStringFromBytes_Aes(byte[] cipherText, byte[] Key, byte[] IV){// Check arguments.if (cipherText == null || cipherText.Length <= 0)throw new ArgumentNullException("cipherText");if (Key == null || Key.Length <= 0)throw new ArgumentNullException("Key");if (IV == null || IV.Length <= 0)throw new ArgumentNullException("Key");// Declare the string used to hold// the decrypted text.string plaintext = null;// Create an Aes object// with the specified key and IV.using (Aes aesAlg = Aes.Create()){aesAlg.Key = Key;aesAlg.IV = IV;// Create a decrytor to perform the stream transform.ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV);// Create the streams used for decryption.using (MemoryStream msDecrypt = new MemoryStream(cipherText)){using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)){using (StreamReader srDecrypt = new StreamReader(csDecrypt)){// Read the decrypted bytes from the decrypting stream// and place them in a string.plaintext = srDecrypt.ReadToEnd();}}}}return plaintext;}}
}
#13楼
我一直在使用Mark Brittingham接受的答案,它给了我很多帮助。 最近我不得不将加密文本发送到另一个组织,这就是出现问题的地方。 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 Vectorrijn.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!";//encryptstring hex = p.Encrypt(plainText);//decryptstring 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 sidebyte[] 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 ciphertexthex = 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 urlbyte[] 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;}
}
#14楼
在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);}
}
#15楼
我改变了这个 :
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();elsetempStr += val.ToString();}return tempStr;
}
对此:
public string ByteArrToString(byte[] byteArr){string temp = "";foreach (byte b in byteArr)temp += b.ToString().PadLeft(3, '0');return temp;}
#16楼
我清理了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 ciphertextprivate 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();}
}
#17楼
Marks(优秀)答案的变体
- 添加“使用”s
- 使类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();}}
}
C#的简单不安全双向“混淆”相关推荐
- SurfaceView简单理解,Android混淆,Android openGl开发详解简单图形的绘制,
SurfaceView允许你在非ui线程中去绘制. SurfaceView的帧率可以操作60FPS 在要求实时性比较高的游戏开发中,显然,view的ondraw是满足不了你的,这时候只能是用Surfa ...
- 实现简单的带头双向循环链表
双向链表 1. 带头双向循环链表的定义 2. 带头双向循环链表的创建 3. 带头双向循环链表的增删改查 (1)头插头删 (2)尾插尾删 (3)pos位置的前插与删除 4.插入与删除改良 1. 带头双向 ...
- 用JS简单实现Vue的双向绑定
Vue实现数据双向绑定原理: 采用数据劫持结合发布者-订阅者模式的方式,通过 Object.defineProperty() 来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者, ...
- 混淆工具Dotfuscator基本使用
Dotfuscator是dnet程序混淆工具:混淆,就是搞乱代码,代码功能完全不变:这样反汇编以后难以阅读:以保护自己的知识产权: 此工具是微软提供的:可以从VS安装:也可以单独下安装包: 安装完: ...
- ASP.NET Core 3.0 gRPC 双向流
目录 ASP.NET Core 3.0 使用gRPC ASP.NET Core 3.0 gRPC 双向流 ASP.NET Core 3.0 gRPC 认证授权 一.前言 在前一文 < 二. 什么 ...
- “约见”面试官系列之常见面试题第九篇vue实现双向绑定原理(建议收藏)
目录 1.原理 2.实现 在目前的前端面试中,vue的双向数据绑定已经成为了一个非常容易考到的点,即使不能当场写出来,至少也要能说出原理.本篇文章中我将会仿照vue写一个双向数据绑定的实例,名字就叫m ...
- Android代码混淆方法,Android 代码混淆零基础入门
内容提要 本篇文章主要有三个部分,让读者读完后能自己写规则混淆项目 对Android代码怎么开启混淆做一个简单的介绍. 对混淆规则做一个简单介绍: 在混淆过后Crash日志反推代码工具retrace. ...
- c语言一次绑定多个控件,一入前端深似海,从此红尘是路人系列第九弹之如何实现一个双向数据绑定...
前言 简单介绍一下双向数据绑定实现的是一个什么样的东西.首先有两个东西,他们分别是: V-视图层 M-数据层 1.视图层传向数据层:V发生改变,M也发生改变 2.数据层传向视图层:M发生改变,V也发生 ...
- *oulapp的双向证书破解
*oulapp的双向证书破解 今天简单说一下双向证书的破解,顺便说一个比较好用的工具,案例: c291bA== 破解双向证书: 之前见过单向证书校验,比如企查查.饿了么等,这个最简单的方法就是使用Ju ...
最新文章
- Ajax的进阶学习(一)
- oracle数据库备份方法主要有哪几种,Oracle数据库备份方法有哪三种?
- SuperEdge — Overview
- 她说要介绍10000个开源项目?来!我们一起监督!
- [hdu5266]区间LCA
- yii2 mysql like_Yii2实现跨mysql数据库关联查询排序功能
- 一直在构建版本_球鞋 | 一鞋两穿?AJ1十孔版本登场,拉链设计还是真香了?
- C++求字符串长度的两种方法
- Linux的奖励机制是啥意思,Linux能力(capability)机制的继承
- poj-3185-开关问题
- 【BIT2021程设】2. 解谜游戏——初见DFS
- ubuntu/deepin安装配置mysql
- 再见,百度网盘!新 60MB/s!
- 盘点8个高效方法提高睾酮水平
- win7计算机管理无用户账户,win7系统控制面板中用户账户显示空白的解决方法
- 服务器维护10月11魔兽,魔兽世界怀旧服10月11日免费转服第五期开启公告 免费转服详情...
- react native 的button点击变色以及禁用问题
- 刚刚,数学界“诺奖”Abel Prize迎来首位女性得主
- Hibernate学习(一)
- Java修真之练气筑基篇(持续更新)
热门文章
- 操作系统就是一个“死循环”?
- 【Android】Service几个重要的方法运行在哪个线程
- java同步机制:synchronized
- 用户月活跃度在哪里可以查_2020年12月计算机等级考试报名时间,另外11月6号可以查9月考试成绩...
- SwiftUI 发展现状和学习指南
- Foundation框架介绍
- vmware-tools安装说明
- 使用PHPStorm 配置自定义的Apache与PHP环境
- 20165224 陆艺杰 网络攻防 实验1
- 2018-2019-1 20165305 实验三 实时系统