|
@@ -8,7 +8,7 @@ namespace ArcToolkitCLI.Util
|
|
|
{
|
|
|
public static class Encryption
|
|
|
{
|
|
|
- private static Random Random = new Random();
|
|
|
+ private static readonly Random Random = new Random();
|
|
|
|
|
|
public static byte[] ReadKeyFromFile(string filename)
|
|
|
{
|
|
@@ -48,11 +48,11 @@ namespace ArcToolkitCLI.Util
|
|
|
|
|
|
public static byte[] GenerateIV(byte[] ivSeed)
|
|
|
{
|
|
|
- uint[] seed = { 0x075BCD15, 0x159A55E5, 0x1F123BB5, BitConverter.ToUInt32(ivSeed, 0) ^ 0xBFBFBFBF };
|
|
|
+ uint[] seed = {0x075BCD15, 0x159A55E5, 0x1F123BB5, BitConverter.ToUInt32(ivSeed, 0) ^ 0xBFBFBFBF};
|
|
|
|
|
|
- for (int i = 0; i < 4; i++)
|
|
|
+ for (var i = 0; i < 4; i++)
|
|
|
{
|
|
|
- uint n = seed[0] ^ (seed[0] << 11);
|
|
|
+ var n = seed[0] ^ (seed[0] << 11);
|
|
|
seed[0] = seed[1];
|
|
|
seed[1] = seed[2];
|
|
|
seed[2] = seed[3];
|
|
@@ -72,14 +72,14 @@ namespace ArcToolkitCLI.Util
|
|
|
var ivSeed = new byte[4];
|
|
|
Array.Copy(encryptedBytes, encryptedBytes.Length - 4, ivSeed, 0, 4);
|
|
|
|
|
|
- byte[] iv = GenerateIV(ivSeed);
|
|
|
+ var 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 - extraDataSize - 5))
|
|
|
+ using (var 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 - extraDataSize - 5];
|
|
@@ -91,30 +91,38 @@ namespace ArcToolkitCLI.Util
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- public static byte[] EncryptBytes(byte[] data, byte[] key, byte[] ivSeed = null, byte[] extraData = null)
|
|
|
+ public static byte[] EncryptBytes(byte[] data, byte[] key, byte[] ivSeed = null)
|
|
|
{
|
|
|
- if(extraData?.Length > 255)
|
|
|
- throw new ArgumentException("Extra data cannot be larger than 255 bytes!", nameof(extraData));
|
|
|
-
|
|
|
if (ivSeed == null)
|
|
|
ivSeed = BitConverter.GetBytes(Random.Next());
|
|
|
|
|
|
+ var iv = GenerateIV(ivSeed);
|
|
|
|
|
|
- byte[] iv = GenerateIV(ivSeed);
|
|
|
+ byte[] extraData = null;
|
|
|
+ if ((data.Length & 0xf) != 0) // Rijndael requires padding to 16 bytes in order to encrypt
|
|
|
+ {
|
|
|
+ var newSize = (data.Length & 0xfffffff0) + 0x10;
|
|
|
+ extraData = new byte[newSize - data.Length];
|
|
|
+ }
|
|
|
|
|
|
using (var rijndael = new RijndaelManaged())
|
|
|
{
|
|
|
rijndael.Padding = PaddingMode.None;
|
|
|
|
|
|
- using (ICryptoTransform encryptor = rijndael.CreateEncryptor(key, iv))
|
|
|
+ using (var 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);
|
|
|
+ if (extraData != null)
|
|
|
+ stream.Write(extraData, 0, extraData.Length);
|
|
|
+ stream.Flush();
|
|
|
+
|
|
|
+ var extraLength = (byte) (extraData?.Length ?? 0);
|
|
|
+ mem.Write(new[] {(byte) (extraLength ^ ivSeed[0])}, 0, 1);
|
|
|
+ mem.Write(ivSeed, 0, ivSeed.Length);
|
|
|
+ }
|
|
|
|
|
|
return mem.ToArray();
|
|
|
}
|