Simple insecure two-way data “obfuscation”?

后端 未结 17 1381
别跟我提以往
别跟我提以往 2020-11-22 01:10

I\'m looking for very simple obfuscation (like encrypt and decrypt but not necessarily secure) functionality for some data. It\'s not mission critical. I need something to k

相关标签:
17条回答
  • 2020-11-22 01:37

    If you just want simple encryption (i.e., possible for a determined cracker to break, but locking out most casual users), just pick two passphrases of equal length, say:

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

    and xor your data with both of them (looping the passphrases if necessary)(a). For example:

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

    Someone searching your binary may well think the DNA string is a key, but they're unlikely to think the C code is anything other than uninitialized memory saved with your binary.


    (a) Keep in mind this is very simple encryption and, by some definitions, may not be considered encryption at all (since the intent of encryption is to prevent unauthorised access rather than just make it more difficult). Although, of course, even the strongest encryption is insecure when someone's standing over the key-holders with a steel pipe.

    As stated in the first sentence, this is a means to make it difficult enough for the casual attacker that they'll move on. It's similar to preventing burglaries on your home - you don't need to make it impregnable, you just need to make it less pregnable than the house next door :-)

    0 讨论(0)
  • 2020-11-22 01:38

    Yes, add the System.Security assembly, import the System.Security.Cryptography namespace. Here's a simple example of a symmetric (DES) algorithm encryption:

    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);
    
    0 讨论(0)
  • 2020-11-22 01:38

    [EDIT] Years later, I've come back to say: don't do this! See What's wrong with XOR encryption? for details.

    A very simple, easy two-way encrytpion is XOR encryption.

    1. Come up with a password. Let's have it be mypass.
    2. Convert the password into binary (according to ASCII). The password becomes 01101101 01111001 01110000 01100001 01110011 01110011.
    3. Take the message you want to encode. Convert that into binary, also.
    4. Look at the length of the message. If the message length is 400 bytes, turn the password into a 400 byte string by repeating it over and over again. It would become 01101101 01111001 01110000 01100001 01110011 01110011 01101101 01111001 01110000 01100001 01110011 01110011 01101101 01111001 01110000 01100001 01110011 01110011... (or mypassmypassmypass...)
    5. XOR the message with the long password.
    6. Send the result.
    7. Another time, XOR the encrypted message with the same password (mypassmypassmypass...).
    8. There's your message!
    0 讨论(0)
  • 2020-11-22 01:39

    I wanted to post my solution since none of the above the solutions are as simple as mine. Let me know what you think:

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

    Optional

    This assumes that the MachineKey of the server used to encrypt the value is the same as the one used to decrypt the value. If desired, you can specify a static MachineKey in the Web.config so that your application can decrypt/encrypt data regardless of where it is run (e.g. development vs. production server). You can generate a static machine key following these instructions.

    0 讨论(0)
  • 2020-11-22 01:40

    A variant of Marks (excellent) answer

    • Add "using"s
    • Make the class IDisposable
    • Remove the URL encoding code to make the example simpler.
    • Add a simple test fixture to demonstrate usage

    Hope this helps

    [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();
            }
        }
    }
    
    0 讨论(0)
  • 2020-11-22 01:42

    Encryption is easy: as others have pointed out, there are classes in the System.Security.Cryptography namespace that do all the work for you. Use them rather than any home-grown solution.

    But decryption is easy too. The issue you have is not the encryption algorithm, but protecting access to the key used for decryption.

    I would use one of the following solutions:

    • DPAPI using the ProtectedData class with CurrentUser scope. This is easy as you don't need to worry about a key. Data can only be decrypted by the same user, so no good for sharing data between users or machines.

    • DPAPI using the ProtectedData class with LocalMachine scope. Good for e.g. protecting configuration data on a single secure server. But anyone who can log into the machine can encrypt it, so no good unless the server is secure.

    • Any symmetric algorithm. I typically use the static SymmetricAlgorithm.Create() method if I don't care what algorithm is used (in fact it's Rijndael by default). In this case you need to protect your key somehow. E.g. you can obfuscate it in some way and hide it in your code. But be aware that anyone who is smart enough to decompile your code will likely be able to find the key.

    0 讨论(0)
提交回复
热议问题