diff --git a/MinecraftClient/Crypto/Streams/BouncyAes/AesFastEngine.cs b/MinecraftClient/Crypto/Streams/BouncyAes/AesFastEngine.cs index a1b54456..069ba31a 100644 --- a/MinecraftClient/Crypto/Streams/BouncyAes/AesFastEngine.cs +++ b/MinecraftClient/Crypto/Streams/BouncyAes/AesFastEngine.cs @@ -30,6 +30,11 @@ namespace Org.BouncyCastle.Crypto.Engines * This file contains the fast version with 8Kbytes of static tables for round precomputation *

*/ + /// + /// Unfortunately this class has a few side channel issues. + /// In an environment where encryption/decryption may be closely observed it should not be used. + /// + [Obsolete("Use AesEngine instead")] public class AesFastEngine : IBlockCipher { @@ -573,12 +578,22 @@ namespace Org.BouncyCastle.Crypto.Engines private const uint m1 = 0x80808080; private const uint m2 = 0x7f7f7f7f; private const uint m3 = 0x0000001b; + private const uint m4 = 0xC0C0C0C0; + private const uint m5 = 0x3f3f3f3f; private static uint FFmulX(uint x) { return ((x & m2) << 1) ^ (((x & m1) >> 7) * m3); } + private static uint FFmulX2(uint x) + { + uint t0 = (x & m5) << 2; + uint t1 = (x & m4); + t1 ^= (t1 >> 1); + return t0 ^ (t1 >> 2) ^ (t1 >> 5); + } + /* The following defines provide alternative definitions of FFmulX that might give improved performance if a fast 32-bit multiply is not available. @@ -591,12 +606,13 @@ namespace Org.BouncyCastle.Crypto.Engines private static uint Inv_Mcol(uint x) { - uint f2 = FFmulX(x); - uint f4 = FFmulX(f2); - uint f8 = FFmulX(f4); - uint f9 = x ^ f8; - - return f2 ^ f4 ^ f8 ^ Shift(f2 ^ f9, 8) ^ Shift(f4 ^ f9, 16) ^ Shift(f9, 24); + uint t0, t1; + t0 = x; + t1 = t0 ^ Shift(t0, 8); + t0 ^= FFmulX(t1); + t1 ^= FFmulX2(t0); + t0 ^= t1 ^ Shift(t1, 16); + return t0; } private static uint SubWord(uint x) @@ -613,16 +629,14 @@ namespace Org.BouncyCastle.Crypto.Engines * AES specified a fixed block size of 128 bits and key sizes 128/192/256 bits * This code is written assuming those are the only possible values */ - private uint[][] GenerateWorkingKey( - byte[] key, - bool forEncryption) + private uint[][] GenerateWorkingKey(byte[] key, bool forEncryption) { - int KC = key.Length / 4; // key length in words - - if (((KC != 4) && (KC != 6) && (KC != 8)) || ((KC * 4) != key.Length)) + int keyLen = key.Length; + if (keyLen < 16 || keyLen > 32 || (keyLen & 7) != 0) throw new ArgumentException("Key length not 128/192/256 bits."); - ROUNDS = KC + 6; // This is not always true for the generalized Rijndael that allows larger block sizes + int KC = keyLen >> 2; + this.ROUNDS = KC + 6; // This is not always true for the generalized Rijndael that allows larger block sizes uint[][] W = new uint[ROUNDS + 1][]; // 4 words in a block for (int i = 0; i <= ROUNDS; ++i) @@ -630,32 +644,109 @@ namespace Org.BouncyCastle.Crypto.Engines W[i] = new uint[4]; } - // - // copy the key into the round key array - // - - int t = 0; - for (int i = 0; i < key.Length; t++) + switch (KC) { - W[t >> 2][t & 3] = Pack.LE_To_UInt32(key, i); - i+=4; - } - - // - // while not enough round key material calculated - // calculate new values - // - int k = (ROUNDS + 1) << 2; - for (int i = KC; (i < k); i++) + case 4: { - uint temp = W[(i-1)>>2][(i-1)&3]; - if ((i % KC) == 0) { - temp = SubWord(Shift(temp, 8)) ^ rcon[(i / KC)-1]; - } else if ((KC > 6) && ((i % KC) == 4)) { - temp = SubWord(temp); + uint t0 = Pack.LE_To_UInt32(key, 0); W[0][0] = t0; + uint t1 = Pack.LE_To_UInt32(key, 4); W[0][1] = t1; + uint t2 = Pack.LE_To_UInt32(key, 8); W[0][2] = t2; + uint t3 = Pack.LE_To_UInt32(key, 12); W[0][3] = t3; + + for (int i = 1; i <= 10; ++i) + { + uint u = SubWord(Shift(t3, 8)) ^ rcon[i - 1]; + t0 ^= u; W[i][0] = t0; + t1 ^= t0; W[i][1] = t1; + t2 ^= t1; W[i][2] = t2; + t3 ^= t2; W[i][3] = t3; } - W[i>>2][i&3] = W[(i - KC)>>2][(i-KC)&3] ^ temp; + break; + } + case 6: + { + uint t0 = Pack.LE_To_UInt32(key, 0); W[0][0] = t0; + uint t1 = Pack.LE_To_UInt32(key, 4); W[0][1] = t1; + uint t2 = Pack.LE_To_UInt32(key, 8); W[0][2] = t2; + uint t3 = Pack.LE_To_UInt32(key, 12); W[0][3] = t3; + uint t4 = Pack.LE_To_UInt32(key, 16); W[1][0] = t4; + uint t5 = Pack.LE_To_UInt32(key, 20); W[1][1] = t5; + + uint rcon = 1; + uint u = SubWord(Shift(t5, 8)) ^ rcon; rcon <<= 1; + t0 ^= u; W[1][2] = t0; + t1 ^= t0; W[1][3] = t1; + t2 ^= t1; W[2][0] = t2; + t3 ^= t2; W[2][1] = t3; + t4 ^= t3; W[2][2] = t4; + t5 ^= t4; W[2][3] = t5; + + for (int i = 3; i < 12; i += 3) + { + u = SubWord(Shift(t5, 8)) ^ rcon; rcon <<= 1; + t0 ^= u; W[i ][0] = t0; + t1 ^= t0; W[i ][1] = t1; + t2 ^= t1; W[i ][2] = t2; + t3 ^= t2; W[i ][3] = t3; + t4 ^= t3; W[i + 1][0] = t4; + t5 ^= t4; W[i + 1][1] = t5; + u = SubWord(Shift(t5, 8)) ^ rcon; rcon <<= 1; + t0 ^= u; W[i + 1][2] = t0; + t1 ^= t0; W[i + 1][3] = t1; + t2 ^= t1; W[i + 2][0] = t2; + t3 ^= t2; W[i + 2][1] = t3; + t4 ^= t3; W[i + 2][2] = t4; + t5 ^= t4; W[i + 2][3] = t5; + } + + u = SubWord(Shift(t5, 8)) ^ rcon; + t0 ^= u; W[12][0] = t0; + t1 ^= t0; W[12][1] = t1; + t2 ^= t1; W[12][2] = t2; + t3 ^= t2; W[12][3] = t3; + + break; + } + case 8: + { + uint t0 = Pack.LE_To_UInt32(key, 0); W[0][0] = t0; + uint t1 = Pack.LE_To_UInt32(key, 4); W[0][1] = t1; + uint t2 = Pack.LE_To_UInt32(key, 8); W[0][2] = t2; + uint t3 = Pack.LE_To_UInt32(key, 12); W[0][3] = t3; + uint t4 = Pack.LE_To_UInt32(key, 16); W[1][0] = t4; + uint t5 = Pack.LE_To_UInt32(key, 20); W[1][1] = t5; + uint t6 = Pack.LE_To_UInt32(key, 24); W[1][2] = t6; + uint t7 = Pack.LE_To_UInt32(key, 28); W[1][3] = t7; + + uint u, rcon = 1; + + for (int i = 2; i < 14; i += 2) + { + u = SubWord(Shift(t7, 8)) ^ rcon; rcon <<= 1; + t0 ^= u; W[i ][0] = t0; + t1 ^= t0; W[i ][1] = t1; + t2 ^= t1; W[i ][2] = t2; + t3 ^= t2; W[i ][3] = t3; + u = SubWord(t3); + t4 ^= u; W[i + 1][0] = t4; + t5 ^= t4; W[i + 1][1] = t5; + t6 ^= t5; W[i + 1][2] = t6; + t7 ^= t6; W[i + 1][3] = t7; + } + + u = SubWord(Shift(t7, 8)) ^ rcon; + t0 ^= u; W[14][0] = t0; + t1 ^= t0; W[14][1] = t1; + t2 ^= t1; W[14][2] = t2; + t3 ^= t2; W[14][3] = t3; + + break; + } + default: + { + throw new InvalidOperationException("Should never get here"); + } } if (!forEncryption) @@ -675,7 +766,6 @@ namespace Org.BouncyCastle.Crypto.Engines private int ROUNDS; private uint[][] WorkingKey; - private uint C0, C1, C2, C3; private bool forEncryption; private const int BLOCK_SIZE = 16; @@ -687,6 +777,11 @@ namespace Org.BouncyCastle.Crypto.Engines { } + internal static string GetTypeName(object obj) + { + return obj.GetType().FullName; + } + /** * initialise an AES cipher. * @@ -702,7 +797,8 @@ namespace Org.BouncyCastle.Crypto.Engines KeyParameter keyParameter = parameters as KeyParameter; if (keyParameter == null) - throw new ArgumentException("invalid parameter passed to AES init - " + parameters.GetType().Name); + throw new ArgumentException("invalid parameter passed to AES init - " + + GetTypeName(parameters)); WorkingKey = GenerateWorkingKey(keyParameter.GetKey(), forEncryption); @@ -724,11 +820,7 @@ namespace Org.BouncyCastle.Crypto.Engines return BLOCK_SIZE; } - public virtual int ProcessBlock( - byte[] input, - int inOff, - byte[] output, - int outOff) + public virtual int ProcessBlock(byte[] input, int inOff, byte[] output, int outOff) { if (WorkingKey == null) throw new InvalidOperationException("AES engine not initialised"); @@ -736,19 +828,15 @@ namespace Org.BouncyCastle.Crypto.Engines Check.DataLength(input, inOff, 16, "input buffer too short"); Check.OutputLength(output, outOff, 16, "output buffer too short"); - UnPackBlock(input, inOff); - if (forEncryption) { - EncryptBlock(WorkingKey); + EncryptBlock(input, inOff, output, outOff, WorkingKey); } else { - DecryptBlock(WorkingKey); + DecryptBlock(input, inOff, output, outOff, WorkingKey); } - PackBlock(output, outOff); - return BLOCK_SIZE; } @@ -756,34 +844,19 @@ namespace Org.BouncyCastle.Crypto.Engines { } - private void UnPackBlock( - byte[] bytes, - int off) + private void EncryptBlock(byte[] input, int inOff, byte[] output, int outOff, uint[][] KW) { - C0 = Pack.LE_To_UInt32(bytes, off); - C1 = Pack.LE_To_UInt32(bytes, off + 4); - C2 = Pack.LE_To_UInt32(bytes, off + 8); - C3 = Pack.LE_To_UInt32(bytes, off + 12); - } + uint C0 = Pack.LE_To_UInt32(input, inOff + 0); + uint C1 = Pack.LE_To_UInt32(input, inOff + 4); + uint C2 = Pack.LE_To_UInt32(input, inOff + 8); + uint C3 = Pack.LE_To_UInt32(input, inOff + 12); - private void PackBlock( - byte[] bytes, - int off) - { - Pack.UInt32_To_LE(C0, bytes, off); - Pack.UInt32_To_LE(C1, bytes, off + 4); - Pack.UInt32_To_LE(C2, bytes, off + 8); - Pack.UInt32_To_LE(C3, bytes, off + 12); - } - - private void EncryptBlock(uint[][] KW) - { uint[] kw = KW[0]; - uint t0 = this.C0 ^ kw[0]; - uint t1 = this.C1 ^ kw[1]; - uint t2 = this.C2 ^ kw[2]; + uint t0 = C0 ^ kw[0]; + uint t1 = C1 ^ kw[1]; + uint t2 = C2 ^ kw[2]; - uint r0, r1, r2, r3 = this.C3 ^ kw[3]; + uint r0, r1, r2, r3 = C3 ^ kw[3]; int r = 1; while (r < ROUNDS - 1) { @@ -808,20 +881,30 @@ namespace Org.BouncyCastle.Crypto.Engines // the final round's table is a simple function of S so we don't use a whole other four tables for it kw = KW[r]; - this.C0 = (uint)S[r0 & 255] ^ (((uint)S[(r1 >> 8) & 255]) << 8) ^ (((uint)S[(r2 >> 16) & 255]) << 16) ^ (((uint)S[r3 >> 24]) << 24) ^ kw[0]; - this.C1 = (uint)S[r1 & 255] ^ (((uint)S[(r2 >> 8) & 255]) << 8) ^ (((uint)S[(r3 >> 16) & 255]) << 16) ^ (((uint)S[r0 >> 24]) << 24) ^ kw[1]; - this.C2 = (uint)S[r2 & 255] ^ (((uint)S[(r3 >> 8) & 255]) << 8) ^ (((uint)S[(r0 >> 16) & 255]) << 16) ^ (((uint)S[r1 >> 24]) << 24) ^ kw[2]; - this.C3 = (uint)S[r3 & 255] ^ (((uint)S[(r0 >> 8) & 255]) << 8) ^ (((uint)S[(r1 >> 16) & 255]) << 16) ^ (((uint)S[r2 >> 24]) << 24) ^ kw[3]; + C0 = (uint)S[r0 & 255] ^ (((uint)S[(r1 >> 8) & 255]) << 8) ^ (((uint)S[(r2 >> 16) & 255]) << 16) ^ (((uint)S[r3 >> 24]) << 24) ^ kw[0]; + C1 = (uint)S[r1 & 255] ^ (((uint)S[(r2 >> 8) & 255]) << 8) ^ (((uint)S[(r3 >> 16) & 255]) << 16) ^ (((uint)S[r0 >> 24]) << 24) ^ kw[1]; + C2 = (uint)S[r2 & 255] ^ (((uint)S[(r3 >> 8) & 255]) << 8) ^ (((uint)S[(r0 >> 16) & 255]) << 16) ^ (((uint)S[r1 >> 24]) << 24) ^ kw[2]; + C3 = (uint)S[r3 & 255] ^ (((uint)S[(r0 >> 8) & 255]) << 8) ^ (((uint)S[(r1 >> 16) & 255]) << 16) ^ (((uint)S[r2 >> 24]) << 24) ^ kw[3]; + + Pack.UInt32_To_LE(C0, output, outOff + 0); + Pack.UInt32_To_LE(C1, output, outOff + 4); + Pack.UInt32_To_LE(C2, output, outOff + 8); + Pack.UInt32_To_LE(C3, output, outOff + 12); } - private void DecryptBlock(uint[][] KW) + private void DecryptBlock(byte[] input, int inOff, byte[] output, int outOff, uint[][] KW) { - uint[] kw = KW[ROUNDS]; - uint t0 = this.C0 ^ kw[0]; - uint t1 = this.C1 ^ kw[1]; - uint t2 = this.C2 ^ kw[2]; + uint C0 = Pack.LE_To_UInt32(input, inOff + 0); + uint C1 = Pack.LE_To_UInt32(input, inOff + 4); + uint C2 = Pack.LE_To_UInt32(input, inOff + 8); + uint C3 = Pack.LE_To_UInt32(input, inOff + 12); - uint r0, r1, r2, r3 = this.C3 ^ kw[3]; + uint[] kw = KW[ROUNDS]; + uint t0 = C0 ^ kw[0]; + uint t1 = C1 ^ kw[1]; + uint t2 = C2 ^ kw[2]; + + uint r0, r1, r2, r3 = C3 ^ kw[3]; int r = ROUNDS - 1; while (r > 1) { @@ -846,10 +929,15 @@ namespace Org.BouncyCastle.Crypto.Engines // the final round's table is a simple function of Si so we don't use a whole other four tables for it kw = KW[0]; - this.C0 = (uint)Si[r0 & 255] ^ (((uint)Si[(r3 >> 8) & 255]) << 8) ^ (((uint)Si[(r2 >> 16) & 255]) << 16) ^ (((uint)Si[r1 >> 24]) << 24) ^ kw[0]; - this.C1 = (uint)Si[r1 & 255] ^ (((uint)Si[(r0 >> 8) & 255]) << 8) ^ (((uint)Si[(r3 >> 16) & 255]) << 16) ^ (((uint)Si[r2 >> 24]) << 24) ^ kw[1]; - this.C2 = (uint)Si[r2 & 255] ^ (((uint)Si[(r1 >> 8) & 255]) << 8) ^ (((uint)Si[(r0 >> 16) & 255]) << 16) ^ (((uint)Si[r3 >> 24]) << 24) ^ kw[2]; - this.C3 = (uint)Si[r3 & 255] ^ (((uint)Si[(r2 >> 8) & 255]) << 8) ^ (((uint)Si[(r1 >> 16) & 255]) << 16) ^ (((uint)Si[r0 >> 24]) << 24) ^ kw[3]; + C0 = (uint)Si[r0 & 255] ^ (((uint)Si[(r3 >> 8) & 255]) << 8) ^ (((uint)Si[(r2 >> 16) & 255]) << 16) ^ (((uint)Si[r1 >> 24]) << 24) ^ kw[0]; + C1 = (uint)Si[r1 & 255] ^ (((uint)Si[(r0 >> 8) & 255]) << 8) ^ (((uint)Si[(r3 >> 16) & 255]) << 16) ^ (((uint)Si[r2 >> 24]) << 24) ^ kw[1]; + C2 = (uint)Si[r2 & 255] ^ (((uint)Si[(r1 >> 8) & 255]) << 8) ^ (((uint)Si[(r0 >> 16) & 255]) << 16) ^ (((uint)Si[r3 >> 24]) << 24) ^ kw[2]; + C3 = (uint)Si[r3 & 255] ^ (((uint)Si[(r2 >> 8) & 255]) << 8) ^ (((uint)Si[(r1 >> 16) & 255]) << 16) ^ (((uint)Si[r0 >> 24]) << 24) ^ kw[3]; + + Pack.UInt32_To_LE(C0, output, outOff + 0); + Pack.UInt32_To_LE(C1, output, outOff + 4); + Pack.UInt32_To_LE(C2, output, outOff + 8); + Pack.UInt32_To_LE(C3, output, outOff + 12); } } } diff --git a/MinecraftClient/Crypto/Streams/BouncyAes/CfbBlockCipher.cs b/MinecraftClient/Crypto/Streams/BouncyAes/CfbBlockCipher.cs index 43371653..ed0be407 100644 --- a/MinecraftClient/Crypto/Streams/BouncyAes/CfbBlockCipher.cs +++ b/MinecraftClient/Crypto/Streams/BouncyAes/CfbBlockCipher.cs @@ -29,6 +29,9 @@ namespace Org.BouncyCastle.Crypto.Modes IBlockCipher cipher, int bitBlockSize) { + if (bitBlockSize < 8 || (bitBlockSize & 7) != 0) + throw new ArgumentException("CFB" + bitBlockSize + " not supported", "bitBlockSize"); + this.cipher = cipher; this.blockSize = bitBlockSize / 8; this.IV = new byte[cipher.GetBlockSize()]; diff --git a/MinecraftClient/Crypto/Streams/BouncyAes/Check.cs b/MinecraftClient/Crypto/Streams/BouncyAes/Check.cs index 96a05c64..aacda144 100644 --- a/MinecraftClient/Crypto/Streams/BouncyAes/Check.cs +++ b/MinecraftClient/Crypto/Streams/BouncyAes/Check.cs @@ -12,13 +12,13 @@ namespace Org.BouncyCastle.Crypto internal static void DataLength(byte[] buf, int off, int len, string msg) { - if (off + len > buf.Length) + if (off > (buf.Length - len)) throw new DataLengthException(msg); } internal static void OutputLength(byte[] buf, int off, int len, string msg) { - if (off + len > buf.Length) + if (off > (buf.Length - len)) throw new OutputLengthException(msg); } } diff --git a/MinecraftClient/Crypto/Streams/BouncyAes/CipherStream.cs b/MinecraftClient/Crypto/Streams/BouncyAes/CipherStream.cs index b6920854..058d7f73 100644 --- a/MinecraftClient/Crypto/Streams/BouncyAes/CipherStream.cs +++ b/MinecraftClient/Crypto/Streams/BouncyAes/CipherStream.cs @@ -2,8 +2,6 @@ using System; using System.Diagnostics; using System.IO; -using Org.BouncyCastle.Crypto; - namespace Org.BouncyCastle.Crypto.IO { public class CipherStream @@ -201,7 +199,23 @@ namespace Org.BouncyCastle.Crypto.IO set { throw new NotSupportedException(); } } - public override void Close() +#if PORTABLE + protected override void Dispose(bool disposing) + { + if (disposing) + { + if (outCipher != null) + { + byte[] data = outCipher.DoFinal(); + stream.Write(data, 0, data.Length); + stream.Flush(); + } + Platform.Dispose(stream); + } + base.Dispose(disposing); + } +#else + public override void Close() { if (outCipher != null) { @@ -210,9 +224,11 @@ namespace Org.BouncyCastle.Crypto.IO stream.Flush(); } stream.Close(); + base.Close(); } +#endif - public override void Flush() + public override void Flush() { // Note: outCipher.DoFinal is only called during Close() stream.Flush(); diff --git a/MinecraftClient/Crypto/Streams/BouncyAes/CryptoException.cs b/MinecraftClient/Crypto/Streams/BouncyAes/CryptoException.cs index 67f0d86f..73d450be 100644 --- a/MinecraftClient/Crypto/Streams/BouncyAes/CryptoException.cs +++ b/MinecraftClient/Crypto/Streams/BouncyAes/CryptoException.cs @@ -2,7 +2,7 @@ using System; namespace Org.BouncyCastle.Crypto { -#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT) +#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT || PORTABLE) [Serializable] #endif public class CryptoException diff --git a/MinecraftClient/Crypto/Streams/BouncyAes/DataLengthException.cs b/MinecraftClient/Crypto/Streams/BouncyAes/DataLengthException.cs index e9efc0bd..447ff2a1 100644 --- a/MinecraftClient/Crypto/Streams/BouncyAes/DataLengthException.cs +++ b/MinecraftClient/Crypto/Streams/BouncyAes/DataLengthException.cs @@ -8,7 +8,7 @@ namespace Org.BouncyCastle.Crypto * insufficient input. In general this exception will Get thrown rather * than an ArrayOutOfBounds exception. */ -#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT) +#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT || PORTABLE) [Serializable] #endif public class DataLengthException diff --git a/MinecraftClient/Crypto/Streams/BouncyAes/KeyParameter.cs b/MinecraftClient/Crypto/Streams/BouncyAes/KeyParameter.cs index 33dff96d..043adf27 100644 --- a/MinecraftClient/Crypto/Streams/BouncyAes/KeyParameter.cs +++ b/MinecraftClient/Crypto/Streams/BouncyAes/KeyParameter.cs @@ -27,7 +27,7 @@ namespace Org.BouncyCastle.Crypto.Parameters throw new ArgumentNullException("key"); if (keyOff < 0 || keyOff > key.Length) throw new ArgumentOutOfRangeException("keyOff"); - if (keyLen < 0 || (keyOff + keyLen) > key.Length) + if (keyLen < 0 || keyLen > (key.Length - keyOff)) throw new ArgumentOutOfRangeException("keyLen"); this.key = new byte[keyLen]; diff --git a/MinecraftClient/Crypto/Streams/BouncyAes/OutputLengthException.cs b/MinecraftClient/Crypto/Streams/BouncyAes/OutputLengthException.cs index e1cf4492..437589f4 100644 --- a/MinecraftClient/Crypto/Streams/BouncyAes/OutputLengthException.cs +++ b/MinecraftClient/Crypto/Streams/BouncyAes/OutputLengthException.cs @@ -2,7 +2,7 @@ namespace Org.BouncyCastle.Crypto { -#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT) +#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT || PORTABLE) [Serializable] #endif public class OutputLengthException diff --git a/MinecraftClient/Crypto/Streams/BouncyAes/Pack.cs b/MinecraftClient/Crypto/Streams/BouncyAes/Pack.cs index 087cb7ce..8ba738d4 100644 --- a/MinecraftClient/Crypto/Streams/BouncyAes/Pack.cs +++ b/MinecraftClient/Crypto/Streams/BouncyAes/Pack.cs @@ -20,11 +20,41 @@ namespace Org.BouncyCastle.Crypto.Utilities bs[off + 1] = (byte)(n); } - internal static ushort BE_To_UInt16(byte[] bs) + internal static void UInt16_To_BE(ushort[] ns, byte[] bs, int off) { - uint n = (uint)bs[0] << 8 - | (uint)bs[1]; - return (ushort)n; + for (int i = 0; i < ns.Length; ++i) + { + UInt16_To_BE(ns[i], bs, off); + off += 2; + } + } + + internal static void UInt16_To_BE(ushort[] ns, int nsOff, int nsLen, byte[] bs, int bsOff) + { + for (int i = 0; i < nsLen; ++i) + { + UInt16_To_BE(ns[nsOff + i], bs, bsOff); + bsOff += 2; + } + } + + internal static byte[] UInt16_To_BE(ushort n) + { + byte[] bs = new byte[2]; + UInt16_To_BE(n, bs, 0); + return bs; + } + + internal static byte[] UInt16_To_BE(ushort[] ns) + { + return UInt16_To_BE(ns, 0, ns.Length); + } + + internal static byte[] UInt16_To_BE(ushort[] ns, int nsOff, int nsLen) + { + byte[] bs = new byte[2 * nsLen]; + UInt16_To_BE(ns, nsOff, nsLen, bs, 0); + return bs; } internal static ushort BE_To_UInt16(byte[] bs, int off) @@ -34,11 +64,27 @@ namespace Org.BouncyCastle.Crypto.Utilities return (ushort)n; } - internal static byte[] UInt32_To_BE(uint n) + internal static void BE_To_UInt16(byte[] bs, int bsOff, ushort[] ns, int nsOff) { - byte[] bs = new byte[4]; - UInt32_To_BE(n, bs, 0); - return bs; + ns[nsOff] = BE_To_UInt16(bs, bsOff); + } + + internal static ushort[] BE_To_UInt16(byte[] bs) + { + return BE_To_UInt16(bs, 0, bs.Length); + } + + internal static ushort[] BE_To_UInt16(byte[] bs, int off, int len) + { + if ((len & 1) != 0) + throw new ArgumentException("must be a multiple of 2", "len"); + + ushort[] ns = new ushort[len / 2]; + for (int i = 0; i < len; i += 2) + { + BE_To_UInt16(bs, off + i, ns, i >> 1); + } + return ns; } internal static void UInt32_To_BE(uint n, byte[] bs) @@ -57,13 +103,6 @@ namespace Org.BouncyCastle.Crypto.Utilities bs[off + 3] = (byte)(n); } - internal static byte[] UInt32_To_BE(uint[] ns) - { - byte[] bs = new byte[4 * ns.Length]; - UInt32_To_BE(ns, bs, 0); - return bs; - } - internal static void UInt32_To_BE(uint[] ns, byte[] bs, int off) { for (int i = 0; i < ns.Length; ++i) @@ -73,6 +112,29 @@ namespace Org.BouncyCastle.Crypto.Utilities } } + internal static void UInt32_To_BE(uint[] ns, int nsOff, int nsLen, byte[] bs, int bsOff) + { + for (int i = 0; i < nsLen; ++i) + { + UInt32_To_BE(ns[nsOff + i], bs, bsOff); + bsOff += 4; + } + } + + internal static byte[] UInt32_To_BE(uint n) + { + byte[] bs = new byte[4]; + UInt32_To_BE(n, bs, 0); + return bs; + } + + internal static byte[] UInt32_To_BE(uint[] ns) + { + byte[] bs = new byte[4 * ns.Length]; + UInt32_To_BE(ns, bs, 0); + return bs; + } + internal static uint BE_To_UInt32(byte[] bs) { return (uint)bs[0] << 24 @@ -98,6 +160,15 @@ namespace Org.BouncyCastle.Crypto.Utilities } } + internal static void BE_To_UInt32(byte[] bs, int bsOff, uint[] ns, int nsOff, int nsLen) + { + for (int i = 0; i < nsLen; ++i) + { + ns[nsOff + i] = BE_To_UInt32(bs, bsOff); + bsOff += 4; + } + } + internal static byte[] UInt64_To_BE(ulong n) { byte[] bs = new byte[8]; @@ -117,11 +188,29 @@ namespace Org.BouncyCastle.Crypto.Utilities UInt32_To_BE((uint)(n), bs, off + 4); } - internal static ulong BE_To_UInt64(byte[] bs) + internal static byte[] UInt64_To_BE(ulong[] ns) { - uint hi = BE_To_UInt32(bs); - uint lo = BE_To_UInt32(bs, 4); - return ((ulong)hi << 32) | (ulong)lo; + byte[] bs = new byte[8 * ns.Length]; + UInt64_To_BE(ns, bs, 0); + return bs; + } + + internal static void UInt64_To_BE(ulong[] ns, byte[] bs, int off) + { + for (int i = 0; i < ns.Length; ++i) + { + UInt64_To_BE(ns[i], bs, off); + off += 8; + } + } + + internal static void UInt64_To_BE(ulong[] ns, int nsOff, int nsLen, byte[] bs, int bsOff) + { + for (int i = 0; i < nsLen; ++i) + { + UInt64_To_BE(ns[nsOff + i], bs, bsOff); + bsOff += 8; + } } internal static ulong BE_To_UInt64(byte[] bs, int off) @@ -131,6 +220,24 @@ namespace Org.BouncyCastle.Crypto.Utilities return ((ulong)hi << 32) | (ulong)lo; } + internal static void BE_To_UInt64(byte[] bs, int off, ulong[] ns) + { + for (int i = 0; i < ns.Length; ++i) + { + ns[i] = BE_To_UInt64(bs, off); + off += 8; + } + } + + internal static void BE_To_UInt64(byte[] bs, int bsOff, ulong[] ns, int nsOff, int nsLen) + { + for (int i = 0; i < nsLen; ++i) + { + ns[nsOff + i] = BE_To_UInt64(bs, bsOff); + bsOff += 8; + } + } + internal static void UInt16_To_LE(ushort n, byte[] bs) { bs[0] = (byte)(n); @@ -196,6 +303,15 @@ namespace Org.BouncyCastle.Crypto.Utilities } } + internal static void UInt32_To_LE(uint[] ns, int nsOff, int nsLen, byte[] bs, int bsOff) + { + for (int i = 0; i < nsLen; ++i) + { + UInt32_To_LE(ns[nsOff + i], bs, bsOff); + bsOff += 4; + } + } + internal static uint LE_To_UInt32(byte[] bs) { return (uint)bs[0] @@ -230,6 +346,17 @@ namespace Org.BouncyCastle.Crypto.Utilities } } + internal static uint[] LE_To_UInt32(byte[] bs, int off, int count) + { + uint[] ns = new uint[count]; + for (int i = 0; i < ns.Length; ++i) + { + ns[i] = LE_To_UInt32(bs, off); + off += 4; + } + return ns; + } + internal static byte[] UInt64_To_LE(ulong n) { byte[] bs = new byte[8]; @@ -249,6 +376,31 @@ namespace Org.BouncyCastle.Crypto.Utilities UInt32_To_LE((uint)(n >> 32), bs, off + 4); } + internal static byte[] UInt64_To_LE(ulong[] ns) + { + byte[] bs = new byte[8 * ns.Length]; + UInt64_To_LE(ns, bs, 0); + return bs; + } + + internal static void UInt64_To_LE(ulong[] ns, byte[] bs, int off) + { + for (int i = 0; i < ns.Length; ++i) + { + UInt64_To_LE(ns[i], bs, off); + off += 8; + } + } + + internal static void UInt64_To_LE(ulong[] ns, int nsOff, int nsLen, byte[] bs, int bsOff) + { + for (int i = 0; i < nsLen; ++i) + { + UInt64_To_LE(ns[nsOff + i], bs, bsOff); + bsOff += 8; + } + } + internal static ulong LE_To_UInt64(byte[] bs) { uint lo = LE_To_UInt32(bs); @@ -262,5 +414,23 @@ namespace Org.BouncyCastle.Crypto.Utilities uint hi = LE_To_UInt32(bs, off + 4); return ((ulong)hi << 32) | (ulong)lo; } + + internal static void LE_To_UInt64(byte[] bs, int off, ulong[] ns) + { + for (int i = 0; i < ns.Length; ++i) + { + ns[i] = LE_To_UInt64(bs, off); + off += 8; + } + } + + internal static void LE_To_UInt64(byte[] bs, int bsOff, ulong[] ns, int nsOff, int nsLen) + { + for (int i = 0; i < nsLen; ++i) + { + ns[nsOff + i] = LE_To_UInt64(bs, bsOff); + bsOff += 8; + } + } } }