Skip to content

Commit cfba069

Browse files
committed
~10% perf increase (encryption/decryption) due to improved Xor implementation.
1 parent 5f81d52 commit cfba069

File tree

3 files changed

+95
-4
lines changed

3 files changed

+95
-4
lines changed

Cipher/AesCtrCryptoTransform.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,8 @@ public int TransformBlock(byte[] inputBuffer, int inputOffset, int inputCount, b
5757
if (fullBlockSize > 0)
5858
{
5959
fullBlockSize = this.cryptoTransform.TransformBlock(outputBuffer, outputOffset, fullBlockSize, outputBuffer, outputOffset);
60-
for (i = 0; i < fullBlockSize; ++i) outputBuffer[outputOffset + i] ^= inputBuffer[inputOffset + i];
61-
//XorArrays(outputBuffer, outputOffset, inputBuffer, inputOffset, fullBlockSize);
60+
//for (i = 0; i < fullBlockSize; ++i) outputBuffer[outputOffset + i] ^= inputBuffer[inputOffset + i];
61+
Utils.Xor(outputBuffer, outputOffset, inputBuffer, inputOffset, fullBlockSize);
6262
}
6363

6464
if (partialBlockSize > 0)

Cipher/AesFactories.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ namespace SecurityDriven.Inferno.Cipher
55
{
66
public static class AesFactories
77
{
8-
static readonly Func<Aes> ManagedAes = () => new AesManaged();
9-
static readonly Func<Aes> FipsAes = () => new AesCryptoServiceProvider();
8+
internal static readonly Func<Aes> ManagedAes = () => new AesManaged();
9+
internal static readonly Func<Aes> FipsAes = () => new AesCryptoServiceProvider();
1010

1111
public static readonly Func<Aes> Aes = Utils.AllowOnlyFipsAlgorithms ? FipsAes : ManagedAes;
1212
}//class AesFactories

Utils.cs

Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -212,6 +212,97 @@ public void ToBEBytes(byte[] buffer, int offset = 0)
212212
typeof(Action<Array, int, Array, int, int>),
213213
typeof(Buffer).GetMethod("InternalBlockCopy", BindingFlags.NonPublic | BindingFlags.Static))
214214
as Action<Array, int, Array, int, int>;
215+
216+
#region Combine byte arrays & segments
217+
public static byte[] Combine(ArraySegment<byte> a, ArraySegment<byte> b)
218+
{
219+
byte[] combinedArray = new byte[a.Count + b.Count];
220+
BlockCopy(a.Array, a.Offset, combinedArray, 0, a.Count);
221+
BlockCopy(b.Array, b.Offset, combinedArray, a.Count, b.Count);
222+
return combinedArray;
223+
}// Combine(two byte array segments)
224+
225+
public static byte[] Combine(byte[] a, byte[] b) { return Combine(a.AsArraySegment(), b.AsArraySegment()); }// Combine(two byte arrays)
226+
227+
public static byte[] Combine(ArraySegment<byte> a, ArraySegment<byte> b, ArraySegment<byte> c)
228+
{
229+
byte[] combinedArray = new byte[a.Count + b.Count + c.Count];
230+
BlockCopy(a.Array, a.Offset, combinedArray, 0, a.Count);
231+
BlockCopy(b.Array, b.Offset, combinedArray, a.Count, b.Count);
232+
BlockCopy(c.Array, c.Offset, combinedArray, a.Count + b.Count, c.Count);
233+
return combinedArray;
234+
}// Combine(three byte array segments)
235+
236+
public static byte[] Combine(byte[] a, byte[] b, byte[] c) { return Combine(a.AsArraySegment(), b.AsArraySegment(), c.AsArraySegment()); }// Combine(three byte arrays)
237+
238+
public static byte[] Combine(params byte[][] arrays)
239+
{
240+
int combinedArrayLength = 0, combinedArrayOffset = 0;
241+
for (int i = 0; i < arrays.Length; ++i) combinedArrayLength += arrays[i].Length;
242+
byte[] array, combinedArray = new byte[combinedArrayLength];
243+
244+
for (int i = 0; i < arrays.Length; ++i)
245+
{
246+
array = arrays[i];
247+
BlockCopy(array, 0, combinedArray, combinedArrayOffset, array.Length);
248+
combinedArrayOffset += array.Length;
249+
}
250+
return combinedArray;
251+
}// Combine(params byte[][])
252+
253+
public static byte[] Combine(params ArraySegment<byte>[] arraySegments)
254+
{
255+
int combinedArrayLength = 0, combinedArrayOffset = 0;
256+
for (int i = 0; i < arraySegments.Length; ++i) combinedArrayLength += arraySegments[i].Count;
257+
byte[] combinedArray = new byte[combinedArrayLength];
258+
259+
for (int i = 0; i < arraySegments.Length; ++i)
260+
{
261+
var segment = arraySegments[i];
262+
BlockCopy(segment.Array, segment.Offset, combinedArray, combinedArrayOffset, segment.Count);
263+
combinedArrayOffset += segment.Count;
264+
}
265+
return combinedArray;
266+
}// Combine(params ArraySegment<byte>[])
267+
#endregion
268+
269+
#region Xor
270+
[StructLayout(LayoutKind.Explicit)]
271+
struct Union
272+
{
273+
[FieldOffset(0)]
274+
public byte[] Bytes;
275+
276+
[FieldOffset(0)]
277+
public long[] Longs;
278+
}// struct Union
279+
280+
public static void Xor(byte[] dest, int destOffset, byte[] left, int leftOffset, byte[] right, int rightOffset, int byteCount)
281+
{
282+
int i = 0;
283+
if ((destOffset & 7) == 0 && (leftOffset & 7) == 0 && (rightOffset & 7) == 0) // all offsets must be multiples of 8 for long-sized xor
284+
{
285+
Union destUnion = new Union { Bytes = dest }, leftUnion = new Union { Bytes = left }, rightBuffer = new Union { Bytes = right };
286+
int longDestOffset = destOffset >> 3, longLeftOffset = leftOffset >> 3, longRightOffset = rightOffset >> 3, longCount = byteCount >> 3;
287+
for (; i < longCount; ++i) destUnion.Longs[longDestOffset + i] = leftUnion.Longs[longLeftOffset + i] ^ rightBuffer.Longs[longRightOffset + i];
288+
i = longCount << 3;
289+
}
290+
for (; i < byteCount; ++i) dest[destOffset + i] = (byte)(left[leftOffset + i] ^ right[rightOffset + i]);
291+
}// Xor()
292+
293+
public static void Xor(byte[] dest, int destOffset, byte[] left, int leftOffset, int byteCount)
294+
{
295+
int i = 0;
296+
if ((destOffset & 7) == 0 && (leftOffset & 7) == 0) // all offsets must be multiples of 8 for long-sized xor
297+
{
298+
Union destUnion = new Union { Bytes = dest }, leftUnion = new Union { Bytes = left };
299+
int longDestOffset = destOffset >> 3, longLeftOffset = leftOffset >> 3, longCount = byteCount >> 3;
300+
for (; i < longCount; ++i) destUnion.Longs[longDestOffset + i] ^= leftUnion.Longs[longLeftOffset + i];
301+
i = longCount << 3;
302+
}
303+
for (; i < byteCount; ++i) dest[destOffset + i] ^= left[leftOffset + i];
304+
}// Xor()
305+
#endregion
215306
}// class Utils
216307

217308
public static class ArraySegmentExtensions

0 commit comments

Comments
 (0)