using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using OtpSharp; namespace ArchBreaker { static class ArchSecurity { public static string GenerateAssertion(string issuer) { var totpObj = new Totp(Encoding.UTF8.GetBytes(issuer), step: 600, totpSize: 8); var totp = totpObj.ComputeTotp(); var payload = new Dictionary() { {"aud", Constants.BaasBaseURL}, {"iss", issuer} }; return Jose.JWT.Encode(payload, Encoding.UTF8.GetBytes(totp), Jose.JwsAlgorithm.HS256); } public static byte[] ComputeKey(string commonKey, string sessionID) { var commonBytes = Encoding.ASCII.GetBytes(commonKey); var sessionBytes = Encoding.ASCII.GetBytes(sessionID); var result = new byte[commonBytes.Length + sessionBytes.Length]; for (int i = 0; i < commonBytes.Length; i++) result[i] = (byte)(0x9E - commonBytes[i]); Array.Copy(sessionBytes, 0, result, commonBytes.Length, sessionBytes.Length); return result; } public static void TransformPacket(byte[] packet, byte[] key, bool encrypt) { for (int i = 0; i < packet.Length; i++) { int keyOffset = (i + 1) % key.Length; int rot = key[keyOffset] & 7; if (rot == 0) packet[i] ^= key[keyOffset]; else { if (encrypt) rot = 8 - rot; packet[i] = (byte)((packet[i] >> (8 - rot)) | (packet[i] << rot)); } } } public static byte[] DecompressPacket(byte[] input) { var hdr = ReadLZ4Header(input); int destSize = hdr.Item1, offset = hdr.Item2; var output = new byte[destSize]; LZ4PCL.LZ4Codec.Decode( input, offset, input.Length - offset, output, 0, destSize, true); return output; } public static byte[] CompressPacket(byte[] input) { var buf = new byte[LZ4PCL.LZ4Codec.MaximumOutputLength(input.Length)]; int realSize = LZ4PCL.LZ4Codec.Encode( input, 0, input.Length, buf, 0, buf.Length); // Pack the header for ruby-lz4 compat var header = new byte[5]; int headerSize = 0; int inputSize = input.Length; do { byte b = (byte)(inputSize & 0x7F); inputSize >>= 7; if (inputSize == 0) header[headerSize++] = b; else header[headerSize++] = (byte)(b | 0x80); } while (inputSize != 0); // Combine header + output into one final array var output = new byte[headerSize + realSize]; Array.Copy(header, 0, output, 0, headerSize); Array.Copy(buf, 0, output, headerSize, realSize); return output; } private static Tuple ReadLZ4Header(byte[] buffer) { int destSize = 0; for (int i = 0; i < 5; i++) { int v = buffer[i]; destSize |= ((v & 0x7F) << (7 * i)); if ((v & 0x80) == 0) return new Tuple(destSize, i + 1); } return new Tuple(-1, -1); } private static readonly Random _prng = new Random(); public static string RandomString(int size) { const string pool = "abcdefghijklmnopqrstuvwyxzABCDEFGHIJKLMNOPRSTUVWXYZ0123456789"; var result = new char[size]; for (int i = 0; i < size; i++) result[i] = pool[_prng.Next(pool.Length)]; return new string(result); } } }