Update to BouncyCastle 1.9.0

This commit is contained in:
BruceChen 2022-08-25 21:29:33 +08:00
parent ed8e97fd2d
commit a3971f9097
9 changed files with 392 additions and 115 deletions

View file

@ -30,6 +30,11 @@ namespace Org.BouncyCastle.Crypto.Engines
* This file contains the fast version with 8Kbytes of static tables for round precomputation * This file contains the fast version with 8Kbytes of static tables for round precomputation
* </p> * </p>
*/ */
/// <remarks>
/// Unfortunately this class has a few side channel issues.
/// In an environment where encryption/decryption may be closely observed it should not be used.
/// </remarks>
[Obsolete("Use AesEngine instead")]
public class AesFastEngine public class AesFastEngine
: IBlockCipher : IBlockCipher
{ {
@ -573,12 +578,22 @@ namespace Org.BouncyCastle.Crypto.Engines
private const uint m1 = 0x80808080; private const uint m1 = 0x80808080;
private const uint m2 = 0x7f7f7f7f; private const uint m2 = 0x7f7f7f7f;
private const uint m3 = 0x0000001b; private const uint m3 = 0x0000001b;
private const uint m4 = 0xC0C0C0C0;
private const uint m5 = 0x3f3f3f3f;
private static uint FFmulX(uint x) private static uint FFmulX(uint x)
{ {
return ((x & m2) << 1) ^ (((x & m1) >> 7) * m3); 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 The following defines provide alternative definitions of FFmulX that might
give improved performance if a fast 32-bit multiply is not available. 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) private static uint Inv_Mcol(uint x)
{ {
uint f2 = FFmulX(x); uint t0, t1;
uint f4 = FFmulX(f2); t0 = x;
uint f8 = FFmulX(f4); t1 = t0 ^ Shift(t0, 8);
uint f9 = x ^ f8; t0 ^= FFmulX(t1);
t1 ^= FFmulX2(t0);
return f2 ^ f4 ^ f8 ^ Shift(f2 ^ f9, 8) ^ Shift(f4 ^ f9, 16) ^ Shift(f9, 24); t0 ^= t1 ^ Shift(t1, 16);
return t0;
} }
private static uint SubWord(uint x) 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 * 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 * This code is written assuming those are the only possible values
*/ */
private uint[][] GenerateWorkingKey( private uint[][] GenerateWorkingKey(byte[] key, bool forEncryption)
byte[] key,
bool forEncryption)
{ {
int KC = key.Length / 4; // key length in words int keyLen = key.Length;
if (keyLen < 16 || keyLen > 32 || (keyLen & 7) != 0)
if (((KC != 4) && (KC != 6) && (KC != 8)) || ((KC * 4) != key.Length))
throw new ArgumentException("Key length not 128/192/256 bits."); 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 uint[][] W = new uint[ROUNDS + 1][]; // 4 words in a block
for (int i = 0; i <= ROUNDS; ++i) for (int i = 0; i <= ROUNDS; ++i)
@ -630,32 +644,109 @@ namespace Org.BouncyCastle.Crypto.Engines
W[i] = new uint[4]; W[i] = new uint[4];
} }
// switch (KC)
// copy the key into the round key array
//
int t = 0;
for (int i = 0; i < key.Length; t++)
{ {
W[t >> 2][t & 3] = Pack.LE_To_UInt32(key, i); case 4:
i+=4;
}
//
// while not enough round key material calculated
// calculate new values
//
int k = (ROUNDS + 1) << 2;
for (int i = KC; (i < k); i++)
{ {
uint temp = W[(i-1)>>2][(i-1)&3]; uint t0 = Pack.LE_To_UInt32(key, 0); W[0][0] = t0;
if ((i % KC) == 0) { uint t1 = Pack.LE_To_UInt32(key, 4); W[0][1] = t1;
temp = SubWord(Shift(temp, 8)) ^ rcon[(i / KC)-1]; uint t2 = Pack.LE_To_UInt32(key, 8); W[0][2] = t2;
} else if ((KC > 6) && ((i % KC) == 4)) { uint t3 = Pack.LE_To_UInt32(key, 12); W[0][3] = t3;
temp = SubWord(temp);
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) if (!forEncryption)
@ -675,7 +766,6 @@ namespace Org.BouncyCastle.Crypto.Engines
private int ROUNDS; private int ROUNDS;
private uint[][] WorkingKey; private uint[][] WorkingKey;
private uint C0, C1, C2, C3;
private bool forEncryption; private bool forEncryption;
private const int BLOCK_SIZE = 16; 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. * initialise an AES cipher.
* *
@ -702,7 +797,8 @@ namespace Org.BouncyCastle.Crypto.Engines
KeyParameter keyParameter = parameters as KeyParameter; KeyParameter keyParameter = parameters as KeyParameter;
if (keyParameter == null) 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); WorkingKey = GenerateWorkingKey(keyParameter.GetKey(), forEncryption);
@ -724,11 +820,7 @@ namespace Org.BouncyCastle.Crypto.Engines
return BLOCK_SIZE; return BLOCK_SIZE;
} }
public virtual int ProcessBlock( public virtual int ProcessBlock(byte[] input, int inOff, byte[] output, int outOff)
byte[] input,
int inOff,
byte[] output,
int outOff)
{ {
if (WorkingKey == null) if (WorkingKey == null)
throw new InvalidOperationException("AES engine not initialised"); 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.DataLength(input, inOff, 16, "input buffer too short");
Check.OutputLength(output, outOff, 16, "output buffer too short"); Check.OutputLength(output, outOff, 16, "output buffer too short");
UnPackBlock(input, inOff);
if (forEncryption) if (forEncryption)
{ {
EncryptBlock(WorkingKey); EncryptBlock(input, inOff, output, outOff, WorkingKey);
} }
else else
{ {
DecryptBlock(WorkingKey); DecryptBlock(input, inOff, output, outOff, WorkingKey);
} }
PackBlock(output, outOff);
return BLOCK_SIZE; return BLOCK_SIZE;
} }
@ -756,34 +844,19 @@ namespace Org.BouncyCastle.Crypto.Engines
{ {
} }
private void UnPackBlock( private void EncryptBlock(byte[] input, int inOff, byte[] output, int outOff, uint[][] KW)
byte[] bytes,
int off)
{ {
C0 = Pack.LE_To_UInt32(bytes, off); uint C0 = Pack.LE_To_UInt32(input, inOff + 0);
C1 = Pack.LE_To_UInt32(bytes, off + 4); uint C1 = Pack.LE_To_UInt32(input, inOff + 4);
C2 = Pack.LE_To_UInt32(bytes, off + 8); uint C2 = Pack.LE_To_UInt32(input, inOff + 8);
C3 = Pack.LE_To_UInt32(bytes, off + 12); 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[] kw = KW[0];
uint t0 = this.C0 ^ kw[0]; uint t0 = C0 ^ kw[0];
uint t1 = this.C1 ^ kw[1]; uint t1 = C1 ^ kw[1];
uint t2 = this.C2 ^ kw[2]; 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; int r = 1;
while (r < ROUNDS - 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 // 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]; 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]; 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]; 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]; 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]; 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 C0 = Pack.LE_To_UInt32(input, inOff + 0);
uint t0 = this.C0 ^ kw[0]; uint C1 = Pack.LE_To_UInt32(input, inOff + 4);
uint t1 = this.C1 ^ kw[1]; uint C2 = Pack.LE_To_UInt32(input, inOff + 8);
uint t2 = this.C2 ^ kw[2]; 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; int r = ROUNDS - 1;
while (r > 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 // 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]; 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]; 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]; 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]; 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]; 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);
} }
} }
} }

View file

@ -29,6 +29,9 @@ namespace Org.BouncyCastle.Crypto.Modes
IBlockCipher cipher, IBlockCipher cipher,
int bitBlockSize) int bitBlockSize)
{ {
if (bitBlockSize < 8 || (bitBlockSize & 7) != 0)
throw new ArgumentException("CFB" + bitBlockSize + " not supported", "bitBlockSize");
this.cipher = cipher; this.cipher = cipher;
this.blockSize = bitBlockSize / 8; this.blockSize = bitBlockSize / 8;
this.IV = new byte[cipher.GetBlockSize()]; this.IV = new byte[cipher.GetBlockSize()];

View file

@ -12,13 +12,13 @@ namespace Org.BouncyCastle.Crypto
internal static void DataLength(byte[] buf, int off, int len, string msg) 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); throw new DataLengthException(msg);
} }
internal static void OutputLength(byte[] buf, int off, int len, string 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); throw new OutputLengthException(msg);
} }
} }

