restructure

swoom
This commit is contained in:
Malloc of Kuzkycyziklistan 2017-05-08 16:06:17 -05:00
parent 583182e81b
commit bea5eafbf8
20 changed files with 292 additions and 178 deletions

View file

@ -101,7 +101,6 @@
<Compile Include="Socks\PendingConnection.cs" /> <Compile Include="Socks\PendingConnection.cs" />
<Compile Include="Socks\PoolManager.cs" /> <Compile Include="Socks\PoolManager.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Utilities.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="App.config"> <None Include="App.config">
@ -125,12 +124,6 @@
<Folder Include="Assets\Shaders\" /> <Folder Include="Assets\Shaders\" />
<Folder Include="Assets\Textures\" /> <Folder Include="Assets\Textures\" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<ProjectReference Include="Kneesocks\Kneesocks.csproj">
<Project>{347353f6-cecd-4895-8717-2b5394ac71cc}</Project>
<Name>Kneesocks</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup> <ItemGroup>
<Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" /> <Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" />
</ItemGroup> </ItemGroup>
@ -150,6 +143,16 @@
<DependentUpon>App.config</DependentUpon> <DependentUpon>App.config</DependentUpon>
</Content> </Content>
</ItemGroup> </ItemGroup>
<ItemGroup>
<ProjectReference Include="Libraries\Kneesocks\Kneesocks.csproj">
<Project>{347353f6-cecd-4895-8717-2b5394ac71cc}</Project>
<Name>Kneesocks</Name>
</ProjectReference>
<ProjectReference Include="Libraries\Square\Square.csproj">
<Project>{054f172e-9683-40bc-8bdd-7671340ec193}</Project>
<Name>Square</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="packages\System.Data.SQLite.Core.1.0.105.0\build\net46\System.Data.SQLite.Core.targets" Condition="Exists('packages\System.Data.SQLite.Core.1.0.105.0\build\net46\System.Data.SQLite.Core.targets')" /> <Import Project="packages\System.Data.SQLite.Core.1.0.105.0\build\net46\System.Data.SQLite.Core.targets" Condition="Exists('packages\System.Data.SQLite.Core.1.0.105.0\build\net46\System.Data.SQLite.Core.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild"> <Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">

View file

