chmodseven

Byte Functions

Jan 7th, 2021 (edited)
106
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 15.92 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Text.RegularExpressions;
  6.  
  7. // ReSharper disable UnusedMember.Global
  8.  
  9. #region MIT LICENSE
  10.  
  11. /*
  12.     License: The MIT License (MIT)
  13.     Copyright (C) 2021 Shannon Rowe
  14.    
  15.     Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
  16.     documentation files (the "Software"), to deal in the Software without restriction, including without limitation
  17.     the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
  18.     and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
  19.  
  20.     The above copyright notice and this permission notice shall be included in all copies or substantial portions of
  21.     the Software.
  22.    
  23.     THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
  24.     TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  25.     THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
  26.     CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  27.     DEALINGS IN THE SOFTWARE.
  28. */
  29.  
  30. #endregion
  31.  
  32. namespace Tesseraction.Functions
  33. {
  34.     public static class ByteFunctions
  35.     {
  36.         private static readonly Encoding defaultStringEncoding = Encoding.UTF8;
  37.  
  38.         public static readonly byte [] XorSaltBytes = {4, 8, 15, 16, 23, 42, 73, 108, 136, 222};
  39.         private static readonly Regex validBase64Regex = new Regex ("^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=)?$");
  40.  
  41.  
  42.         public static byte [] CombineBytes (byte [] bytes1, byte [] bytes2)
  43.         {
  44.             if (bytes1 == null)
  45.             {
  46.                 throw new ArgumentNullException (nameof (bytes1));
  47.             }
  48.  
  49.             if (bytes2 == null)
  50.             {
  51.                 throw new ArgumentNullException (nameof (bytes2));
  52.             }
  53.  
  54.             if (bytes1.Length + bytes2.Length == 0)
  55.             {
  56.                 throw new ArgumentOutOfRangeException (nameof (bytes1));
  57.             }
  58.  
  59.             // Combine the two byte arrays into a new one the size of both
  60.             byte [] combinedBytes = new byte [bytes1.Length + bytes2.Length];
  61.             if (bytes1.Length > 0)
  62.             {
  63.                 Buffer.BlockCopy (bytes1, 0, combinedBytes, 0, bytes1.Length);
  64.             }
  65.  
  66.             if (bytes2.Length > 0)
  67.             {
  68.                 Buffer.BlockCopy (bytes2, 0, combinedBytes, bytes1.Length, bytes2.Length);
  69.             }
  70.  
  71.             return combinedBytes;
  72.         }
  73.  
  74.         public static void SplitBytes (byte [] bytes, int splitPoint, out byte [] bytes1, out byte [] bytes2)
  75.         {
  76.             if (bytes == null ||
  77.                 bytes.Length == 0)
  78.             {
  79.                 throw new ArgumentNullException (nameof (bytes));
  80.             }
  81.  
  82.             if (splitPoint <= 0 || splitPoint >= bytes.Length)
  83.             {
  84.                 throw new ArgumentOutOfRangeException (nameof (splitPoint));
  85.             }
  86.  
  87.             // First output array is all bytes up to split point
  88.             // E.g. for a split point of 5, this will be bytes 0-4
  89.             byte [] splitBytes1 = new byte [splitPoint];
  90.  
  91.             // Second output is all bytes from split point to end
  92.             // E.g. for a 10 byte array with split point of 5, this will be bytes 5-9
  93.             byte [] splitBytes2 = new byte [bytes.Length - splitPoint];
  94.  
  95.             Buffer.BlockCopy (bytes, 0, splitBytes1, 0, splitPoint);
  96.             Buffer.BlockCopy (bytes, splitPoint, splitBytes2, 0, splitBytes2.Length);
  97.  
  98.             bytes1 = splitBytes1;
  99.             bytes2 = splitBytes2;
  100.         }
  101.  
  102.         public static byte [] CombineByteArrays (params byte [] [] byteArrays)
  103.         {
  104.             if (byteArrays == null || byteArrays.Length == 0)
  105.             {
  106.                 throw new ArgumentNullException (nameof (byteArrays));
  107.             }
  108.  
  109.             List<byte> metadata = new List<byte> ();
  110.             metadata.AddRange (BitConverter.GetBytes (byteArrays.Length));
  111.  
  112.             int totalLength = 0;
  113.             foreach (byte [] array in byteArrays)
  114.             {
  115.                 if (array == null || array.Length == 0)
  116.                 {
  117.                     metadata.AddRange (BitConverter.GetBytes (0));
  118.                     continue;
  119.                 }
  120.  
  121.                 totalLength += array.Length;
  122.                 metadata.AddRange (BitConverter.GetBytes (array.Length));
  123.             }
  124.  
  125.             if (totalLength == 0)
  126.             {
  127.                 throw new ArgumentOutOfRangeException (nameof (byteArrays));
  128.             }
  129.  
  130.             // Combine the multiple byte arrays into a new one the size of all of them, prefixed by metadata
  131.             byte [] combinedBytes = new byte [totalLength + metadata.Count];
  132.             Buffer.BlockCopy (metadata.ToArray (), 0, combinedBytes, 0, metadata.Count);
  133.             int index = metadata.Count;
  134.  
  135.             foreach (byte [] array in byteArrays)
  136.             {
  137.                 if (array == null || array.Length == 0)
  138.                 {
  139.                     continue;
  140.                 }
  141.  
  142.                 Buffer.BlockCopy (array, 0, combinedBytes, index, array.Length);
  143.                 index += array.Length;
  144.             }
  145.  
  146.             return combinedBytes;
  147.         }
  148.  
  149.         // ReSharper disable once ReturnTypeCanBeEnumerable.Global
  150.         public static byte [] [] SplitByteArrays (byte [] bytes, IEnumerable<int> predeterminedExpectedArray = null)
  151.         {
  152.             if (bytes == null || bytes.Length == 0)
  153.             {
  154.                 throw new ArgumentNullException (nameof (bytes));
  155.             }
  156.  
  157.             int expectedArrayCount;
  158.             List<int> expectedArrayLengths = new List<int> ();
  159.             int index = 0;
  160.  
  161.             if (predeterminedExpectedArray != null)
  162.             {
  163.                 expectedArrayLengths = predeterminedExpectedArray.ToList ();
  164.                 expectedArrayCount = expectedArrayLengths.Count;
  165.             }
  166.             else
  167.             {
  168.                 expectedArrayCount = (int) Convert.ChangeType (BitConverter.ToInt32 (bytes, 0), typeof (int));
  169.                 index = sizeof (int);
  170.                 int totalLength = 0;
  171.                 for (int i = 0; i < expectedArrayCount; i++)
  172.                 {
  173.                     int arrayLength = (int) Convert.ChangeType (BitConverter.ToInt32 (bytes, index), typeof (int));
  174.                     expectedArrayLengths.Add (arrayLength);
  175.                     totalLength += arrayLength;
  176.                     index += sizeof (int);
  177.                 }
  178.  
  179.                 if (totalLength + index != bytes.Length)
  180.                 {
  181.                     throw new ArgumentOutOfRangeException (nameof (bytes), "Got " + (totalLength + index).ToString ("N0") +
  182.                                                                            " bytes when expecting " + bytes.Length.ToString ("N0"));
  183.                 }
  184.             }
  185.  
  186.             byte [] [] byteArrays = new byte [expectedArrayCount] [];
  187.             for (int i = 0; i < expectedArrayCount; i++)
  188.             {
  189.                 byteArrays [i] = new byte [expectedArrayLengths [i]];
  190.                 Buffer.BlockCopy (bytes, index, byteArrays [i], 0, expectedArrayLengths [i]);
  191.                 index += expectedArrayLengths [i];
  192.             }
  193.  
  194.             return byteArrays;
  195.         }
  196.  
  197.         public static byte [] SnipBytes (byte [] bytes, int startPoint, int length)
  198.         {
  199.             if (bytes == null ||
  200.                 bytes.Length == 0)
  201.             {
  202.                 throw new ArgumentNullException (nameof (bytes));
  203.             }
  204.  
  205.             if (startPoint < 0 || startPoint >= bytes.Length)
  206.             {
  207.                 throw new ArgumentOutOfRangeException (nameof (startPoint));
  208.             }
  209.  
  210.             if (length <= 0 || length > bytes.Length - startPoint)
  211.             {
  212.                 throw new ArgumentOutOfRangeException (nameof (length));
  213.             }
  214.  
  215.             byte [] snippedBytes = new byte [length];
  216.             Buffer.BlockCopy (bytes, startPoint, snippedBytes, 0, length);
  217.             return snippedBytes;
  218.         }
  219.  
  220.         public static bool CompareBytes (byte [] bytes1, byte [] bytes2)
  221.         {
  222.             if (bytes1 == null ||
  223.                 bytes1.Length == 0)
  224.             {
  225.                 throw new ArgumentNullException (nameof (bytes1));
  226.             }
  227.  
  228.             if (bytes2 == null ||
  229.                 bytes2.Length == 0)
  230.             {
  231.                 throw new ArgumentNullException (nameof (bytes2));
  232.             }
  233.  
  234.             // Check equality at reference level, i.e. same reference is already equal
  235.             if (bytes1 == bytes2)
  236.             {
  237.                 return true;
  238.             }
  239.  
  240.             // Check for match on length
  241.             if (bytes1.Length != bytes2.Length)
  242.             {
  243.                 return false;
  244.             }
  245.  
  246.             // 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
  247.             bool matched = true;
  248.             int bytes1Length = bytes1.Length;
  249.             for (int i = 0; i < bytes1Length; i++)
  250.             {
  251.                 if (bytes1 [i] == bytes2 [i])
  252.                 {
  253.                     continue;
  254.                 }
  255.  
  256.                 matched = false;
  257.                 break;
  258.             }
  259.  
  260.             return matched;
  261.         }
  262.  
  263.         public static byte [] ScrambleBytes (byte [] bytes, byte [] xorSaltBytes, int scrambleXor)
  264.         {
  265.             if (bytes == null ||
  266.                 bytes.Length == 0)
  267.             {
  268.                 throw new ArgumentNullException (nameof (bytes));
  269.             }
  270.  
  271.             if (xorSaltBytes == null ||
  272.                 xorSaltBytes.Length == 0)
  273.             {
  274.                 throw new ArgumentNullException (nameof (xorSaltBytes));
  275.             }
  276.  
  277.             if (scrambleXor < 1 || scrambleXor > 255)
  278.             {
  279.                 throw new ArgumentOutOfRangeException (nameof (scrambleXor));
  280.             }
  281.  
  282.             int bytesLength = bytes.Length;
  283.             byte [] scrambledBytes = new byte [bytesLength];
  284.  
  285.             // Derive scrambler as a product of XOR value and the byte array length
  286.             // Then pass it through the XOR salts
  287.             int scrambler = bytesLength * scrambleXor;
  288.             int xorSaltBytesLength = xorSaltBytes.Length;
  289.             for (int i = 0; i < xorSaltBytesLength; i++)
  290.             {
  291.                 if (xorSaltBytes [i] > 0)
  292.                 {
  293.                     scrambler += (i + 1) * xorSaltBytes [i];
  294.                 }
  295.             }
  296.  
  297.             // Loop through and scramble each byte, then place it in reverse order
  298.             for (int i = 0; i < bytesLength; i++)
  299.             {
  300.                 // Formula is ((length * index^2) + scrambler) % 256
  301.                 byte scrambleByte = (byte) ((bytesLength * i * i + scrambler) % 256);
  302.  
  303.                 // Place it in reverse order and scramble using XOR at the same time
  304.                 scrambledBytes [bytesLength - i - 1] = (byte) (bytes [i] ^ scrambleByte);
  305.             }
  306.  
  307.             return scrambledBytes;
  308.         }
  309.  
  310.         public static byte [] ScrambleBytes (byte [] bytes, int scrambleXor)
  311.         {
  312.             return ScrambleBytes (bytes, XorSaltBytes, scrambleXor);
  313.         }
  314.  
  315.         public static byte [] UnscrambleBytes (byte [] bytes, byte [] xorSaltBytes, int scrambleXor)
  316.         {
  317.             if (bytes == null ||
  318.                 bytes.Length == 0)
  319.             {
  320.                 throw new ArgumentNullException (nameof (bytes));
  321.             }
  322.  
  323.             if (xorSaltBytes == null ||
  324.                 xorSaltBytes.Length == 0)
  325.             {
  326.                 throw new ArgumentNullException (nameof (xorSaltBytes));
  327.             }
  328.  
  329.             if (scrambleXor < 1 || scrambleXor > 255)
  330.             {
  331.                 throw new ArgumentOutOfRangeException (nameof (scrambleXor));
  332.             }
  333.  
  334.             int bytesLength = bytes.Length;
  335.             byte [] unscrambledBytes = new byte [bytesLength];
  336.  
  337.             // Derive scrambler as a product of XOR value and the byte array length
  338.             // Then pass it through the XOR salts
  339.             int scrambler = bytesLength * scrambleXor;
  340.             int xorSaltBytesLength = xorSaltBytes.Length;
  341.             for (int i = 0; i < xorSaltBytesLength; i++)
  342.             {
  343.                 if (xorSaltBytes [i] > 0)
  344.                 {
  345.                     scrambler += (i + 1) * xorSaltBytes [i];
  346.                 }
  347.             }
  348.  
  349.             // Loop through and unscramble each byte, then place it back in original order
  350.             for (int i = 0; i < bytesLength; i++)
  351.             {
  352.                 // Formula is ((length * reverse index^2) + scrambler) % 256
  353.                 int reverseIndex = bytesLength - i - 1;
  354.                 byte scrambleByte = (byte) ((bytesLength * reverseIndex * reverseIndex + scrambler) % 256);
  355.  
  356.                 // Place it in reverse order and unscramble using XOR at the same time
  357.                 unscrambledBytes [bytesLength - i - 1] = (byte) (bytes [i] ^ scrambleByte);
  358.             }
  359.  
  360.             return unscrambledBytes;
  361.         }
  362.  
  363.         public static byte [] UnscrambleBytes (byte [] bytes, int scrambleXor)
  364.         {
  365.             return UnscrambleBytes (bytes, XorSaltBytes, scrambleXor);
  366.         }
  367.  
  368.         public static bool IsPotentiallyValidBase64String (string stringValue)
  369.         {
  370.             return !(string.IsNullOrEmpty (stringValue) ||
  371.                      stringValue.Length % 4 != 0 ||
  372.                      !validBase64Regex.Match (stringValue).Success);
  373.         }
  374.  
  375.         public static byte [] ConvertStringToBytes (
  376.             string stringValue,
  377.             Encoding stringEncoding = null,
  378.             bool convertQuietly = false)
  379.         {
  380.             if (!string.IsNullOrEmpty (stringValue))
  381.             {
  382.                 if (stringEncoding == null)
  383.                 {
  384.                     stringEncoding = defaultStringEncoding;
  385.                 }
  386.  
  387.                 return stringEncoding.GetBytes (stringValue);
  388.             }
  389.  
  390.             if (convertQuietly)
  391.             {
  392.                 return null;
  393.             }
  394.  
  395.             throw new ArgumentNullException (nameof (stringValue));
  396.         }
  397.  
  398.         public static byte [] ConvertBase64StringToBytes (string stringValue, bool convertQuietly = false)
  399.         {
  400.             if (!string.IsNullOrEmpty (stringValue))
  401.             {
  402.                 return Convert.FromBase64String (stringValue);
  403.             }
  404.  
  405.             if (convertQuietly)
  406.             {
  407.                 return null;
  408.             }
  409.  
  410.             throw new ArgumentNullException (nameof (stringValue));
  411.         }
  412.  
  413.         public static string ConvertBytesToString (
  414.             byte [] bytes,
  415.             Encoding stringEncoding = null,
  416.             bool convertQuietly = false)
  417.         {
  418.             if (bytes != null && bytes.Length != 0)
  419.             {
  420.                 if (stringEncoding == null)
  421.                 {
  422.                     stringEncoding = defaultStringEncoding;
  423.                 }
  424.  
  425.                 return stringEncoding.GetString (bytes);
  426.             }
  427.  
  428.             if (convertQuietly)
  429.             {
  430.                 return string.Empty;
  431.             }
  432.  
  433.             throw new ArgumentNullException (nameof (bytes));
  434.         }
  435.  
  436.         public static string ConvertBytesToBase64String (byte [] bytes, bool convertQuietly = false)
  437.         {
  438.             if (bytes != null && bytes.Length != 0)
  439.             {
  440.                 return Convert.ToBase64String (bytes);
  441.             }
  442.  
  443.             if (convertQuietly)
  444.             {
  445.                 return string.Empty;
  446.             }
  447.  
  448.             throw new ArgumentNullException (nameof (bytes));
  449.         }
  450.     }
  451. }
Add Comment
Please, Sign In to add comment