View file

@ -2,8 +2,6 @@ using System;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using Org.BouncyCastle.Crypto;
namespace Org.BouncyCastle.Crypto.IO namespace Org.BouncyCastle.Crypto.IO
{ {
public class CipherStream public class CipherStream
@ -201,7 +199,23 @@ namespace Org.BouncyCastle.Crypto.IO
set { throw new NotSupportedException(); } 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) if (outCipher != null)
{ {
@ -210,9 +224,11 @@ namespace Org.BouncyCastle.Crypto.IO
stream.Flush(); stream.Flush();
} }
stream.Close(); stream.Close();
base.Close();
} }
#endif
public override void Flush() public override void Flush()
{ {
// Note: outCipher.DoFinal is only called during Close() // Note: outCipher.DoFinal is only called during Close()
stream.Flush(); stream.Flush();

View file

@ -2,7 +2,7 @@ using System;
namespace Org.BouncyCastle.Crypto namespace Org.BouncyCastle.Crypto
{ {
#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT) #if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT || PORTABLE)
[Serializable] [Serializable]
#endif #endif
public class CryptoException public class CryptoException

View file

@ -8,7 +8,7 @@ namespace Org.BouncyCastle.Crypto
* insufficient input. In general this exception will Get thrown rather * insufficient input. In general this exception will Get thrown rather
* than an ArrayOutOfBounds exception. * than an ArrayOutOfBounds exception.
*/ */
#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT) #if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT || PORTABLE)
[Serializable] [Serializable]
#endif #endif
public class DataLengthException public class DataLengthException

View file

@ -27,7 +27,7 @@ namespace Org.BouncyCastle.Crypto.Parameters
throw new ArgumentNullException("key"); throw new ArgumentNullException("key");
if (keyOff < 0 || keyOff > key.Length) if (keyOff < 0 || keyOff > key.Length)
throw new ArgumentOutOfRangeException("keyOff"); throw new ArgumentOutOfRangeException("keyOff");
if (keyLen < 0 || (keyOff + keyLen) > key.Length) if (keyLen < 0 || keyLen > (key.Length - keyOff))
throw new ArgumentOutOfRangeException("keyLen"); throw new ArgumentOutOfRangeException("keyLen");
this.key = new byte[keyLen]; this.key = new byte[keyLen];

View file

@ -2,7 +2,7 @@
namespace Org.BouncyCastle.Crypto namespace Org.BouncyCastle.Crypto
{ {
#if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT) #if !(NETCF_1_0 || NETCF_2_0 || SILVERLIGHT || PORTABLE)
[Serializable] [Serializable]
#endif #endif
public class OutputLengthException public class OutputLengthException

View file

@ -20,11 +20,41 @@ namespace Org.BouncyCastle.Crypto.Utilities
bs[off + 1] = (byte)(n); 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 for (int i = 0; i < ns.Length; ++i)
| (uint)bs[1]; {
return (ushort)n; 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) internal static ushort BE_To_UInt16(byte[] bs, int off)
@ -34,11 +64,27 @@ namespace Org.BouncyCastle.Crypto.Utilities
return (ushort)n; 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]; ns[nsOff] = BE_To_UInt16(bs, bsOff);
UInt32_To_BE(n, bs, 0); }
return bs;
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) internal static void UInt32_To_BE(uint n, byte[] bs)
@ -57,13 +103,6 @@ namespace Org.BouncyCastle.Crypto.Utilities
bs[off + 3] = (byte)(n); 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) internal static void UInt32_To_BE(uint[] ns, byte[] bs, int off)
{ {
for (int i = 0; i < ns.Length; ++i) 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) internal static uint BE_To_UInt32(byte[] bs)
{ {
return (uint)bs[0] << 24 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) internal static byte[] UInt64_To_BE(ulong n)
{ {
byte[] bs = new byte[8]; byte[] bs = new byte[8];
@ -117,11 +188,29 @@ namespace Org.BouncyCastle.Crypto.Utilities
UInt32_To_BE((uint)(n), bs, off + 4); 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); byte[] bs = new byte[8 * ns.Length];
uint lo = BE_To_UInt32(bs, 4); UInt64_To_BE(ns, bs, 0);
return ((ulong)hi << 32) | (ulong)lo; 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) 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; 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) internal static void UInt16_To_LE(ushort n, byte[] bs)
{ {
bs[0] = (byte)(n); 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) internal static uint LE_To_UInt32(byte[] bs)
{ {
return (uint)bs[0] 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) internal static byte[] UInt64_To_LE(ulong n)
{ {
byte[] bs = new byte[8]; byte[] bs = new byte[8];
@ -249,6 +376,31 @@ namespace Org.BouncyCastle.Crypto.Utilities
UInt32_To_LE((uint)(n >> 32), bs, off + 4); 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) internal static ulong LE_To_UInt64(byte[] bs)
{ {
uint lo = LE_To_UInt32(bs); uint lo = LE_To_UInt32(bs);
@ -262,5 +414,23 @@ namespace Org.BouncyCastle.Crypto.Utilities
uint hi = LE_To_UInt32(bs, off + 4); uint hi = LE_To_UInt32(bs, off + 4);
return ((ulong)hi << 32) | (ulong)lo; 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;
}
}
} }
} }