当前位置:  开发笔记 > 编程语言 > 正文

C#的简单不安全双向"混淆"

如何解决《C#的简单不安全双向"混淆"》经验,为你挑选了10个好方法。

我正在为某些数据寻找非常简单的混淆(如加密和解密但不一定是安全的)功能.这不是关键任务.我需要一些东西来保持诚实的人诚实,但比ROT13或Base64强一点.

我更喜欢已经包含在.NET framework 2.0中的东西,所以我不必担心任何外部依赖.

我真的不想乱用公钥/私钥等等.我对加密知之甚少,但我知道我写的任何东西都不会毫无价值......事实上,我可能搞砸了数学并且让它变得微不足道.



1> Mark Brittin..:

这里的其他答案工作正常,但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 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;
    }
}


**安全警告:不要使用此代码**尽管是公认的答案,但上述评论中提到严重的安全问题,提交人已连续8年忽视.
@AndyMcKenna - 这是有目的地完成的,因此您可以更改数组中的值,正如Mark在第二段中所述.
你不应该像这样使用IV.对于给定的两条消息,它们不应该使用相同的密钥和相同的IV加密.对于每个消息,IV应该是随机的,前置于cryptuffream,并在解密之前读出.http://crypto.stackexchange.com/a/82/1934
对每条消息使用随机IV不是异国情调或新的,只是算法的重要和部分设计.对每条消息使用可预测的IV是一个常见的加密错误,不需要长期存在.
另请注意,使用CBC作为其模式的结果是您可能容易受到[填充oracle攻击](http://www.skullsecurity.org/blog/2013/a-padding-oracle-example).使用经过身份验证的加密,并且只要有可能,*不要自己实施加密*.
转换为base 64然后URL编码将导致更少的代码和更紧凑的输出.
不要使用常数IV.请不要告诉人们这样做,你破坏了加密算法的安全功能.没有理由不能为每个加密生成新的IV并将其附加到您的cryptotext.
`using`警察(那不是我)可能会在你之后使用一些流
Pauk是对的.你真的不应该使用代码中显示的键.把它们变成你自己的.用"坏"键,你别无选择;-)
@DomenicDatti - 这不是错误.如果您阅读了评论,您会看到我故意这样做,以便人们不仅使用示例中显示的键值.
@jbtule - 这就是为什么我包含了"GenerateEncryptionVector"函数 - 所以你可以在需要最大安全性的环境中这样做.但是,在大多数商业加密设置中,这有点过分.当然,随着时间的推移,由于开发人员与利用信息系统的人之间的简单军备竞赛,在安全方式上往往变得更加异乎寻常的东西逐渐成为标准.
IV每次都应该是不同的1)所以如果你多次加密同一个消息,它会给你不同的结果(类似于盐)2)因为如果你重复使用IV,一些算法会发生灾难性的失败
马克,你不应该在你的答案中使用像"上面"这样的单词,因为答案会相互关联.事实上,在投票顺序中唯一超出这个答案的是问题.
很好 - 请注意,您可以使用Convert.ToBase64String和Convert.FromBase64String在EncryptString和DecryptString方法中获得更紧凑的字符串表示形式(而不是您的手动StrToByteArray和ByteArrayToStr方法)
我发现了问题。加密和解密方法不是线程安全的。我添加了代码以使其线程安全并且没有更多错误。为进一步参考,这是我遇到的错误:复制内存时检测到可能的I / O竞争状况。默认情况下,I / O包不是线程安全的。在多线程应用程序中,必须以线程安全的方式访问流,例如TextReader或TextWriter的返回的线程安全包装器。
@TankorSmash这是一个[初始化载体](https://en.wikipedia.org/wiki/Initialization_vector).这是一个非秘密值,每个消息必须是不同的(CBC模式,在这个答案中使用,要求它是不可预测的随机,其他模式只需要唯一性).这个答案选择一个固定的值,完全没有IV的要点.
为什么这里有这么多关于答案不安全的评论?并非每种加密都必须非常安全。OP要求简单的不安全加密。也许安全性并不重要。只是文本乱码而不是Base64编码就可以了。

2> Mud..:

我清理了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();
    }
}


**安全警告:不要使用此代码**请参阅@TomHeard的评论
不要使用常量初始化向量,请参阅:http://crypto.stackexchange.com/questions/66/what-are-the-details-of-the-des-weakness-of-reusing-the-same-iv -in-cbc-mode-with/82#82有关原因的更多信息.相反,为每个加密生成一个新的IV并将其附加到cryptotext,这样更好,而不是很难.
@TomHeard用上面的代码怎么做呢?
解码时,我不得不用+替换空格,以便在Chrome中使用QueryString :( new SimplerAES()).解密(Request.QueryString ["myParam"].替换('','+'));
请注意,当用作URL路径(不是查询字符串)的一部分时,此解决方案中的EncryptToUrl方法的输出(或一般使用UrlEncoded base 64字符串)在IIS 7下默认不起作用,如由于IIS 7安全设置,ASP.NET MVC路由.有关更多信息,请参阅:http://stackoverflow.com/a/2014121/12484

3> ZeroBugBounc..:

是的,添加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);


**安全警告:请勿使用本准则**请参阅@HubertKario的评论
@MarkBrittingham:任何没有块链接功能的块密码,初始化向量和适当的填充都是不安全的.使用DES是此方案中最不重要的问题.
这是一个不错的,紧凑的双向加密.唯一需要注意的是,DES不再被认为是最先进的安全措施.该标题现在转到我在下面讨论的AES算法.
那么密钥在哪里使用?

