|  | @@ -1,6 +1,7 @@
 | 
	
		
			
				|  |  |  using System;
 | 
	
		
			
				|  |  |  using System.Collections.Generic;
 | 
	
		
			
				|  |  |  using System.IO;
 | 
	
		
			
				|  |  | +using System.Security.Cryptography;
 | 
	
		
			
				|  |  |  using ArcToolkitCLI.Commands.Options;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  namespace ArcToolkitCLI.Util
 | 
	
	
		
			
				|  | @@ -42,5 +43,75 @@ namespace ArcToolkitCLI.Util
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |              return 0;
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        public static byte[] GenerateIV(byte[] ivSeed)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            uint[] seed = { 0x075BCD15, 0x159A55E5, 0x1F123BB5, BitConverter.ToUInt32(ivSeed, 1) ^ 0xBFBFBFBF };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            for (int i = 0; i < 4; i++)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                uint n = seed[0] ^ (seed[0] << 11);
 | 
	
		
			
				|  |  | +                seed[0] = seed[1];
 | 
	
		
			
				|  |  | +                seed[1] = seed[2];
 | 
	
		
			
				|  |  | +                seed[2] = seed[3];
 | 
	
		
			
				|  |  | +                seed[3] = n ^ seed[3] ^ ((n ^ (seed[3] >> 11)) >> 8);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            var output = new byte[16];
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            Buffer.BlockCopy(seed, 0, output, 0, 16);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            return output;
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        public static byte[] DecryptBytes(byte[] encryptedBytes, byte[] key)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            var ivSeed = new byte[5];
 | 
	
		
			
				|  |  | +            Array.Copy(encryptedBytes, encryptedBytes.Length - 5, ivSeed, 0, 5);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            byte[] iv = GenerateIV(ivSeed);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            using (var rijndael = new RijndaelManaged())
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                rijndael.Padding = PaddingMode.None;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                using (ICryptoTransform decryptor = rijndael.CreateDecryptor(key, iv))
 | 
	
		
			
				|  |  | +                using (var mem = new MemoryStream(encryptedBytes, 0, encryptedBytes.Length - 5))
 | 
	
		
			
				|  |  | +                using (var stream = new CryptoStream(mem, decryptor, CryptoStreamMode.Read))
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    var output = new byte[encryptedBytes.Length - 5];
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                    stream.Read(output, 0, output.Length);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                    return output;
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        public static byte[] EncryptBytes(byte[] data, byte[] key, byte[] ivSeed, byte[] extraData = null)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            if(extraData?.Length > 255)
 | 
	
		
			
				|  |  | +                throw new ArgumentException("Extra data cannot be larger than 255 bytes!", nameof(extraData));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            byte[] iv = GenerateIV(ivSeed);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            using (var rijndael = new RijndaelManaged())
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                rijndael.Padding = PaddingMode.None;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                using (ICryptoTransform encryptor = rijndael.CreateEncryptor(key, iv))
 | 
	
		
			
				|  |  | +                using (var mem = new MemoryStream())
 | 
	
		
			
				|  |  | +                {
 | 
	
		
			
				|  |  | +                    using (var stream = new CryptoStream(mem, encryptor, CryptoStreamMode.Write))
 | 
	
		
			
				|  |  | +                        stream.Write(data, 0, data.Length);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                    byte extraLength = (byte) (extraData?.Length ?? 0);
 | 
	
		
			
				|  |  | +                    mem.Write(new []{ (byte)(extraLength ^ ivSeed[0])}, 0, 1);
 | 
	
		
			
				|  |  | +                    mem.Write(ivSeed, 0, ivSeed.Length);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                    return mem.ToArray();
 | 
	
		
			
				|  |  | +                }
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  }
 |