Initial commit

master
Avril 4 years ago
commit 4f440ca028
Signed by: flanchan
GPG Key ID: 284488987C31F630

360
.gitignore vendored

@ -0,0 +1,360 @@
## Ignore Visual Studio temporary files, build results, and
## files generated by popular Visual Studio add-ons.
##
## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
# User-specific files
*.rsuser
*.suo
*.user
*.userosscache
*.sln.docstates
# User-specific files (MonoDevelop/Xamarin Studio)
*.userprefs
# Mono auto generated files
mono_crash.*
# Build results
[Dd]ebug/
[Dd]ebugPublic/
[Rr]elease/
[Rr]eleases/
x64/
x86/
[Ww][Ii][Nn]32/
[Aa][Rr][Mm]/
[Aa][Rr][Mm]64/
bld/
[Bb]in/
[Oo]bj/
[Ll]og/
[Ll]ogs/
# Visual Studio 2015/2017 cache/options directory
.vs/
# Uncomment if you have tasks that create the project's static files in wwwroot
#wwwroot/
# Visual Studio 2017 auto generated files
Generated\ Files/
# MSTest test Results
[Tt]est[Rr]esult*/
[Bb]uild[Ll]og.*
# NUnit
*.VisualState.xml
TestResult.xml
nunit-*.xml
# Build Results of an ATL Project
[Dd]ebugPS/
[Rr]eleasePS/
dlldata.c
# Benchmark Results
BenchmarkDotNet.Artifacts/
# .NET Core
project.lock.json
project.fragment.lock.json
artifacts/
# ASP.NET Scaffolding
ScaffoldingReadMe.txt
# StyleCop
StyleCopReport.xml
# Files built by Visual Studio
*_i.c
*_p.c
*_h.h
*.ilk
*.meta
*.obj
*.iobj
*.pch
*.pdb
*.ipdb
*.pgc
*.pgd
*.rsp
*.sbr
*.tlb
*.tli
*.tlh
*.tmp
*.tmp_proj
*_wpftmp.csproj
*.log
*.vspscc
*.vssscc
.builds
*.pidb
*.svclog
*.scc
# Chutzpah Test files
_Chutzpah*
# Visual C++ cache files
ipch/
*.aps
*.ncb
*.opendb
*.opensdf
*.sdf
*.cachefile
*.VC.db
*.VC.VC.opendb
# Visual Studio profiler
*.psess
*.vsp
*.vspx
*.sap
# Visual Studio Trace Files
*.e2e
# TFS 2012 Local Workspace
$tf/
# Guidance Automation Toolkit
*.gpState
# ReSharper is a .NET coding add-in
_ReSharper*/
*.[Rr]e[Ss]harper
*.DotSettings.user
# TeamCity is a build add-in
_TeamCity*
# DotCover is a Code Coverage Tool
*.dotCover
# AxoCover is a Code Coverage Tool
.axoCover/*
!.axoCover/settings.json
# Coverlet is a free, cross platform Code Coverage Tool
coverage*[.json, .xml, .info]
# Visual Studio code coverage results
*.coverage
*.coveragexml
# NCrunch
_NCrunch_*
.*crunch*.local.xml
nCrunchTemp_*
# MightyMoose
*.mm.*
AutoTest.Net/
# Web workbench (sass)
.sass-cache/
# Installshield output folder
[Ee]xpress/
# DocProject is a documentation generator add-in
DocProject/buildhelp/
DocProject/Help/*.HxT
DocProject/Help/*.HxC
DocProject/Help/*.hhc
DocProject/Help/*.hhk
DocProject/Help/*.hhp
DocProject/Help/Html2
DocProject/Help/html
# Click-Once directory
publish/
# Publish Web Output
*.[Pp]ublish.xml
*.azurePubxml
# Note: Comment the next line if you want to checkin your web deploy settings,
# but database connection strings (with potential passwords) will be unencrypted
*.pubxml
*.publishproj
# Microsoft Azure Web App publish settings. Comment the next line if you want to
# checkin your Azure Web App publish settings, but sensitive information contained
# in these scripts will be unencrypted
PublishScripts/
# NuGet Packages
*.nupkg
# NuGet Symbol Packages
*.snupkg
# The packages folder can be ignored because of Package Restore
**/[Pp]ackages/*
# except build/, which is used as an MSBuild target.
!**/[Pp]ackages/build/
# Uncomment if necessary however generally it will be regenerated when needed
#!**/[Pp]ackages/repositories.config
# NuGet v3's project.json files produces more ignorable files
*.nuget.props
*.nuget.targets
# Microsoft Azure Build Output
csx/
*.build.csdef
# Microsoft Azure Emulator
ecf/
rcf/
# Windows Store app package directories and files
AppPackages/
BundleArtifacts/
Package.StoreAssociation.xml
_pkginfo.txt
*.appx
*.appxbundle
*.appxupload
# Visual Studio cache files
# files ending in .cache can be ignored
*.[Cc]ache
# but keep track of directories ending in .cache
!?*.[Cc]ache/
# Others
ClientBin/
~$*
*~
*.dbmdl
*.dbproj.schemaview
*.jfm
*.pfx
*.publishsettings
orleans.codegen.cs
# Including strong name files can present a security risk
# (https://github.com/github/gitignore/pull/2483#issue-259490424)
#*.snk
# Since there are multiple workflows, uncomment next line to ignore bower_components
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
#bower_components/
# RIA/Silverlight projects
Generated_Code/
# Backup & report files from converting an old project file
# to a newer Visual Studio version. Backup files are not needed,
# because we have git ;-)
_UpgradeReport_Files/
Backup*/
UpgradeLog*.XML
UpgradeLog*.htm
ServiceFabricBackup/
*.rptproj.bak
# SQL Server files
*.mdf
*.ldf
*.ndf
# Business Intelligence projects
*.rdl.data
*.bim.layout
*.bim_*.settings
*.rptproj.rsuser
*- [Bb]ackup.rdl
*- [Bb]ackup ([0-9]).rdl
*- [Bb]ackup ([0-9][0-9]).rdl
# Microsoft Fakes
FakesAssemblies/
# GhostDoc plugin setting file
*.GhostDoc.xml
# Node.js Tools for Visual Studio
.ntvs_analysis.dat
node_modules/
# Visual Studio 6 build log
*.plg
# Visual Studio 6 workspace options file
*.opt
# Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
*.vbw
# Visual Studio LightSwitch build output
**/*.HTMLClient/GeneratedArtifacts
**/*.DesktopClient/GeneratedArtifacts
**/*.DesktopClient/ModelManifest.xml
**/*.Server/GeneratedArtifacts
**/*.Server/ModelManifest.xml
_Pvt_Extensions
# Paket dependency manager
.paket/paket.exe
paket-files/
# FAKE - F# Make
.fake/
# CodeRush personal settings
.cr/personal
# Python Tools for Visual Studio (PTVS)
__pycache__/
*.pyc
# Cake - Uncomment if you are using it
# tools/**
# !tools/packages.config
# Tabs Studio
*.tss
# Telerik's JustMock configuration file
*.jmconfig
# BizTalk build output
*.btp.cs
*.btm.cs
*.odx.cs
*.xsd.cs
# OpenCover UI analysis results
OpenCover/
# Azure Stream Analytics local run output
ASALocalRun/
# MSBuild Binary and Structured Log
*.binlog
# NVidia Nsight GPU debugger configuration file
*.nvuser
# MFractors (Xamarin productivity tool) working folder
.mfractor/
# Local History for Visual Studio
.localhistory/
# BeatPulse healthcheck temp database
healthchecksdb
# Backup folder for Package Reference Convert tool in Visual Studio 2017
MigrationBackup/
# Ionide (cross platform F# VS Code tools) working folder
.ionide/
# Fody - auto-generated XML schema
FodyWeavers.xsd

@ -0,0 +1,200 @@
using System;
using System.Threading;
using System.Threading.Tasks;
using System.Linq;
using System.Collections.Generic;
namespace Tools
{
public sealed class AsyncMutex : IDisposable
{
private readonly SemaphoreSlim sem;
public AsyncMutex()
{
sem = new SemaphoreSlim(1, 1);
}
private AsyncMutex(SemaphoreSlim from)
{
sem = from;
}
private class Lock : IDisposable
{
public AsyncMutex Parent { get; }
public Lock(AsyncMutex held)
{
Parent = held;
}
public void Dispose()
{
Parent.sem.Release();
}
}
public IDisposable Acquire(int msTimeout, CancellationToken token = default)
{
sem.Wait(msTimeout, token);
return new Lock(this);
}
public IDisposable Acquire(CancellationToken token)
{
sem.Wait(token);
return new Lock(this);
}
public IDisposable Acquire()
{
sem.Wait();
return new Lock(this);
}
public async Task<IDisposable> AcquireAsync(int msTimeout, CancellationToken token = default)
{
await sem.WaitAsync(msTimeout, token);
return new Lock(this);
}
public async Task<IDisposable> AcquireAsync(CancellationToken token = default)
{
await sem.WaitAsync(token);
return new Lock(this);
}
public void Dispose()
{
sem.Dispose();
}
public static AsyncMutex Semaphore(int count, int max)
{
SemaphoreSlim sem = new SemaphoreSlim(count, max);
return new AsyncMutex(sem);
}
public static AsyncMutex Semaphore(int count)
=> Semaphore(count, count);
}
public static class ExAsyncTools
{
#region Then()
public static async Task Then(this Task t, Action lam)
{
await t;
lam();
}
public static Task Then(this Task t, Action lam, CancellationToken token)
=> Then(t, (_) => lam(), token);
public static async Task Then(this Task t, Action<CancellationToken> lam, CancellationToken token)
{
TaskCompletionSource<bool> fail = new TaskCompletionSource<bool>();
using (token.Register(() => fail.TrySetResult(false)))
{
if ((await Task.WhenAny(t, fail.Task)) == t)
{
lam(token);
}
token.ThrowIfCancellationRequested();
}
}
public static async Task Then(this Task t, Func<Task> lam)
{
await t;
await lam();
}
public static Task Then(this Task t, Func<Task> lam, CancellationToken token)
=> Then(t, (_) => lam(), token);
public static async Task Then(this Task t, Func<CancellationToken, Task> lam, CancellationToken token)
{
TaskCompletionSource<bool> fail = new TaskCompletionSource<bool>();
using (token.Register(() => fail.TrySetResult(false)))
{
if ((await Task.WhenAny(t, fail.Task)) == t)
{
await lam(token);
}
token.ThrowIfCancellationRequested();
}
}
public static async Task<T> Then<T>(this Task<T> t, Action<T> lam)
{
T res = await t;
lam(res);
return res;
}
public static Task<T> Then<T>(this Task<T> t, Action<T> lam, CancellationToken token)
=> Then(t, (v, _) => lam(v), token);
public static async Task<T> Then<T>(this Task<T> t, Action<T, CancellationToken> lam, CancellationToken token)
{
TaskCompletionSource<bool> fail = new TaskCompletionSource<bool>();
using (token.Register(() => fail.TrySetResult(false)))
{
if ((await Task.WhenAny(t, fail.Task)) == t)
{
var res = t.Result;
lam(res, token);
return res;
}
throw new OperationCanceledException();
}
}
public static async Task<T> Then<T>(this Task<T> t, Func<T, T> lam)
{
T res = await t;
return lam(res);
}
public static Task<T> Then<T>(this Task<T> t, Func<T, T> lam, CancellationToken token)
=> Then(t, (v, _) => lam(v), token);
public static async Task<T> Then<T>(this Task<T> t, Func<T, CancellationToken, T> lam, CancellationToken token)
{
TaskCompletionSource<bool> fail = new TaskCompletionSource<bool>();
using (token.Register(() => fail.TrySetResult(false)))
{
if ((await Task.WhenAny(t, fail.Task)) == t)
{
var res = t.Result;
res = lam(res, token);
return res;
}
throw new OperationCanceledException();
}
}
public static async Task<T> Then<T>(this Task<T> t, Func<T, Task<T>> lam)
{
return await lam(await t);
}
public static Task<T> Then<T>(this Task<T> t, Func<T, Task<T>> lam, CancellationToken token)
=> Then(t, (x, _) => lam(x), token);
public static async Task<T> Then<T>(this Task<T> t, Func<T, CancellationToken, Task<T>> lam, CancellationToken token)
{
TaskCompletionSource<bool> fail = new TaskCompletionSource<bool>();
using (token.Register(() => fail.TrySetResult(false)))
{
if ((await Task.WhenAny(t, fail.Task)) == t)
{
var res = t.Result;
res = await lam(res, token);
return res;
}
throw new OperationCanceledException();
}
}
#endregion
public static CancellationTokenSource Link(this in CancellationToken token, params CancellationToken[] others)
{
return CancellationTokenSource.CreateLinkedTokenSource(new CancellationToken[] { token }.Concat(others).ToArray());
}
}
}

@ -0,0 +1,325 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace Tools.Maybes
{
static class test
{
public static void maybe()
{
var result = Maybe.Some(false);
if(result)
{
bool value = result;
}
else
{
}
result.Match(Some: value =>
{
return 10;
}, None: () =>
{
return 0;
});
var valresult = ValueMaybe.Some(10.1f);
if(valresult)
{
float res = valresult;
}
else
{
}
valresult.Match(Some: value =>
{
return value * 2;
}, None: () =>
{
return 0;
});
}
/* public void tresult()
{
var result = Result.Ok("hi");
}*/
}
public static class ValueMaybe
{
public static ValueMaybe<T> Some<T>(T value)
=> new ValueMaybe<T>(value, true);
public static ValueMaybe<T> None<T>()
=> new ValueMaybe<T>(default, false);
}
public readonly struct ValueMaybe<T>
{
private readonly T value;
private readonly bool hasValue;
public bool Equals(ValueMaybe<T> other)
{
return other.hasValue == this.hasValue && (ReferenceEquals(value, other.value) || (value?.Equals(other.value) ?? false));
}
public override int GetHashCode()
{
return hasValue ? Math.Abs(value?.GetHashCode() ?? 0) : -1;
}
public override bool Equals(object obj)
{
return (obj is ValueMaybe<T> some && Equals(some)) || (hasValue && obj is T val && (ReferenceEquals(val, value) || (value?.Equals(val) ?? false)));
}
internal ValueMaybe(T value, bool hasValue)
{
this.hasValue = hasValue;
this.value = value;
}
public static bool operator true(ValueMaybe<T> some)
=> some.hasValue;
public static bool operator false(ValueMaybe<T> some)
=> !some.hasValue;
public static implicit operator T(ValueMaybe<T> input)
=> input.hasValue ? input.value : throw new InvalidCastException("No value");
public static implicit operator ValueMaybe<T>(T input)
=> ValueMaybe.Some(input);
public T Value => value;
public bool HasValue => hasValue;
public bool TryGetValue(out T value)
{
if(HasValue)
{
value = Value;
return true;
}
value = default;
return false;
}
public void Match(Action<T> Some=null, Action None=null)
{
if (hasValue)
Some?.Invoke(value);
else
None?.Invoke();
}
public V Match<V>(Func<T, V> Some=null, Func<V> None=null)
{
if(hasValue)
{
if (Some != null) return Some(value);
else return default;
}
else
{
if (None != null) return None();
else return default;
}
}
public static bool operator ==(ValueMaybe<T> left, ValueMaybe<T> right)
{
return left.Equals(right);
}
public static bool operator !=(ValueMaybe<T> left, ValueMaybe<T> right)
{
return !(left == right);
}
}
public sealed class Some<T> : Maybe<T>
{
public override T Value { get; }
internal Some(T value)
{
Value = value;
}
public override bool Equals(object obj)
{
return obj is Some<T> some && (ReferenceEquals(some.Value, Value) || (some.Value?.Equals(Value) ?? false));
}
public override int GetHashCode()
{
return Math.Abs(Value?.GetHashCode() ?? 0);
}
public override string ToString()
{
return "Some(" + (Value?.ToString() ?? "null") + ")";
}
}
public sealed class None<T> : Maybe<T>
{
internal None() { }
public override bool Equals(object obj)
{
return obj is None<T>;
}
public override int GetHashCode()
{
return -1;
}
public override string ToString()
{
return "None";
}
}
public static class Maybe
{
public static Maybe<T> Some<T>(T value)
=> new Some<T>(value);
public static Maybe<T> None<T>()
=> new None<T>();
}
public abstract class Maybe<T>
{
public static bool operator true(Maybe<T> input)
=> input is Some<T>;
public static bool operator false(Maybe<T> input)
=> input is None<T>;
public override bool Equals(object obj)
{
throw new NotImplementedException();
}
public override int GetHashCode()
{
throw new NotImplementedException();
}
public override string ToString()
{
throw new NotImplementedException();
}
public static bool operator ==(Maybe<T> left, T right)
=> left.HasValue && (left == Maybe.Some(right));
public static bool operator !=(Maybe<T> left, T right)
=> !(left == right);
public static bool operator ==(Maybe<T> left, Maybe<T> right)
{
return ReferenceEquals(left, right) || (left?.Equals(right) ?? false);
}
public static bool operator !=(Maybe<T> left, Maybe<T> right)
=> !(left == right);
public static implicit operator T(Maybe<T> some) => some is Some<T> thing ? thing : throw new InvalidCastException("No value");
public static implicit operator Maybe<T>(T some) => new Some<T>(some);
public virtual T Value => (T)this;
public bool HasValue => this is Some<T>;
public bool TryGetValue(out T value)
{
if(this is Some<T> thing)
{
value = thing.Value;
return true;
}
value = default;
return false;
}
public void Match(Action<T> Some = null, Action None = null)
{
if (this is Some<T> some)
{
Some?.Invoke(some.Value);
}
else if (this is None<T> none)
None?.Invoke();
throw new InvalidOperationException("Maybe is neither some nor none.");
}
public V Match<V>(Func<T, V> Some = null, Func<V> None = null)
{
if (this is Some<T> some)
{
if (Some == null) return default;
else return Some(some.Value);
}
else if (this is None<T> none)
{
if (None == null) return default;
else
return None();
}
throw new InvalidOperationException("Maybe is neither some nor none.");
}
}
#if REWORK && false
public class Ok<T,E> : Result<T,E>
{
public override T Value { get; }
public Ok(T value)
{
Value = value;
}
}
public class Err<T,E> : Result<T,E>
{
public override E Error { get; }
public Err(E exception)
{
Error = exception;
}
}
public static class Result
{
public static Ok<T, E> Ok<T, E>(T value)
=> new Ok<T, E>(value);
public static Err<T, E> Err<T, E>(E value)
=> new Err<T, E>(value);
}
public abstract class Result<T,E>
{
public static bool operator true(Result<T, E> input)
=> input is Ok<T, E>;
public static bool operator false(Result<T, E> input)
=> input is Err<T, E>;
public virtual T Value => (T)this;
public virtual E Error => (E)this;
public bool TryGetValue(out T value)
{
if (this is Ok<T, E> thing)
{
value = thing.Value;
return true;
}
value = default;
return false;
}
public bool TryGetError(out E value)
{
if (this is Err<T, E> thing)
{
value = thing.Error;
return true;
}
value = default;
return false;
}
public static implicit operator T(Result<T, E> validResult) => validResult is Ok<T, E> ok ? ok.Value : throw new InvalidCastException("No value");
public static implicit operator E(Result<T, E> invalidResult) => invalidResult is Err<T, E> ok ? ok.Error : throw new InvalidCastException("No exception");
}
#endif
}