4> Brainfloat..:

只是想我会补充一点,我通过添加一个随机的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()
{
    // 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");
}


**安全警告:请勿使用此代码**请参阅@CodesInChaos的上述评论
1)不要将`System.Random`用作RNG.2)这完全打破了选择密文攻击(特别是填充 - 神谕)

5> Simon..:

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


**安全警告:请勿使用此代码**请参阅上述@TomHeard的评论
不要使用常量初始化向量,请参阅:crypto.stackexchange.com/questions/66/...以获取有关原因的更多信息.相反,为每个加密生成一个新的IV并将其附加到cryptotext,这样更好,而不是很难.
@Chalky在加密时,您使用Rijndael类为您生成随机IV(http://msdn.microsoft.com/en-us/library/system.security.cryptography.symmetricalgorithm.generateiv(v=vs.110) .aspx),进行加密,然后使用IV属性从Rijndael实例中获取IV.然后,您可以将前缀(或附加,只要您的解密从同一侧抓取它就可以工作)到您的加密文本.在解密时,然后从接收的数据中提取IV(IV属性的大小与BlockSize属性的大小除以8),然后在解密之前将其传递给解密实例.
@Chalky请注意,IV不需要保密,它只需要对发送的每条消息都是唯一的.

6> stalepretzel..:

[编辑]多年以后,我回来说:不要这样做! 看看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...).

    有你的消息!


**安全警告:不使用此代码**带有重复键的XOR加密很容易被破解.
@Ryan并非所有情况都需要加密安全哈希或Rijndael密码."简单的双向加密"实际上可能意味着*简单*,这表明xor甚至ROT13.
异或 - 说真的?

7> angularsen..:

我从几个答案和评论中结合了我发现的最好的东西.

随机初始化向量前置加密文本(@jbtule)

使用TransformFinalBlock()而不是MemoryStream(@RenniePet)

没有预先填写的密钥,以避免任何人复制和粘贴灾难

正确处置和使用模式

码:

/// 
/// Simple encryption/decryption using a random initialization vector
/// and prepending it to the crypto text.
/// 
/// Based on multiple answers in http://stackoverflow.com/questions/165808/simple-two-way-encryption-for-c-sharp 
public class SimpleAes : IDisposable
{
    /// 
    ///     Initialization vector length in bytes.
    /// 
    private const int IvBytes = 16;

    /// 
    ///     Must be exactly 16, 24 or 32 bytes long.
    /// 
    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()预期的明文前缀.


在这种情况下:`byte [] inputBuffer = _encryptor.TransformFinalBlock(buffer,0,buffer.Length); return _rijndael.IV.Concat(inputBuffer).ToArray();`

8> paxdiablo..:

如果你只是想要简单的加密(即,确定的破解者可能会破坏,但锁定大多数临时用户),只需选择两个相等长度的密码,例如:

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)请记住,这是非常简单的加密,并且根据某些定义,可能根本不被视为加密(因为加密的目的是为了防止未经授权的访问,而不仅仅是使其更加困难).当然,当有人用钢管架住钥匙扣时,即使最强的加密也是不安全的.

如第一句中所述,这是一种让偶然攻击者难以继续前进的手段.它类似于防止你家的盗窃 - 你不需要让它变得坚不可摧,你只需要让它比隔壁的房子更难以预防:-)


**安全警告:不要使用此代码**只需对加密数据的一般知识,重复密钥XOR就很容易破解.
有趣的想法.我不确定我是否"相信"二进制文件中的源代码 - 但是如何调整这个想法以使用错误消息作为密码呢?
@jbtule,如果您已经阅读了这个问题,您就会意识到不需要更安全的加密.特别提到"简单加密","不是关键任务",只是"保持诚实的人诚实".你还应该阅读我的第一段,它明确指出它不会锁定坚定的攻击者.
为什么他们需要长度相等?如果长度不同,实际上似乎更好.这样,有效XOR操作数的长度是LCM(length1,length2),而不仅仅是length1(= length2).如果长度相对为素数,那当然变成长度1*长度2.

9> Joe..:

加密很容易:正如其他人指出的那样,System.Security.Cryptography命名空间中有一些类可以为您完成所有工作。使用它们而不是任何本地解决方案。

但是解密也很容易。您遇到的问题不是加密算法,而是保护对用于解密的密钥的访问。

我将使用以下解决方案之一:

DPAPI将ProtectedData类与CurrentUser范围一起使用。这很容易,因为您无需担心密钥。数据只能由同一用户解密,因此不利于用户或计算机之间共享数据。

DPAPI将ProtectedData类与LocalMachine范围一起使用。有益于例如保护单个安全服务器上的配置数据。但是任何可以登录计算机的人都可以对其进行加密,因此,除非服务器是安全的,否则效果不佳。

任何对称算法。如果我不在乎使用哪种算法,我通常会使用静态SymmetricAlgorithm.Create()方法(事实上,默认情况下是Rijndael)。在这种情况下,您需要以某种方式保护您的钥匙。例如,您可以通过某种方式对其进行混淆,并将其隐藏在代码中。但是请注意,只要有足够的能力来反编译您的代码的人都可以找到密钥。



10> William..:

我想发布我的解决方案,因为上述解决方案都不像我的那么简单.让我知道你的想法:

 // 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与用于解密该值的服务器的MachineKey相同.如果需要,您可以在Web.config中指定静态MachineKey,以便您的应用程序可以解密/加密数据,无论数据在何处运行(例如开发与生产服务器).您可以按照这些说明生成静态机器密钥.

推荐阅读
帆侮听我悄悄说星星
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有