Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Text.RegularExpressions;
- // ReSharper disable UnusedMember.Global
- #region MIT LICENSE
- /*
- License: The MIT License (MIT)
- Copyright (C) 2021 Shannon Rowe
- Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
- documentation files (the "Software"), to deal in the Software without restriction, including without limitation
- the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
- and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
- The above copyright notice and this permission notice shall be included in all copies or substantial portions of
- the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
- TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
- CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
- DEALINGS IN THE SOFTWARE.
- */
- #endregion
- namespace Tesseraction.Functions
- {
- public static class ByteFunctions
- {
- private static readonly Encoding defaultStringEncoding = Encoding.UTF8;
- public static readonly byte [] XorSaltBytes = {4, 8, 15, 16, 23, 42, 73, 108, 136, 222};
- private static readonly Regex validBase64Regex = new Regex ("^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$");
- public static byte [] CombineBytes (byte [] bytes1, byte [] bytes2)
- {
- if (bytes1 == null)
- {
- throw new ArgumentNullException (nameof (bytes1));
- }
- if (bytes2 == null)
- {
- throw new ArgumentNullException (nameof (bytes2));
- }
- if (bytes1.Length + bytes2.Length == 0)
- {
- throw new ArgumentOutOfRangeException (nameof (bytes1));
- }
- // Combine the two byte arrays into a new one the size of both
- byte [] combinedBytes = new byte [bytes1.Length + bytes2.Length];
- if (bytes1.Length > 0)
- {
- Buffer.BlockCopy (bytes1, 0, combinedBytes, 0, bytes1.Length);
- }
- if (bytes2.Length > 0)
- {
- Buffer.BlockCopy (bytes2, 0, combinedBytes, bytes1.Length, bytes2.Length);
- }
- return combinedBytes;
- }
- public static void SplitBytes (byte [] bytes, int splitPoint, out byte [] bytes1, out byte [] bytes2)
- {
- if (bytes == null ||
- bytes.Length == 0)
- {
- throw new ArgumentNullException (nameof (bytes));
- }
- if (splitPoint <= 0 || splitPoint >= bytes.Length)
- {
- throw new ArgumentOutOfRangeException (nameof (splitPoint));
- }
- // First output array is all bytes up to split point
- // E.g. for a split point of 5, this will be bytes 0-4
- byte [] splitBytes1 = new byte [splitPoint];
- // Second output is all bytes from split point to end
- // E.g. for a 10 byte array with split point of 5, this will be bytes 5-9
- byte [] splitBytes2 = new byte [bytes.Length - splitPoint];
- Buffer.BlockCopy (bytes, 0, splitBytes1, 0, splitPoint);
- Buffer.BlockCopy (bytes, splitPoint, splitBytes2, 0, splitBytes2.Length);
- bytes1 = splitBytes1;
- bytes2 = splitBytes2;
- }
- public static byte [] CombineByteArrays (params byte [] [] byteArrays)
- {
- if (byteArrays == null || byteArrays.Length == 0)
- {
- throw new ArgumentNullException (nameof (byteArrays));
- }
- List<byte> metadata = new List<byte> ();
- metadata.AddRange (BitConverter.GetBytes (byteArrays.Length));
- int totalLength = 0;
- foreach (byte [] array in byteArrays)
- {
- if (array == null || array.Length == 0)
- {
- metadata.AddRange (BitConverter.GetBytes (0));
- continue;
- }
- totalLength += array.Length;
- metadata.AddRange (BitConverter.GetBytes (array.Length));
- }
- if (totalLength == 0)
- {
- throw new ArgumentOutOfRangeException (nameof (byteArrays));
- }
- // Combine the multiple byte arrays into a new one the size of all of them, prefixed by metadata
- byte [] combinedBytes = new byte [totalLength + metadata.Count];
- Buffer.BlockCopy (metadata.ToArray (), 0, combinedBytes, 0, metadata.Count);
- int index = metadata.Count;
- foreach (byte [] array in byteArrays)
- {
- if (array == null || array.Length == 0)
- {
- continue;
- }
- Buffer.BlockCopy (array, 0, combinedBytes, index, array.Length);
- index += array.Length;
- }
- return combinedBytes;
- }
- // ReSharper disable once ReturnTypeCanBeEnumerable.Global
- public static byte [] [] SplitByteArrays (byte [] bytes, IEnumerable<int> predeterminedExpectedArray = null)
- {
- if (bytes == null || bytes.Length == 0)
- {
- throw new ArgumentNullException (nameof (bytes));
- }
- int expectedArrayCount;
- List<int> expectedArrayLengths = new List<int> ();
- int index = 0;
- if (predeterminedExpectedArray != null)
- {
- expectedArrayLengths = predeterminedExpectedArray.ToList ();
- expectedArrayCount = expectedArrayLengths.Count;
- }
- else
- {
- expectedArrayCount = (int) Convert.ChangeType (BitConverter.ToInt32 (bytes, 0), typeof (int));
- index = sizeof (int);
- int totalLength = 0;
- for (int i = 0; i < expectedArrayCount; i++)
- {
- int arrayLength = (int) Convert.ChangeType (BitConverter.ToInt32 (bytes, index), typeof (int));
- expectedArrayLengths.Add (arrayLength);
- totalLength += arrayLength;
- index += sizeof (int);
- }
- if (totalLength + index != bytes.Length)
- {
- throw new ArgumentOutOfRangeException (nameof (bytes), "Got " + (totalLength + index).ToString ("N0") +
- " bytes when expecting " + bytes.Length.ToString ("N0"));
- }
- }
- byte [] [] byteArrays = new byte [expectedArrayCount] [];
- for (int i = 0; i < expectedArrayCount; i++)
- {
- byteArrays [i] = new byte [expectedArrayLengths [i]];
- Buffer.BlockCopy (bytes, index, byteArrays [i], 0, expectedArrayLengths [i]);
- index += expectedArrayLengths [i];
- }
- return byteArrays;
- }
- public static byte [] SnipBytes (byte [] bytes, int startPoint, int length)
- {
- if (bytes == null ||
- bytes.Length == 0)
- {
- throw new ArgumentNullException (nameof (bytes));
- }
- if (startPoint < 0 || startPoint >= bytes.Length)
- {
- throw new ArgumentOutOfRangeException (nameof (startPoint));
- }
- if (length <= 0 || length > bytes.Length - startPoint)
- {
- throw new ArgumentOutOfRangeException (nameof (length));
- }
- byte [] snippedBytes = new byte [length];
- Buffer.BlockCopy (bytes, startPoint, snippedBytes, 0, length);
- return snippedBytes;
- }
- public static bool CompareBytes (byte [] bytes1, byte [] bytes2)
- {
- if (bytes1 == null ||
- bytes1.Length == 0)
- {
- throw new ArgumentNullException (nameof (bytes1));
- }
- if (bytes2 == null ||
- bytes2.Length == 0)
- {
- throw new ArgumentNullException (nameof (bytes2));
- }
- // Check equality at reference level, i.e. same reference is already equal
- if (bytes1 == bytes2)
- {
- return true;
- }
- // Check for match on length
- if (bytes1.Length != bytes2.Length)
- {
- return false;
- }
- // Note: it seems that using LINQ on iOS is still a bit dodgy with JIT compiler, hence using this loop here rather than SequenceEqual method
- bool matched = true;
- int bytes1Length = bytes1.Length;
- for (int i = 0; i < bytes1Length; i++)
- {
- if (bytes1 [i] == bytes2 [i])
- {
- continue;
- }
- matched = false;
- break;
- }
- return matched;
- }
- public static byte [] ScrambleBytes (byte [] bytes, byte [] xorSaltBytes, int scrambleXor)
- {
- if (bytes == null ||
- bytes.Length == 0)
- {
- throw new ArgumentNullException (nameof (bytes));
- }
- if (xorSaltBytes == null ||
- xorSaltBytes.Length == 0)
- {
- throw new ArgumentNullException (nameof (xorSaltBytes));
- }
- if (scrambleXor < 1 || scrambleXor > 255)
- {
- throw new ArgumentOutOfRangeException (nameof (scrambleXor));
- }
- int bytesLength = bytes.Length;
- byte [] scrambledBytes = new byte [bytesLength];
- // Derive scrambler as a product of XOR value and the byte array length
- // Then pass it through the XOR salts
- int scrambler = bytesLength * scrambleXor;
- int xorSaltBytesLength = xorSaltBytes.Length;
- for (int i = 0; i < xorSaltBytesLength; i++)
- {
- if (xorSaltBytes [i] > 0)
- {
- scrambler += (i + 1) * xorSaltBytes [i];
- }
- }
- // Loop through and scramble each byte, then place it in reverse order
- for (int i = 0; i < bytesLength; i++)
- {
- // Formula is ((length * index^2) + scrambler) % 256
- byte scrambleByte = (byte) ((bytesLength * i * i + scrambler) % 256);
- // Place it in reverse order and scramble using XOR at the same time
- scrambledBytes [bytesLength - i - 1] = (byte) (bytes [i] ^ scrambleByte);
- }
- return scrambledBytes;
- }
- public static byte [] ScrambleBytes (byte [] bytes, int scrambleXor)
- {
- return ScrambleBytes (bytes, XorSaltBytes, scrambleXor);
- }
- public static byte [] UnscrambleBytes (byte [] bytes, byte [] xorSaltBytes, int scrambleXor)
- {
- if (bytes == null ||
- bytes.Length == 0)
- {
- throw new ArgumentNullException (nameof (bytes));
- }
- if (xorSaltBytes == null ||
- xorSaltBytes.Length == 0)
- {
- throw new ArgumentNullException (nameof (xorSaltBytes));
- }
- if (scrambleXor < 1 || scrambleXor > 255)
- {
- throw new ArgumentOutOfRangeException (nameof (scrambleXor));
- }
- int bytesLength = bytes.Length;
- byte [] unscrambledBytes = new byte [bytesLength];
- // Derive scrambler as a product of XOR value and the byte array length
- // Then pass it through the XOR salts
- int scrambler = bytesLength * scrambleXor;
- int xorSaltBytesLength = xorSaltBytes.Length;
- for (int i = 0; i < xorSaltBytesLength; i++)
- {
- if (xorSaltBytes [i] > 0)
- {
- scrambler += (i + 1) * xorSaltBytes [i];
- }
- }
- // Loop through and unscramble each byte, then place it back in original order
- for (int i = 0; i < bytesLength; i++)
- {
- // Formula is ((length * reverse index^2) + scrambler) % 256
- int reverseIndex = bytesLength - i - 1;
- byte scrambleByte = (byte) ((bytesLength * reverseIndex * reverseIndex + scrambler) % 256);
- // Place it in reverse order and unscramble using XOR at the same time
- unscrambledBytes [bytesLength - i - 1] = (byte) (bytes [i] ^ scrambleByte);
- }
- return unscrambledBytes;
- }
- public static byte [] UnscrambleBytes (byte [] bytes, int scrambleXor)
- {
- return UnscrambleBytes (bytes, XorSaltBytes, scrambleXor);
- }
- public static bool IsPotentiallyValidBase64String (string stringValue)
- {
- return !(string.IsNullOrEmpty (stringValue) ||
- stringValue.Length % 4 != 0 ||
- !validBase64Regex.Match (stringValue).Success);
- }
- public static byte [] ConvertStringToBytes (
- string stringValue,
- Encoding stringEncoding = null,
- bool convertQuietly = false)
- {
- if (!string.IsNullOrEmpty (stringValue))
- {
- if (stringEncoding == null)
- {
- stringEncoding = defaultStringEncoding;
- }
- return stringEncoding.GetBytes (stringValue);
- }
- if (convertQuietly)
- {
- return null;
- }
- throw new ArgumentNullException (nameof (stringValue));
- }
- public static byte [] ConvertBase64StringToBytes (string stringValue, bool convertQuietly = false)
- {
- if (!string.IsNullOrEmpty (stringValue))
- {
- return Convert.FromBase64String (stringValue);
- }
- if (convertQuietly)
- {
- return null;
- }
- throw new ArgumentNullException (nameof (stringValue));
- }
- public static string ConvertBytesToString (
- byte [] bytes,
- Encoding stringEncoding = null,
- bool convertQuietly = false)
- {
- if (bytes != null && bytes.Length != 0)
- {
- if (stringEncoding == null)
- {
- stringEncoding = defaultStringEncoding;
- }
- return stringEncoding.GetString (bytes);
- }
- if (convertQuietly)
- {
- return string.Empty;
- }
- throw new ArgumentNullException (nameof (bytes));
- }
- public static string ConvertBytesToBase64String (byte [] bytes, bool convertQuietly = false)
- {
- if (bytes != null && bytes.Length != 0)
- {
- return Convert.ToBase64String (bytes);
- }
- if (convertQuietly)
- {
- return string.Empty;
- }
- throw new ArgumentNullException (nameof (bytes));
- }
- }
- }
Add Comment
Please, Sign In to add comment