@ -0,0 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
</Project>

@ -0,0 +1,581 @@
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace Tools
{
namespace ByValData
{
namespace Fixed
{
namespace Special
{
public unsafe struct FixedSHA1Hash
{
public const int Size = 20;
public fixed byte data[Size];
public FixedSHA1Hash(byte[] from)
{
fixed (byte* p = data)
{
Marshal.Copy(from, 0, (IntPtr)p, Math.Min(Size, from.Length));
}
}
public static implicit operator byte[](FixedSHA1Hash from)
{
return from.ToByteArrayUnmanaged();
}
public static implicit operator FixedSHA1Hash(byte[] from)
{
return from.ToUnmanaged<FixedSHA1Hash>();
}
}
}
public unsafe struct FixedByteArray1
{
public const int Size = 1;
public fixed byte data[Size];
public byte AsByte
{
get
{
fixed (byte* ptr = data) return *ptr;
}
set
{
fixed (byte* ptr = data) *ptr = value;
}
}
public sbyte AsSByte
{
get
{
fixed (byte* ptr = data) return *(sbyte*)ptr;
}
set
{
fixed (byte* ptr = data) *(sbyte*)ptr = value;
}
}
public FixedByteArray1(byte asByte)
{
AsByte = asByte;
}
public FixedByteArray1(sbyte asSbyte)
{
AsSByte = asSbyte;
}
public FixedByteArray1(byte[] from)
{
fixed (byte* p = data)
{
Marshal.Copy(from, 0, (IntPtr)p, Math.Min(Size, from.Length));
}
}
public static implicit operator byte[](FixedByteArray1 from)
{
return from.ToByteArrayUnmanaged();
}
public static implicit operator FixedByteArray1(byte[] from)
{
return from.ToUnmanaged<FixedByteArray1>();
}
}
public unsafe struct FixedByteArray2
{
public const int Size = 2;
public fixed byte data[Size];
public short AsShort
{
get
{
fixed (byte* ptr = data) return *(short*)ptr;
}
set
{
fixed (byte* ptr = data) *(short*)ptr = value;
}
}
public ushort AsUShort
{
get
{
fixed (byte* ptr = data) return *(ushort*)ptr;
}
set
{
fixed (byte* ptr = data) *(ushort*)ptr = value;
}
}
public char AsChar
{
get
{
fixed (byte* ptr = data) return *(char*)ptr;
}
set
{
fixed (byte* ptr = data) *(char*)ptr = value;
}
}
public FixedByteArray2(char fromChar)
{
AsChar = fromChar;
}
public FixedByteArray2(short fromShort)
{
AsShort = fromShort;
}
public FixedByteArray2(ushort fromUshort)
{
AsUShort = fromUshort;
}
public FixedByteArray2(byte[] from)
{
fixed (byte* p = data)
{
Marshal.Copy(from, 0, (IntPtr)p, Math.Min(Size, from.Length));
}
}
public static implicit operator byte[](FixedByteArray2 from)
{
return from.ToByteArrayUnmanaged();
}
public static implicit operator FixedByteArray2(byte[] from)
{
return from.ToUnmanaged<FixedByteArray2>();
}
}
public unsafe struct FixedByteArray4
{
public const int Size = 4;
public fixed byte data[Size];
public int AsInt
{
get
{
fixed (byte* ptr = data) return *(int*)ptr;
}
set
{
fixed (byte* ptr = data) *(int*)ptr = value;
}
}
public uint AsUInt
{
get
{
fixed (byte* ptr = data) return *(uint*)ptr;
}
set
{
fixed (byte* ptr = data) *(uint*)ptr = value;
}
}
public bool AsBool
{
get
{
fixed (byte* ptr = data) return *(bool*)ptr;
}
set
{
fixed (byte* ptr = data) *(bool*)ptr = value;
}
}
public float AsFloat
{
get
{
fixed (byte* ptr = data) return *(float*)ptr;
}
set
{
fixed (byte* ptr = data) *(float*)ptr = value;
}
}
public FixedByteArray4(float fromFloat)
{
AsFloat = fromFloat;
}
public FixedByteArray4(bool fromBool)
{
AsBool = fromBool;
}
public FixedByteArray4(int fromInt)
{
AsInt = fromInt;
}
public FixedByteArray4(uint fromUint)
{
AsUInt = fromUint;
}
public FixedByteArray4(byte[] from)
{
fixed (byte* p = data)
{
Marshal.Copy(from, 0, (IntPtr)p, Math.Min(Size, from.Length));
}
}
public static implicit operator byte[](FixedByteArray4 from)
{
return from.ToByteArrayUnmanaged();
}
public static implicit operator FixedByteArray4(byte[] from)
{
return from.ToUnmanaged<FixedByteArray4>();
}
}
public unsafe struct FixedByteArray8
{
public const int Size = 8;
public fixed byte data[Size];
public long AsLong
{
get
{
fixed (byte* ptr = data) return *(long*)ptr;
}
set
{
fixed (byte* ptr = data) *(long*)ptr = value;
}
}
public ulong AsULong
{
get
{
fixed (byte* ptr = data) return *(ulong*)ptr;
}
set
{
fixed (byte* ptr = data) *(ulong*)ptr = value;
}
}
public double AsDouble
{
get
{
fixed (byte* ptr = data) return *(double*)ptr;
}
set
{
fixed (byte* ptr = data) *(double*)ptr = value;
}
}
public FixedByteArray8(double asDouble)
{
AsDouble = asDouble;
}
public FixedByteArray8(ulong asUlong)
{
AsULong = asUlong;
}
public FixedByteArray8(long asLong)
{
AsLong = asLong;
}
public FixedByteArray8(byte[] from)
{
fixed (byte* p = data)
{
Marshal.Copy(from, 0, (IntPtr)p, Math.Min(Size, from.Length));
}
}
public static implicit operator byte[](FixedByteArray8 from)
{
return from.ToByteArrayUnmanaged();
}
public static implicit operator FixedByteArray8(byte[] from)
{
return from.ToUnmanaged<FixedByteArray8>();
}
}
public unsafe struct FixedByteArray16
{
public const int Size = 16;
public fixed byte data[Size];
public decimal AsDecimal
{
get
{
fixed (byte* ptr = data) return *(decimal*)ptr;
}
set
{
fixed (byte* ptr = data) *(decimal*)ptr = value;
}
}
public FixedByteArray16(decimal from)
{
AsDecimal = from;
}
public FixedByteArray16(byte[] from)
{
fixed (byte* p = data)
{
Marshal.Copy(from, 0, (IntPtr)p, Math.Min(Size, from.Length));
}
}
public static implicit operator byte[](FixedByteArray16 from)
{
return from.ToByteArrayUnmanaged();
}
public static implicit operator FixedByteArray16(byte[] from)
{
return from.ToUnmanaged<FixedByteArray16>();
}
}
public unsafe struct FixedByteArray32
{
public const int Size = 32;
public fixed byte data[Size];
public FixedByteArray32(byte[] from)
{
fixed (byte* p = data)
{
Marshal.Copy(from, 0, (IntPtr)p, Math.Min(Size, from.Length));
}
}
public static implicit operator byte[](FixedByteArray32 from)
{
return from.ToByteArrayUnmanaged();
}
public static implicit operator FixedByteArray32(byte[] from)
{
return from.ToUnmanaged<FixedByteArray32>();
}
}
public unsafe struct FixedByteArray64
{
public const int Size = 64;
public fixed byte data[Size];
public FixedByteArray64(byte[] from)
{
fixed (byte* p = data)
{
Marshal.Copy(from, 0, (IntPtr)p, Math.Min(Size, from.Length));
}
}
public static implicit operator byte[](FixedByteArray64 from)
{
return from.ToByteArrayUnmanaged();
}
public static implicit operator FixedByteArray64(byte[] from)
{
return from.ToUnmanaged<FixedByteArray64>();
}
}
public unsafe struct FixedByteArray128
{
public const int Size = 128;
public fixed byte data[Size];
public FixedByteArray128(byte[] from)
{
fixed (byte* p = data)
{
Marshal.Copy(from, 0, (IntPtr)p, Math.Min(Size, from.Length));
}
}
public static implicit operator byte[](FixedByteArray128 from)
{
return from.ToByteArrayUnmanaged();
}
public static implicit operator FixedByteArray128(byte[] from)
{
return from.ToUnmanaged<FixedByteArray128>();
}
}
public unsafe struct FixedByteArray256
{
public const int Size = 128;
public fixed byte data[Size];
public FixedByteArray256(byte[] from)
{
fixed (byte* p = data)
{
Marshal.Copy(from, 0, (IntPtr)p, Math.Min(Size, from.Length));
}
}
public static implicit operator byte[](FixedByteArray256 from)
{
return from.ToByteArrayUnmanaged();
}
public static implicit operator FixedByteArray256(byte[] from)
{
return from.ToUnmanaged<FixedByteArray256>();
}
}
public unsafe struct FixedByteArray512
{
public const int Size = 512;
public fixed byte data[Size];
public FixedByteArray512(byte[] from)
{
fixed (byte* p = data)
{
Marshal.Copy(from, 0, (IntPtr)p, Math.Min(Size, from.Length));
}
}
public static implicit operator byte[](FixedByteArray512 from)
{
return from.ToByteArrayUnmanaged();
}
public static implicit operator FixedByteArray512(byte[] from)
{
return from.ToUnmanaged<FixedByteArray512>();
}
}
public unsafe struct FixedByteArray1024
{
public const int Size = 1024;
public fixed byte data[Size];
public FixedByteArray1024(byte[] from)
{
fixed (byte* p = data)
{
Marshal.Copy(from, 0, (IntPtr)p, Math.Min(Size, from.Length));
}
}
public static implicit operator byte[](FixedByteArray1024 from)
{
return from.ToByteArrayUnmanaged();
}
public static implicit operator FixedByteArray1024(byte[] from)
{
return from.ToUnmanaged<FixedByteArray1024>();
}
}
public unsafe struct FixedByteArray2048
{
public const int Size = 2048;
public fixed byte data[Size];
public FixedByteArray2048(byte[] from)
{
fixed (byte* p = data)
{
Marshal.Copy(from, 0, (IntPtr)p, Math.Min(Size, from.Length));
}
}
public static implicit operator byte[](FixedByteArray2048 from)
{
return from.ToByteArrayUnmanaged();
}
public static implicit operator FixedByteArray2048(byte[] from)
{
return from.ToUnmanaged<FixedByteArray2048>();
}
}
public unsafe struct FixedByteArray4096
{
public const int Size = 4096;
public fixed byte data[Size];
public FixedByteArray4096(byte[] from)
{
fixed (byte* p = data)
{
Marshal.Copy(from, 0, (IntPtr)p, Math.Min(Size, from.Length));
}
}
public static implicit operator byte[](FixedByteArray4096 from)
{
return from.ToByteArrayUnmanaged();
}
public static implicit operator FixedByteArray4096(byte[] from)
{
return from.ToUnmanaged<FixedByteArray4096>();
}
}
}
}
public static class ExBinTools
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe byte[] ToByteArrayUnmanaged<T>(this T t) where T : unmanaged
{
byte[] o = new byte[sizeof(T)];
fixed (byte* ptr = o)
{
*(T*)ptr = t;
}
return o;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe T ToUnmanaged<T>(this byte[] bytes) where T : unmanaged
{
fixed (byte* ptr = bytes)
{
return *(T*)ptr;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe ref T ZeroMemory<T>(this ref T value) where T : unmanaged
{
byte[] buffer = new byte[sizeof(T)];
fixed (T* valuePtr = &value)
{
Marshal.Copy(buffer, 0, (IntPtr)valuePtr, sizeof(T));
}
return ref value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe ref T SetMemory<T>(this ref T value, byte def=default) where T : unmanaged
{
byte[] buffer = new byte[sizeof(T)];
for (int i = 0; i < sizeof(T); i++) buffer[i] = def;
fixed (T* valuePtr = &value)
{
Marshal.Copy(buffer, 0, (IntPtr)valuePtr, sizeof(T));
}
return ref value;
}
}
}

@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
</Project>

@ -0,0 +1,831 @@
using System;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Linq;
using Tools;
using System.IO;
namespace Tools.Crypto
{
static unsafe class MemoryHelper
{
public static byte[] UMToByteArray(void* ptr, int size)
{
byte[] output = new byte[size];
Marshal.Copy((IntPtr)ptr, output, 0, size);
return output;
}
public static void ByteArrayToUM(byte[] input, void* ptr, int size)
{
Marshal.Copy(input, 0, (IntPtr)ptr, size);
}
public static T[] UMToArray<T>(T* ptr, int size) where T : unmanaged
{
T[] output = new T[size];
fixed (T* outputPtr = output)
Buffer.MemoryCopy(ptr, outputPtr, size * sizeof(T), size * sizeof(T));
return output;
}
public static void ArrayToUM<T>(T[] input, T* ptr, int size) where T : unmanaged
{
fixed (T* inputPtr = input)
Buffer.MemoryCopy(inputPtr, ptr, sizeof(T) * size, sizeof(T) * size);
}
}
public unsafe struct RSAHashSignature
{
public const int Length = 32;
internal fixed byte sig[Length];
public byte[] Signature
{
get
{
fixed (byte* ptr = sig)
{
return MemoryHelper.UMToByteArray(ptr, Length);
}
}
set
{
fixed (byte* ptr = sig)
MemoryHelper.ByteArrayToUM(value, ptr, Length);
}
}
public static RSAHashSignature CreateSignature(RSACryptoServiceProvider rsa, SHA256 algo, byte[] data)
{
return rsa.SignData(data, algo).ToUnmanaged<RSAHashSignature>();
}
public static RSAHashSignature CreateSignature(RSACryptoServiceProvider rsa, byte[] data)
{
using (var algo = SHA256.Create())
return CreateSignature(rsa, algo, data);
}
public bool Verify(RSACryptoServiceProvider rsa, SHA256 algo, byte[] data)
{
return rsa.VerifyData(data, algo, Signature);
}
public bool Verify(RSACryptoServiceProvider rsa, byte[] data)
{
using (var algo = SHA256.Create())
return Verify(rsa, algo, data);
}
}
public unsafe struct RSACiphertext
{
public const int Length = 128;
internal fixed byte ciphertext[Length];
public byte[] Ciphertext
{
get
{
fixed (byte* ptr = ciphertext)
return MemoryHelper.UMToByteArray(ptr, Length);
}
set
{
fixed (byte* ptr = ciphertext)
MemoryHelper.ByteArrayToUM(value, ptr, Length);
}
}
public void EncryptSingleBlock(RSACryptoServiceProvider rsa, byte[] plain)
{
Ciphertext = rsa.Encrypt(plain, false);
}
public byte[] DecryptSingleBlock(RSACryptoServiceProvider rsa)
{
return rsa.Decrypt(Ciphertext, false);
}
public unsafe static RSACiphertext[] Encrypt(RSACryptoServiceProvider rsa, byte[] plain)
{
byte[] ct = rsa.Encrypt(plain, false);
if (ct.Length == Length) return new RSACiphertext[] { new RSACiphertext() { Ciphertext = ct } };
else if (ct.Length % Length == 0)
{
int ciphers = ct.Length / Length;
RSACiphertext* cipher = stackalloc RSACiphertext[ciphers];
Marshal.Copy(ct, 0, (IntPtr)cipher, ciphers * sizeof(RSACiphertext));
return MemoryHelper.UMToArray<RSACiphertext>(cipher, ciphers);
}
else
{
//Probably won't happen?
int ciphers = (ct.Length / Length) + 1;
RSACiphertext* cipher = stackalloc RSACiphertext[ciphers];
Marshal.Copy(ct, 0, (IntPtr)cipher, ciphers * sizeof(RSACiphertext));
return MemoryHelper.UMToArray<RSACiphertext>(cipher, ciphers);
}
}
public static byte[] Decrypt(RSACryptoServiceProvider rsa, RSACiphertext[] cipher)
{
byte[] byts = new byte[sizeof(RSACiphertext) * cipher.Length];
fixed (RSACiphertext* input = cipher)
{
fixed (byte* output = byts)
{
Buffer.MemoryCopy(input, output, byts.Length, byts.Length);
}
}
return rsa.Decrypt(byts, false);
}
}
public unsafe struct AESKey
{
public const int KeySize = 32;
public const int IVSize = 16;
internal fixed byte key[KeySize];
internal fixed byte iv[IVSize];
/// <summary>
/// The Key (256 bit)
/// </summary>
public byte[] Key
{
get
{
byte[] bytes = new byte[KeySize];
fixed (byte* k = key)
{
Marshal.Copy((IntPtr)k, bytes, 0, KeySize);
}
return bytes;
}
set
{
if (value.Length != KeySize) throw new ArgumentException(nameof(value) + " must be exaclty " + KeySize + " bytes (not " + value.Length + ")");
fixed (byte* k = key)
{
Marshal.Copy(value, 0, (IntPtr)k, KeySize);
}
}
}
/// <summary>
/// The IV (128 bits)
/// </summary>
public byte[] IV
{
get
{
byte[] bytes = new byte[IVSize];
fixed (byte* k = iv)
{
Marshal.Copy((IntPtr)k, bytes, 0, IVSize);
}
return bytes;
}
set
{
if (value.Length != IVSize) throw new ArgumentException(nameof(value) + " must be exaclty " + IVSize + " bytes (not " + value.Length + ")");
fixed (byte* k = iv)
{
Marshal.Copy(value, 0, (IntPtr)k, IVSize);
}
}
}
/// <summary>
/// Binary serialisation of this key
/// </summary>
public byte[] BinaryData
{
get
{
return this.ToByteArrayUnmanaged();
}
set
{
if (value.Length < sizeof(AESKey)) throw new ArgumentException(nameof(value) + " must be at least " + sizeof(AESKey) + " bytes (not " + value.Length + ")");
fixed (AESKey* k = &this)
{
Marshal.Copy(value, 0, (IntPtr)k, sizeof(AESKey));
}
}
}
/// <summary>
/// Create a new key
/// </summary>
/// <returns>The new AES Key</returns>
public static AESKey NewKey()
{
using (RNGCryptoServiceProvider rng = new RNGCryptoServiceProvider())
{
byte[] buffer = new byte[sizeof(AESKey)];
rng.GetBytes(buffer);
return buffer.ToUnmanaged<AESKey>();
}
}
/// <summary>
/// Set the key and iv to an AesCryptoServiceProvider
/// </summary>
/// <param name="r">The CSP</param>
public void ToCSP(AesCryptoServiceProvider r)
{
r.KeySize = 256;
r.BlockSize = 128;
r.Key = Key;
r.IV = IV;
}
public void FromAes(Aes aes)
{
Key = aes.Key;
IV = aes.IV;
}
public void ToAes(Aes aes)
{
aes.KeySize = 256;
aes.BlockSize = 128;
aes.Key = Key;
aes.IV = IV;
}
/// <summary>
/// Get the key and iv from and AESCryptoServiceProvider
/// </summary>
/// <param name="r">The CSP</param>
public void FromCSP(AesCryptoServiceProvider r)
{
Key = r.Key;
IV = r.IV;
}
/// <summary>
/// Initialise a new AESKey from an AESCryptoServiceProvider
/// </summary>
/// <param name="aes">The AES key</param>
public AESKey(AesCryptoServiceProvider aes)
{
FromCSP(aes);
}
public AESKey(Aes aes)
{
FromAes(aes);
}
}
public unsafe struct RSAPublicKey
{
public const int ModulusSize = 128;
public const int ExponentSize = 3;
internal fixed byte mod[ModulusSize];
internal fixed byte exp[ExponentSize];
/// <summary>
/// The modulus of this key
/// </summary>
public byte[] Modulus
{
get
{
byte[] bytes = new byte[ModulusSize];
fixed (byte* m = mod)
{
Marshal.Copy((IntPtr)m, bytes, 0, ModulusSize);
}
return bytes;
}
set
{
if (value.Length != ModulusSize) throw new ArgumentException(nameof(value) + " must be exaclty " + ModulusSize + " bytes (not " + value.Length + ")");
fixed (byte* m = mod)
{
Marshal.Copy(value, 0, (IntPtr)m, ModulusSize);
}
}
}
/// <summary>
/// The public exponent of this key
/// </summary>
public byte[] Exponent
{
get
{
byte[] bytes = new byte[ExponentSize];
fixed (byte* m = exp)
{
Marshal.Copy((IntPtr)m, bytes, 0, ExponentSize);
}
return bytes;
}
set
{
if (value.Length != ExponentSize) throw new ArgumentException(nameof(value) + " must be exaclty " + ExponentSize + " bytes (not " + value.Length + ")");
fixed (byte* m = exp)
{
Marshal.Copy(value, 0, (IntPtr)m, ExponentSize);
}
}
}
/// <summary>
/// Binary serialisation of this key
/// </summary>
public byte[] BinaryData
{
get
{
return this.ToByteArrayUnmanaged();
}
set
{
if (value.Length < sizeof(RSAPublicKey)) throw new ArgumentException(nameof(value) + " must be at least " + sizeof(RSAPublicKey) + " bytes (not " + value.Length + ")");
fixed (RSAPublicKey* k = &this)
{
Marshal.Copy(value, 0, (IntPtr)k, sizeof(RSAPublicKey));
}
}
}
/// <summary>
/// Set the public key to a RSACryptoServiceProvider
/// </summary>
/// <param name="csp">The CSP to set the key to</param>
public void ToCSP(RSACryptoServiceProvider csp)
{
var p = csp.ExportParameters(false);
p.Modulus = Modulus;
p.Exponent = Exponent;
csp.ImportParameters(p);
}
/// <summary>
/// Get the public key information from an RSACryptoServiceProvider and return it in an RSAPublicKey struct
/// </summary>
/// <param name="csp">The CSP</param>
/// <returns>A new RSAPublicKey struct</returns>
public static RSAPublicKey FromCSP(RSACryptoServiceProvider csp)
{
RSAPublicKey rp = new RSAPublicKey();
var p = csp.ExportParameters(false);
rp.Modulus = p.Modulus;
rp.Exponent = p.Exponent;
return rp;
}
public static implicit operator byte[](RSAPublicKey rp)
{
return rp.ToByteArrayUnmanaged();
}
public static explicit operator RSAPublicKey(byte[] byt)
{
return byt.ToUnmanaged<RSAPublicKey>();
}
}
public unsafe struct RSAPrivateKey
{
public override string ToString()
{
return BitConverter.ToString(this.ToByteArrayUnmanaged()).Replace("-", "");
}
public override bool Equals(object obj)
{
return obj is RSAPrivateKey priv && priv.ToByteArrayUnmanaged().SequenceEqual(this.ToByteArrayUnmanaged());
}
public override int GetHashCode()
{
unchecked
{
return (int)DamienG.Security.Cryptography.Crc32.Compute(this.ToByteArrayUnmanaged());
}
}
public RSAPublicKey PublicPart => new RSAPublicKey() { Modulus = Modulus, Exponent = Exponent };
public const int ModulusLength = 128;
public const int ExponentLength = 3;
public const int DLength = 128;
public const int PLength = 64;
public const int QLength = 64;
public const int DPLength = 64;
public const int DQLength = 64;
public const int InverseQLength = 64;
internal fixed byte modulus[ModulusLength];
internal fixed byte exponent[ExponentLength];
internal fixed byte d[DLength];
internal fixed byte p[PLength];
internal fixed byte q[QLength];
internal fixed byte dp[DPLength];
internal fixed byte dq[DQLength];
internal fixed byte inverseQ[InverseQLength];
public byte[] Modulus
{
get
{
byte[] bytes = new byte[ModulusLength];
fixed (byte* m = modulus)
{
Marshal.Copy((IntPtr)m, bytes, 0, ModulusLength);
}
return bytes;
}
set
{
if (value.Length != ModulusLength) throw new ArgumentException(nameof(value) + " must be exaclty " + ModulusLength + " bytes (not " + value.Length + ")");
fixed (byte* m = modulus)
{
Marshal.Copy(value, 0, (IntPtr)m, ModulusLength);
}
}
}
public byte[] Exponent
{
get
{
byte[] bytes = new byte[ExponentLength];
fixed (byte* m = exponent)
{
Marshal.Copy((IntPtr)m, bytes, 0, ExponentLength);
}
return bytes;
}
set
{
if (value.Length != ExponentLength) throw new ArgumentException(nameof(value) + " must be exaclty " + ExponentLength + " bytes (not " + value.Length + ")");
fixed (byte* m = exponent)
{
Marshal.Copy(value, 0, (IntPtr)m, ExponentLength);
}
}
}
public byte[] D
{
get
{
byte[] bytes = new byte[DLength];
fixed (byte* m = d)
{
Marshal.Copy((IntPtr)m, bytes, 0, DLength);
}
return bytes;
}
set
{
if (value.Length != DLength) throw new ArgumentException(nameof(value) + " must be exaclty " + DLength + " bytes (not " + value.Length + ")");
fixed (byte* m = d)
{
Marshal.Copy(value, 0, (IntPtr)m, DLength);
}
}
}
public byte[] P
{
get
{
byte[] bytes = new byte[PLength];
fixed (byte* m = p)
{
Marshal.Copy((IntPtr)m, bytes, 0, PLength);
}
return bytes;
}
set
{
if (value.Length != PLength) throw new ArgumentException(nameof(value) + " must be exaclty " + PLength + " bytes (not " + value.Length + ")");
fixed (byte* m = p)
{
Marshal.Copy(value, 0, (IntPtr)m, PLength);
}
}
}
public byte[] Q
{
get
{
byte[] bytes = new byte[QLength];
fixed (byte* m = q)
{
Marshal.Copy((IntPtr)m, bytes, 0, QLength);
}
return bytes;
}
set
{
if (value.Length != QLength) throw new ArgumentException(nameof(value) + " must be exaclty " + QLength + " bytes (not " + value.Length + ")");
fixed (byte* m = q)
{
Marshal.Copy(value, 0, (IntPtr)m, QLength);
}
}
}
public byte[] DP
{
get
{
byte[] bytes = new byte[DPLength];
fixed (byte* m = dp)
{
Marshal.Copy((IntPtr)m, bytes, 0, DPLength);
}
return bytes;
}
set
{
if (value.Length != DPLength) throw new ArgumentException(nameof(value) + " must be exaclty " + DPLength + " bytes (not " + value.Length + ")");
fixed (byte* m = dp)
{
Marshal.Copy(value, 0, (IntPtr)m, DPLength);
}
}
}
public byte[] DQ
{
get
{
byte[] bytes = new byte[DQLength];
fixed (byte* m = dq)
{
Marshal.Copy((IntPtr)m, bytes, 0, DQLength);
}
return bytes;
}
set
{
if (value.Length != DQLength) throw new ArgumentException(nameof(value) + " must be exaclty " + DQLength + " bytes (not " + value.Length + ")");
fixed (byte* m = dq)
{
Marshal.Copy(value, 0, (IntPtr)m, DQLength);
}
}
}
public byte[] InverseQ
{
get
{
byte[] bytes = new byte[InverseQLength];
fixed (byte* m = inverseQ)
{
Marshal.Copy((IntPtr)m, bytes, 0, InverseQLength);
}
return bytes;
}
set
{
if (value.Length != InverseQLength) throw new ArgumentException(nameof(value) + " must be exaclty " + InverseQLength + " bytes (not " + value.Length + ")");
fixed (byte* m = inverseQ)
{
Marshal.Copy(value, 0, (IntPtr)m, InverseQLength);
}
}
}
public void FromCSP(RSACryptoServiceProvider rsa)
{
var param = rsa.ExportParameters(true);
Modulus = param.Modulus;
Exponent = param.Exponent;
D = param.D;
P = param.P;
Q = param.Q;
DP = param.DP;
DQ = param.DQ;
InverseQ = param.InverseQ;
}
public void ToCSP(RSACryptoServiceProvider rsa)
{
var param = new RSAParameters();
param.Modulus = Modulus;
param.Exponent = Exponent;
param.D = D;
param.P = P;
param.Q = Q;
param.DP = DP;
param.DQ = DQ;
param.InverseQ = InverseQ;
rsa.ImportParameters(param);
}
public static RSAPrivateKey Generate()
{
using (var rsa = new RSACryptoServiceProvider())
{
RSAPrivateKey ret = new RSAPrivateKey();
ret.FromCSP(rsa);
return ret;
}
}
public static bool operator ==(RSAPrivateKey left, RSAPrivateKey right)
{
return left.Equals(right);
}
public static bool operator !=(RSAPrivateKey left, RSAPrivateKey right)
{
return !(left == right);
}
}
public unsafe struct SHA256Hash
{
public const int Size = 32;
internal fixed byte hash[Size];
public override bool Equals(object obj)
{
return obj is SHA256Hash hash && hash.ToByteArrayUnmanaged().SequenceEqual(this.ToByteArrayUnmanaged());
}
public override int GetHashCode()
{
unchecked
{
return (int)DamienG.Security.Cryptography.Crc32.Compute(this.ToByteArrayUnmanaged());
}
}
public byte[] Hash
{
get
{
byte[] bytes = new byte[Size];
fixed (byte* m = hash)
{
Marshal.Copy((IntPtr)m, bytes, 0, Size);
}
return bytes;
}
set
{
if (value.Length != Size) throw new ArgumentException(nameof(value) + " must be exaclty " + Size + " bytes (not " + value.Length + ")");
fixed (byte* m = hash)
{
Marshal.Copy(value, 0, (IntPtr)m, Size);
}
}
}
public SHA256Hash(byte[] hash)
{
Hash = hash;
}
public static SHA256Hash Generate(byte[] data, SHA256 hasher = null)
{
if (hasher == null)
using (var hash = SHA256.Create())
return Generate(data, hash);
return (SHA256Hash)hasher.ComputeHash(data);
}
public static implicit operator byte[](SHA256Hash hash) => hash.ToByteArrayUnmanaged();
public static explicit operator SHA256Hash(byte[] hash) => hash.Length == Size ? hash.ToUnmanaged<SHA256Hash>() : throw new InvalidCastException("Hash must be exactly "+Size+" bytes");
public static bool operator ==(SHA256Hash left, SHA256Hash right)
{
return left.Equals(right);
}
public static bool operator !=(SHA256Hash left, SHA256Hash right)
{
return !(left == right);
}
public override string ToString()
{
return BitConverter.ToString(this.ToByteArrayUnmanaged()).Replace("-", "").ToLower();
}
}
}
namespace Tools
{
using Tools.Crypto;
public class IncrementalHashStream : Stream
{
private long written = 0;
private IncrementalHash hasher;
public IncrementalHashStream(HashAlgorithmName algo)
{
hasher = IncrementalHash.CreateHash(algo);
}
private byte[] hash;
public SHA256Hash Hash => new SHA256Hash() { Hash = hash ?? throw new InvalidOperationException("Hash has not been computed. (Call Flush())") };
public SHA256Hash HashAndReset()
{
Flush();
return Hash;
}
public override bool CanRead => false;
public override bool CanSeek => false;
public override bool CanWrite => true;
public override long Length => written;
public override long Position { get => throw new NotSupportedException(); set => throw new NotSupportedException(); }
/// <summary>
/// Compute the hash of all written data, store it in <see cref="Hash"/>, and reset the algorithm.
/// </summary>
public override void Flush()
{
lock (mutex)
{
hash = hasher.GetHashAndReset();
}
written = 0;
}
public override int Read(byte[] buffer, int offset, int count)
{
throw new NotSupportedException();
}
public override long Seek(long offset, SeekOrigin origin)
{
throw new NotSupportedException();
}
public override void SetLength(long value)
{
throw new NotSupportedException();
}
private readonly object mutex = new object();
public override void Write(byte[] buffer, int offset, int count)
{
var dt = new ArraySegment<byte>(buffer, offset, count).Array;
lock (mutex)
{
hasher.AppendData(dt);
written += dt.Length;
}
}
public SHA256Hash GetFinalHash()
{
if (hasher == null) throw new ObjectDisposedException(this.ToString());
Flush();
Dispose();
return Hash;
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing) hasher?.Dispose();
hasher = null;
}
}
public static class ExCryptoTools
{
public static SHA256Hash SHA256Hash(this byte[] data)
{
using (var sha = SHA256.Create())
return (SHA256Hash)sha.ComputeHash(data);
}
public static SHA256Hash SHA256Hash(this Stream str)
{
using (var sha = SHA256.Create())
return (SHA256Hash)sha.ComputeHash(str);
}
}
}

@ -0,0 +1,119 @@
// Copyright (c) Damien Guard. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
// Originally published at http://damieng.com/blog/2006/08/08/calculating_crc32_in_c_and_net
using System;
using System.Collections.Generic;
using System.Security.Cryptography;
namespace DamienG.Security.Cryptography
{
/// <summary>
/// Implements a 32-bit CRC hash algorithm compatible with Zip etc.
/// </summary>
/// <remarks>
/// Crc32 should only be used for backward compatibility with older file formats
/// and algorithms. It is not secure enough for new applications.
/// If you need to call multiple times for the same data either use the HashAlgorithm
/// interface or remember that the result of one Compute call needs to be ~ (XOR) before
/// being passed in as the seed for the next Compute call.
/// </remarks>
public sealed class Crc32 : HashAlgorithm
{
public const UInt32 DefaultPolynomial = 0xedb88320u;
public const UInt32 DefaultSeed = 0xffffffffu;
static UInt32[] defaultTable;
readonly UInt32 seed;
readonly UInt32[] table;
UInt32 hash;
public Crc32()
: this(DefaultPolynomial, DefaultSeed)
{
}
public Crc32(UInt32 polynomial, UInt32 seed)
{
table = InitializeTable(polynomial);
this.seed = hash = seed;
}
public override void Initialize()
{
hash = seed;
}
protected override void HashCore(byte[] array, int ibStart, int cbSize)
{
hash = CalculateHash(table, hash, array, ibStart, cbSize);
}
protected override byte[] HashFinal()
{
var hashBuffer = UInt32ToBigEndianBytes(~hash);
HashValue = hashBuffer;
return hashBuffer;
}
public override int HashSize { get { return 32; } }
public static UInt32 Compute(byte[] buffer)
{
return Compute(DefaultSeed, buffer);
}
public static UInt32 Compute(UInt32 seed, byte[] buffer)
{
return Compute(DefaultPolynomial, seed, buffer);
}
public static UInt32 Compute(UInt32 polynomial, UInt32 seed, byte[] buffer)
{
return ~CalculateHash(InitializeTable(polynomial), seed, buffer, 0, buffer.Length);
}
static UInt32[] InitializeTable(UInt32 polynomial)
{
if (polynomial == DefaultPolynomial && defaultTable != null)
return defaultTable;
var createTable = new UInt32[256];
for (var i = 0; i < 256; i++)
{
var entry = (UInt32)i;
for (var j = 0; j < 8; j++)
if ((entry & 1) == 1)
entry = (entry >> 1) ^ polynomial;
else
entry = entry >> 1;
createTable[i] = entry;
}
if (polynomial == DefaultPolynomial)
defaultTable = createTable;
return createTable;
}
static UInt32 CalculateHash(UInt32[] table, UInt32 seed, IList<byte> buffer, int start, int size)
{
var crc = seed;
for (var i = start; i < size - start; i++)
crc = (crc >> 8) ^ table[buffer[i] ^ crc & 0xff];
return crc;
}
static byte[] UInt32ToBigEndianBytes(UInt32 uint32)
{
var result = BitConverter.GetBytes(uint32);
if (BitConverter.IsLittleEndian)
Array.Reverse(result);
return result;
}
}
}

@ -0,0 +1,139 @@
// Copyright (c) Damien Guard. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License.
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
// Originally published at http://damieng.com/blog/2007/11/19/calculating-crc-64-in-c-and-net
using System;
using System.Collections.Generic;
using System.Security.Cryptography;
namespace DamienG.Security.Cryptography
{
/// <summary>
/// Implements a 64-bit CRC hash algorithm for a given polynomial.
/// </summary>
/// <remarks>
/// For ISO 3309 compliant 64-bit CRC's use Crc64Iso.
/// </remarks>
public class Crc64 : HashAlgorithm
{
public const UInt64 DefaultSeed = 0x0;
readonly UInt64[] table;
readonly UInt64 seed;
UInt64 hash;
public Crc64(UInt64 polynomial)
: this(polynomial, DefaultSeed)
{
}
public Crc64(UInt64 polynomial, UInt64 seed)
{
table = InitializeTable(polynomial);
this.seed = hash = seed;
}
public override void Initialize()
{
hash = seed;
}
protected override void HashCore(byte[] array, int ibStart, int cbSize)
{
hash = CalculateHash(hash, table, array, ibStart, cbSize);
}
protected override byte[] HashFinal()
{
var hashBuffer = UInt64ToBigEndianBytes(hash);
HashValue = hashBuffer;
return hashBuffer;
}
public override int HashSize { get { return 64; } }
protected static UInt64 CalculateHash(UInt64 seed, UInt64[] table, IList<byte> buffer, int start, int size)
{
var crc = seed;
for (var i = start; i < size; i++)
unchecked
{
crc = (crc >> 8) ^ table[(buffer[i] ^ crc) & 0xff];
}
return crc;
}
static byte[] UInt64ToBigEndianBytes(UInt64 value)
{
var result = BitConverter.GetBytes(value);
if (BitConverter.IsLittleEndian)
Array.Reverse(result);
return result;
}
static UInt64[] InitializeTable(UInt64 polynomial)
{
if (polynomial == Crc64Iso.Iso3309Polynomial && Crc64Iso.Table != null)
return Crc64Iso.Table;
var createTable = CreateTable(polynomial);
if (polynomial == Crc64Iso.Iso3309Polynomial)
Crc64Iso.Table = createTable;
return createTable;
}
protected static ulong[] CreateTable(ulong polynomial)
{
var createTable = new UInt64[256];
for (var i = 0; i < 256; ++i)
{
var entry = (UInt64) i;
for (var j = 0; j < 8; ++j)
if ((entry & 1) == 1)
entry = (entry >> 1) ^ polynomial;
else
entry = entry >> 1;
createTable[i] = entry;
}
return createTable;
}
}
public class Crc64Iso : Crc64
{
internal static UInt64[] Table;
public const UInt64 Iso3309Polynomial = 0xD800000000000000;
public Crc64Iso()
: base(Iso3309Polynomial)
{
}
public Crc64Iso(UInt64 seed)
: base(Iso3309Polynomial, seed)
{
}
public static UInt64 Compute(byte[] buffer)
{
return Compute(DefaultSeed, buffer);
}
public static UInt64 Compute(UInt64 seed, byte[] buffer)
{
if (Table == null)
Table = CreateTable(Iso3309Polynomial);
return CalculateHash(seed, Table, buffer, 0, buffer.Length);
}
}
}

@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\exbintools\exbintools.csproj" />
</ItemGroup>
</Project>

@ -0,0 +1,221 @@
using System;
using System.IO;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace Tools
{
public static class ExStreamTools
{
public static void CopyTo(this Stream input, Stream output, int buffersize, long bytes)
{
byte[] buffer = new byte[buffersize];
int count;
while (bytes > 0L && (count = input.Read(buffer, 0, (int)Math.Min((long)buffer.Length, bytes))) > 0)
{
output.Write(buffer, 0, count);
bytes -= (long)count;
}
}
public static async Task CopyToAsync(this Stream input, Stream output, int buffersize, long bytes, CancellationToken token =default)
{
byte[] buffer = new byte[buffersize];
int count;
while (bytes > 0L && (count = await input.ReadAsync(buffer, 0, (int)Math.Min((long)buffer.Length, bytes), token)) > 0)
{
await output.WriteAsync(buffer, 0, count, token);
bytes -= (long)count;
}
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe void WriteValueUnmanaged<T>(this Stream s, T t) where T : unmanaged
{
byte[] buffer = new byte[sizeof(T)];
fixed (byte* ptr = buffer)
{
*(T*)ptr = t;
}
s.Write(buffer, 0, buffer.Length);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe Task WriteValueUnmanagedAsync<T>(this Stream s, T t, CancellationToken token = default) where T : unmanaged
{
byte[] buffer = new byte[sizeof(T)];
fixed (byte* ptr = buffer)
{
*(T*)ptr = t;
}
return s.WriteAsync(buffer, 0, buffer.Length, token);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void WriteAll(this Stream s, byte[] buffer)
{
s.Write(buffer, 0, buffer.Length);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Task WriteAllAsync(this Stream s, byte[] buffer, CancellationToken token=default)
{
return s.WriteAsync(buffer, 0, buffer.Length,token);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int ReadAll(this Stream s, byte[] buffer)
{
return s.Read(buffer, 0, buffer.Length);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Task<int> ReadAllAsync(this Stream s, byte[] buffer, CancellationToken token = default)
{
return s.ReadAsync(buffer, 0, buffer.Length, token);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int ReadAllBlocking(this Stream s, byte[] buffer)
{
return s.BlockingRead(buffer, 0, buffer.Length);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Task<int> ReadAllBlockingAsync(this Stream s, byte[] buffer, CancellationToken token = default)
{
return s.BlockingReadAsync(buffer, 0, buffer.Length, token);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static byte[] ReadNew(this Stream s, int len)
{
byte[] buffer = new byte[len];
s.Read(buffer, 0, len);
return buffer;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static async Task<byte[]> ReadNewAsync(this Stream s, int len, CancellationToken token = default)
{
byte[] buffer = new byte[len];
await s.ReadAsync(buffer, 0, len, token);
return buffer;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static byte[] ReadNewBlocking(this Stream s, int len)
{
byte[] buffer = new byte[len];
s.BlockingRead(buffer, 0, len);
return buffer;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static async Task<byte[]> ReadNewBlockingAsync(this Stream s, int len, CancellationToken token = default)
{
byte[] buffer = new byte[len];
await s.BlockingReadAsync(buffer, 0, len, token);
return buffer;
}
public static int BlockingRead(this Stream s, byte[] buffer, int offset, int count)
{
int read;
int rlen = 0;
while ((rlen += (read = s.Read(buffer, offset + rlen, count - rlen))) < count) if (read <= 0) break;
return rlen;
}
public static async Task<int> BlockingReadAsync(this Stream s, byte[] buffer, int offset, int count, CancellationToken token=default)
{
int read;
int rlen = 0;
while ((rlen += (read = await s.ReadAsync(buffer, offset + rlen, count - rlen, token))) < count) if (read <= 0) break;
return rlen;
}
public static void WriteString(this Stream s, string str, Encoding encoding = null)
{
if (encoding == null) encoding = Encoding.UTF8;
int code = encoding.CodePage;
byte[] buf = encoding.GetBytes(str);
s.WriteValueUnmanaged(buf.Length);
s.WriteValueUnmanaged(code);
s.WriteAll(buf);
}
public static Task WriteStringAsync(this Stream s, string str, CancellationToken token = default)
=> WriteStringAsync(s, str, Encoding.UTF8, token);
public static async Task WriteStringAsync(this Stream s, string str, Encoding encoding, CancellationToken token=default)
{
int code = encoding.CodePage;
byte[] buf = encoding.GetBytes(str);
await s.WriteValueUnmanagedAsync(buf.Length, token);
await s.WriteValueUnmanagedAsync(code,token);
await s.WriteAllAsync(buf,token);
}
public static string ReadString(this Stream s, Encoding encoding = null)
{
int len = s.ReadValueUnmanaged<int>();
int code = s.ReadValueUnmanaged<int>();
byte[] buf = s.ReadNew(len);
if (encoding == null)
encoding = Encoding.GetEncoding(code);
return encoding.GetString(buf);
}
public static async Task<string> ReadStringAsync(this Stream s, CancellationToken token = default)
{
int len = await s.ReadValueUnmanagedAsync<int>(token);
int code = await s.ReadValueUnmanagedAsync<int>(token);
byte[] buf = await s.ReadNewAsync(len, token);
var encoding = Encoding.GetEncoding(code);
return encoding.GetString(buf);
}
public static async Task<string> ReadStringAsync(this Stream s, Encoding encoding, CancellationToken token = default)
{
int len = await s.ReadValueUnmanagedAsync<int>(token);
await s.ReadValueUnmanagedAsync<int>(token);
byte[] buf = await s.ReadNewAsync(len, token);
return encoding.GetString(buf);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe T ReadValueUnmanaged<T>(this Stream s) where T : unmanaged
{
T output;
byte[] buffer = new byte[sizeof(T)];
s.Read(buffer, 0, buffer.Length);
fixed (byte* ptr = buffer)
{
output = *(T*)ptr;
}
return output;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static async Task<T> ReadValueUnmanagedAsync<T>(this Stream s, CancellationToken token=default) where T : unmanaged
{
T output;
int len;
unsafe
{
len = sizeof(T);
}
byte[] buffer = new byte[len];
await s.ReadAsync(buffer, 0, buffer.Length, token);
unsafe
{
fixed (byte* ptr = buffer)
{
output = *(T*)ptr;
}
}
return output;
}
}
}

@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
</Project>

@ -0,0 +1,49 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 16
VisualStudioVersion = 16.0.29609.76
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "extensions", "extensions\extensions.csproj", "{6A440D6F-7F49-431C-89E1-61EF6C69038C}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "exbintools", "exbintools\exbintools.csproj", "{A76EB40A-3825-4225-9D63-74338BF92CAC}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "exstreamtools", "exstreamtools\exstreamtools.csproj", "{CBDB78A8-7630-4C8C-9964-E083895BD287}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "excryptotools", "excryptotools\excryptotools.csproj", "{F3FF4A85-1949-47E0-9E2B-052CF72BFA44}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "exasynctools", "exasynctools\exasynctools.csproj", "{4C54F119-650D-4939-8713-83FCA0484E3B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{6A440D6F-7F49-431C-89E1-61EF6C69038C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6A440D6F-7F49-431C-89E1-61EF6C69038C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6A440D6F-7F49-431C-89E1-61EF6C69038C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6A440D6F-7F49-431C-89E1-61EF6C69038C}.Release|Any CPU.Build.0 = Release|Any CPU
{A76EB40A-3825-4225-9D63-74338BF92CAC}.Debug|Any CPU.ActiveCfg = Release|Any CPU
{A76EB40A-3825-4225-9D63-74338BF92CAC}.Debug|Any CPU.Build.0 = Release|Any CPU
{A76EB40A-3825-4225-9D63-74338BF92CAC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A76EB40A-3825-4225-9D63-74338BF92CAC}.Release|Any CPU.Build.0 = Release|Any CPU
{CBDB78A8-7630-4C8C-9964-E083895BD287}.Debug|Any CPU.ActiveCfg = Release|Any CPU
{CBDB78A8-7630-4C8C-9964-E083895BD287}.Debug|Any CPU.Build.0 = Release|Any CPU
{CBDB78A8-7630-4C8C-9964-E083895BD287}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CBDB78A8-7630-4C8C-9964-E083895BD287}.Release|Any CPU.Build.0 = Release|Any CPU
{F3FF4A85-1949-47E0-9E2B-052CF72BFA44}.Debug|Any CPU.ActiveCfg = Release|Any CPU
{F3FF4A85-1949-47E0-9E2B-052CF72BFA44}.Debug|Any CPU.Build.0 = Release|Any CPU
{F3FF4A85-1949-47E0-9E2B-052CF72BFA44}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F3FF4A85-1949-47E0-9E2B-052CF72BFA44}.Release|Any CPU.Build.0 = Release|Any CPU
{4C54F119-650D-4939-8713-83FCA0484E3B}.Debug|Any CPU.ActiveCfg = Release|Any CPU
{4C54F119-650D-4939-8713-83FCA0484E3B}.Debug|Any CPU.Build.0 = Release|Any CPU
{4C54F119-650D-4939-8713-83FCA0484E3B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4C54F119-650D-4939-8713-83FCA0484E3B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {A44477E2-1912-4925-9DCB-297C07E1CE39}
EndGlobalSection
EndGlobal

File diff suppressed because it is too large Load Diff

@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
</Project>
Loading…
Cancel
Save