|
@@ -1,6 +1,7 @@
|
|
using System;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
using System.IO;
|
|
|
|
+using System.Security.Cryptography;
|
|
using ArcToolkitCLI.Commands.Options;
|
|
using ArcToolkitCLI.Commands.Options;
|
|
|
|
|
|
namespace ArcToolkitCLI.Util
|
|
namespace ArcToolkitCLI.Util
|
|
@@ -42,5 +43,75 @@ namespace ArcToolkitCLI.Util
|
|
|
|
|
|
return 0;
|
|
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();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
}
|
|
}
|
|
}
|
|
}
|