@ -5,7 +5,9 @@ VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CircleScape", "CircleScape.csproj", "{438DBAC1-BA37-40BB-9CCE-0FE1F23C6DC5}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CircleScape", "CircleScape.csproj", "{438DBAC1-BA37-40BB-9CCE-0FE1F23C6DC5}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kneesocks", "Kneesocks\Kneesocks.csproj", "{347353F6-CECD-4895-8717-2B5394AC71CC}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kneesocks", "Libraries\Kneesocks\Kneesocks.csproj", "{347353F6-CECD-4895-8717-2B5394AC71CC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Square", "Libraries\Square\Square.csproj", "{054F172E-9683-40BC-8BDD-7671340EC193}"
EndProject EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -21,6 +23,10 @@ Global
{347353F6-CECD-4895-8717-2B5394AC71CC}.Debug|Any CPU.Build.0 = Debug|Any CPU {347353F6-CECD-4895-8717-2B5394AC71CC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{347353F6-CECD-4895-8717-2B5394AC71CC}.Release|Any CPU.ActiveCfg = Release|Any CPU {347353F6-CECD-4895-8717-2B5394AC71CC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{347353F6-CECD-4895-8717-2B5394AC71CC}.Release|Any CPU.Build.0 = Release|Any CPU {347353F6-CECD-4895-8717-2B5394AC71CC}.Release|Any CPU.Build.0 = Release|Any CPU
{054F172E-9683-40BC-8BDD-7671340EC193}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{054F172E-9683-40BC-8BDD-7671340EC193}.Debug|Any CPU.Build.0 = Debug|Any CPU
{054F172E-9683-40BC-8BDD-7671340EC193}.Release|Any CPU.ActiveCfg = Release|Any CPU
{054F172E-9683-40BC-8BDD-7671340EC193}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View file

@ -1,74 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Kneesocks {
public static class StringExtensions {
public enum kHashReturnType {
RAW, HEX, BASE64
}
public static byte[] GetBytes(this string str, bool isUtf8 = true) {
return isUtf8 ? Encoding.UTF8.GetBytes(str)
: Encoding.ASCII.GetBytes(str);
}
public static int ByteLength(this string str, bool isUtf8 = true) {
return isUtf8 ? Encoding.UTF8.GetByteCount(str)
: Encoding.ASCII.GetByteCount(str);
}
public static string Base64Encode(this string str, bool isUtf8 = true) {
var raw =
isUtf8 ? Encoding.UTF8.GetBytes(str)
: Encoding.ASCII.GetBytes(str);
return Convert.ToBase64String(raw);
}
public static string Base64Decode(this string str, bool isUtf8 = true) {
var raw = Convert.FromBase64String(str);
return isUtf8 ? Encoding.UTF8.GetString(raw)
: Encoding.ASCII.GetString(raw);
}
public static string SHA1(this string str, kHashReturnType type = kHashReturnType.RAW) {
using(var hasher = System.Security.Cryptography.SHA1.Create()) {
return ParseRawHash(
hasher.ComputeHash(str.GetBytes(false)),
type
);
}
}
public static string MD5(this string str, kHashReturnType type = kHashReturnType.RAW) {
using(var hasher = System.Security.Cryptography.MD5.Create()) {
return ParseRawHash(
hasher.ComputeHash(str.GetBytes(false)),
type
);
}
}
private static string ParseRawHash(byte[] hash, kHashReturnType type) {
var raw = Encoding.ASCII.GetString(hash);
switch(type) {
case kHashReturnType.BASE64:
return Base64Encode(raw, false);
case kHashReturnType.HEX:
return BitConverter.ToString(hash).Replace("-", "");
case kHashReturnType.RAW:
default:
return raw;
}
}
}
public static class NumericExtensions {
/*public static T Unpack<T>(this byte[] bytes, int offset = 0) {
return 0;
}*/
}
}

View file

@ -32,9 +32,7 @@ namespace Kneesocks {
public string DisconnectReason { get; private set; } = null; public string DisconnectReason { get; private set; } = null;
public bool Handshaked { get; private set; } = false; public bool Handshaked { get; private set; } = false;
private string RawClientHandshake = ""; public Handshake ClientHandshake { get; private set; } = null;
private Dictionary<string, string> Headers =
new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
public Connection(TcpClient sock) { public Connection(TcpClient sock) {
Socket = sock; Socket = sock;
@ -62,30 +60,51 @@ namespace Kneesocks {
DisconnectReason = conn.DisconnectReason; DisconnectReason = conn.DisconnectReason;
Handshaked = conn.Handshaked; Handshaked = conn.Handshaked;
RawClientHandshake = conn.RawClientHandshake; ClientHandshake = conn.ClientHandshake;
Headers = conn.Headers;
}
private void StartRead(ulong length) {
} }
public byte[] Parse() { public byte[] Parse() {
byte[] readBuffer = null; byte[] readBuffer = null;
if(Buffer.IsReading) { if(Buffer.IsReading) {
readBuffer = Buffer.AttemptRead(); readBuffer = Buffer.AttemptRead();
if(readBuffer == null) if(readBuffer == null) {
if(Buffer.ElapsedReadTime.Seconds > 30)
Disconnect(Frame.kClosingReason.ProtocolError, "Timed out waiting for a full response");
return null; return null;
}
} }
if(!Handshaked) { if(!Handshaked) {
if(Stream.) if(!Buffer.IsReading) {
readBuffer = Buffer.AttemptRead("\r\n\r\n");
return null; if(readBuffer == null)
} else { return null;
}
OnParse(); try {
Handshake request = new Handshake(Encoding.ASCII.GetString(readBuffer));
var response = Handshake.AcceptRequest(request).ToBytes();
Stream.Write(response, 0, response.Length);
ClientHandshake = request;
Handshaked = true;
} catch(Exception e) {
Disconnect(Frame.kClosingReason.ProtocolError, e.Message);
return null;
}
OnOpen();
return null;
} }
/*if(!Buffer.IsReading) {
readBuffer = Buffer.AttemptRead("\r\n\r\n");
if(readBuffer == null)
return null;
}*/
OnParse();
return null;
} }
public void Disconnect(string reason = null) { public void Disconnect(string reason = null) {

View file

@ -27,7 +27,7 @@ namespace Kneesocks {
Service_Unavailable = 503, Service_Unavailable = 503,
Gateway_Timeout = 504 Gateway_Timeout = 504
} }
public kStatusCode StatusCode { get; private set; } = kStatusCode.Switching_Protocols; public kStatusCode StatusCode { get; private set; } = kStatusCode.Switching_Protocols;
protected string StatusCodeText { protected string StatusCodeText {
get { get {
@ -44,25 +44,23 @@ namespace Kneesocks {
throw new FormatException("Header delimeter not found in raw data"); throw new FormatException("Header delimeter not found in raw data");
var header = rawData.Substring(0, headerLength); var header = rawData.Substring(0, headerLength);
if(!header.StartsWith("HTTP/")) if(!header.StartsWith("GET ") || !header.Contains("HTTP/"))
throw new FormatException("Protocol defined in status line not understood"); throw new FormatException("Protocol defined in status line not understood");
var lines = header.Split('\n'); var lines = header.Split('\n');
foreach(var line in lines) { foreach(var line in lines) {
string[] parts; string[] parts;
if(line.StartsWith("HTTP/")) { if(line.StartsWith("GET ")) {
parts = line.Trim().Split(' '); parts = line.Trim().Split(' ');
if(parts.Length < 2) if(parts.Length < 3)
throw new FormatException("Status line in header malformed"); throw new FormatException("Status line in header malformed");
int code; /*int code;
if(!int.TryParse(parts[1], out code)) if(!int.TryParse(parts[1], out code))
throw new FormatException("Status code sent is not a number"); throw new FormatException("Status code sent is not a number");*/
if(!Enum.IsDefined(typeof(kStatusCode), code)) /*if(!Enum.IsDefined(typeof(kStatusCode), code))
throw new NotSupportedException("Status code not supported"); throw new NotSupportedException("Status code not supported");*/
StatusCode = (kStatusCode)code;
} else { } else {
parts = line.Trim().Split(new char[] {':'}, 2); parts = line.Trim().Split(new char[] {':'}, 2);
if(parts.Length == 2) if(parts.Length == 2)
@ -88,6 +86,8 @@ namespace Kneesocks {
var key = request.GetHeader("Sec-WebSocket-Key"); var key = request.GetHeader("Sec-WebSocket-Key");
var connectionHash = (key + nonce).SHA1().Base64Encode(false); var connectionHash = (key + nonce).SHA1().Base64Encode(false);
var test = ("dGhlIHNhbXBsZSBub25jZQ==" + nonce).SHA1().Base64Encode(false);
var shake = new Handshake(kStatusCode.Switching_Protocols); var shake = new Handshake(kStatusCode.Switching_Protocols);
shake.SetHeader("Upgrade", "websocket") shake.SetHeader("Upgrade", "websocket")
.SetHeader("Connection", "Upgrade") .SetHeader("Connection", "Upgrade")
@ -99,6 +99,10 @@ namespace Kneesocks {
return new Handshake(statusCode, message); return new Handshake(statusCode, message);
} }
public byte[] ToBytes() {
return Encoding.ASCII.GetBytes(ToString());
}
public override string ToString() { public override string ToString() {
if(Content != null) { if(Content != null) {
SetHeader("Content-Length", Content.ByteLength().ToString()); SetHeader("Content-Length", Content.ByteLength().ToString());

View file

@ -50,6 +50,12 @@
<Compile Include="Stack.cs" /> <Compile Include="Stack.cs" />
<Compile Include="Utilities.cs" /> <Compile Include="Utilities.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Square\Square.csproj">
<Project>{054f172e-9683-40bc-8bdd-7671340ec193}</Project>
<Name>Square</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.

View file

@ -93,7 +93,8 @@ namespace Kneesocks {
Stack = stack, Stack = stack,
Thread = new Thread(new ThreadStart(stack.ManageStack)) Thread = new Thread(new ThreadStart(stack.ManageStack))
}; };
ctx.Thread.Start();
Threads.Add(ctx); Threads.Add(ctx);
updateFullThreadCount = true; updateFullThreadCount = true;
return ctx; return ctx;

View file

@ -17,6 +17,7 @@ namespace Kneesocks {
public ReadBuffer(NetworkStream source) { public ReadBuffer(NetworkStream source) {
Source = source; Source = source;
Buffer = new List<byte>();
} }
public TimeSpan ElapsedReadTime { public TimeSpan ElapsedReadTime {

View file

@ -46,13 +46,9 @@ namespace Kneesocks {
// USED FOR THREADING -- DO NOT CALL // USED FOR THREADING -- DO NOT CALL
public void ManageStack() { public void ManageStack() {
while(Running && (Count > 0 || RunWithNoClients)) { while(Running && (Count > 0 || RunWithNoClients)) {
for(var i = Count - 1; i >= 0 && Running; ++i) { for(var i = Count - 1; i >= 0 && Running; --i) {
var client = Clients[i]; var client = Clients[i];
if(client.Handshaked) { client.Parse();
} else {
}
} }
} }

View file

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace Kneesocks {
public static class StringExtensions {
}
public static class ByteArrayExtensions {
}
public static class CryptoExtensions {
}
}

View file

@ -0,0 +1,13 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Square {
public static class ByteArrayExtensions {
public static string Base64Encode(this byte[] bytes) {
return Convert.ToBase64String(bytes);
}
}
}

View file

@ -0,0 +1,44 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace Square {
public static class CryptoExtensions {
public enum kHashReturnType {
RAW, HEX, BASE64
}
public static string SHA1(this string str, kHashReturnType type = kHashReturnType.RAW) {
using(var hasher = new SHA1CryptoServiceProvider()) {
return ParseRawHash(
hasher.ComputeHash(str.GetBytes(false)),
type
);
}
}
public static string MD5(this string str, kHashReturnType type = kHashReturnType.RAW) {
using(var hasher = new MD5CryptoServiceProvider()) {
return ParseRawHash(
hasher.ComputeHash(str.GetBytes(false)),
type
);
}
}
private static string ParseRawHash(byte[] hash, kHashReturnType type) {
switch(type) {
case kHashReturnType.BASE64:
return hash.Base64Encode(false);
case kHashReturnType.HEX:
return BitConverter.ToString(hash).Replace("-", "");
case kHashReturnType.RAW:
default:
return hash;
}
}
}
}

View file

@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Square {
public static class NumericExtensions {
}
}

View file

@ -0,0 +1,36 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Square")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Square")]
[assembly: AssemblyCopyright("Copyright © 2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("054f172e-9683-40bc-8bdd-7671340ec193")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View file

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{054F172E-9683-40BC-8BDD-7671340EC193}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Square</RootNamespace>
<AssemblyName>Square</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="ByteArrayExtensions.cs" />
<Compile Include="CryptoExtensions.cs" />
<Compile Include="NumericExtensions.cs" />
<Compile Include="StringExtensions.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View file

@ -0,0 +1,36 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Square {
public static class StringExtensions {
public static byte[] GetBytes(this string str, bool isUtf8 = true) {
return isUtf8 ? Encoding.UTF8.GetBytes(str)
: Encoding.ASCII.GetBytes(str);
}
public static int ByteLength(this string str, bool isUtf8 = true) {
return isUtf8 ? Encoding.UTF8.GetByteCount(str)
: Encoding.ASCII.GetByteCount(str);
}
public static string Base64Encode(this string str, bool isUtf8 = true) {
var raw =
isUtf8 ? Encoding.UTF8.GetBytes(str)
: Encoding.ASCII.GetBytes(str);
return Convert.ToBase64String(raw);
}
public static string Base64Decode(this string str, bool isUtf8 = true) {
var raw = Convert.FromBase64String(str);
return isUtf8 ? Encoding.UTF8.GetString(raw)
: Encoding.ASCII.GetString(raw);
}
public static byte[] Base64DecodeRaw(this string str) {
return Convert.FromBase64String(str);
}
}
}

View file

@ -1,64 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
namespace CircleScape {
public static class StringExtensions {
public enum kHashReturnType {
RAW, HEX, BASE64
}
public static string Base64Encode(this string str, bool isUtf8 = true) {
var raw =
isUtf8 ? Encoding.UTF8.GetBytes(str)
: Encoding.ASCII.GetBytes(str);
return Convert.ToBase64String(raw);
}
public static string Base64Decode(this string str, bool isUtf8 = true) {
var raw = Convert.FromBase64String(str);
return isUtf8 ? Encoding.UTF8.GetString(raw)
: Encoding.ASCII.GetString(raw);
}
public static string SHA1(this string str, kHashReturnType type = kHashReturnType.RAW) {
using(var hasher = System.Security.Cryptography.SHA1.Create()) {
return ParseRawHash(
hasher.ComputeHash(Encoding.ASCII.GetBytes(str)),
type
);
}
}
public static string MD5(this string str, kHashReturnType type = kHashReturnType.RAW) {
using(var hasher = System.Security.Cryptography.MD5.Create()) {
return ParseRawHash(
hasher.ComputeHash(Encoding.ASCII.GetBytes(str)),
type
);
}
}
private static string ParseRawHash(byte[] hash, kHashReturnType type) {
var raw = Encoding.ASCII.GetString(hash);
switch(type) {
case kHashReturnType.BASE64:
return Base64Encode(raw, false);
case kHashReturnType.HEX:
return BitConverter.ToString(hash).Replace("-", "");
case kHashReturnType.RAW:
default:
return raw;
}
}
}
public static class NumericExtensions {
}
}