Simple insecure two-way data “obfuscation”?

后端 未结 17 1370
别跟我提以往
别跟我提以往 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:42

    I've been using the accepted answer by Mark Brittingham and its has helped me a lot. Recently I had to send encrypted text to a different organization and that's where some issues came up. The OP does not require these options but since this is a popular question I'm posting my modification (Encrypt and Decrypt functions borrowed from here):

    1. Different IV for every message - Concatenates IV bytes to the cipher bytes before obtaining the hex. Of course this is a convention that needs to be conveyed to the parties receiving the cipher text.
    2. Allows two constructors - one for default RijndaelManaged values, and one where property values can be specified (based on mutual agreement between encrypting and decrypting parties)

    Here is the class (test sample at the end):

    /// 
    /// 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
    /// 
    public class AnotherAES : IDisposable
    {
        private RijndaelManaged rijn;
    
        /// 
        /// Initialize algo with key, block size, key size, padding mode and cipher mode to be known.
        /// 
        /// ASCII key to be used for encryption or decryption
        /// block size to use for AES algorithm. 128, 192 or 256 bits
        /// key length to use for AES algorithm. 128, 192, or 256 bits
        /// 
        /// 
        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;
        }
    
        /// 
        /// 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
        /// 
        /// 
        public AnotherAES(string key)
        {
            rijn = new RijndaelManaged();
            byte[] keyArray = Encoding.UTF8.GetBytes(key);
            rijn.Key = keyArray;
        }
    
        /// 
        /// Based on https://msdn.microsoft.com/en-us/library/system.security.cryptography.rijndaelmanaged(v=vs.110).aspx
        /// Encrypt a string using RijndaelManaged encryptor.
        /// 
        /// string to be encrypted
        /// initialization vector to be used by crypto algorithm
        /// 
        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
    
        /// 
        /// Based on https://msdn.microsoft.com/en-us/library/system.security.cryptography.rijndaelmanaged(v=vs.110).aspx
        /// 
        /// bytes to be decrypted back to plaintext
        /// initialization vector used to encrypt the bytes
        /// 
        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
    
        /// 
        /// Generates a unique encryption vector using RijndaelManaged.GenerateIV() method
        /// 
        /// 
        public byte[] GenerateEncryptionVector()
        {
            if (rijn == null)
                throw new ArgumentNullException("Provider not initialized");
    
            //Generate a Vector
            rijn.GenerateIV();
            return rijn.IV;
        }//end GenerateEncryptionVector
    
    
        /// 
        /// 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.
        /// 
        /// 
        /// 
        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()
    
        /// 
        /// Converts a string to byte array. Useful when converting back hex string which was originally formed from bytes.
        /// 
        /// 
        /// 
        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
    
        /// 
        /// Dispose RijndaelManaged object initialized in the constructor
        /// 
        public void Dispose()
        {
            if (rijn != null)
                rijn.Dispose();
        }//end Dispose()
    }//end class
    

    and..

    Here is the test sample:

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

提交回复
热议问题