-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
1ffe40f
commit 1350fde
Showing
30 changed files
with
2,087 additions
and
24 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,7 @@ | ||
# HashingHandler | ||
# HashingHandler | ||
|
||
A C# library containing abstract classes for hashing data of various types. | ||
|
||
View & Download this project on [NuGet](https://www.nuget.org/packages/HashingHandler/). | ||
|
||
View the documentation for this project at [the website](https://simon-techkid.github.io/HashingHandler/). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,155 @@ | ||
# Algorithms | ||
|
||
Algorithms in HashingHandler implement IHashingAlgorithm or IHashingAlgorithmAsync. Implementers of IHashingAlgorithmAsync also implement IHashingAlgorithm. IHashingAlgorithm provides synchronous hashing algorithm computation, and IHashingAlgorithmAsync provides both synchronous and asynchronous computation support. | ||
|
||
`HashingAlgorithmBase` is the primary base class for implementations of `IHashingAlgorithm` and `IHashingAlgorithmAsync`. It provides support for both synchronous and asynchronous hash computation, using `protected` methods `byte[] ComputeHash()` and `Task<byte[]> ComputeHashAsync()`, as well as synchronous and asynchronous checksum computation of those hashes, using `public` methods `string ComputeHash()` and `Task<string> ComputeHashAsync()`. | ||
|
||
## Variants | ||
|
||
### IHashingAlgorithm | ||
|
||
`IHashingAlgorithm<T>` is used for accessing hash algorithm classes. These classes allow the hashing of byte arrays (`byte[]`), producing `string` checksums of the given data. | ||
|
||
### IHashingAlgorithmAsync | ||
|
||
`IHashingAlgorithmAsync<T>` allows the asynchronous use of `IHashingAlgorithm<T>`. It implements `IHashingAlgorithm<T>`, so objects capable of asynchronous computation are also able to leverage synchronous methods. | ||
|
||
## HashingCrypto and HashingNonCrypto | ||
|
||
HashingHandler contains base classes for creating hashes using its `HashingCrypto` and `HashingNonCrypto` classes, allowing hash creation using [HashAlgorithm](https://learn.microsoft.com/dotnet/api/system.security.cryptography.hashalgorithm) and [NonCryptographicHashAlgorithm](https://learn.microsoft.com/dotnet/api/system.io.hashing.noncryptographichashalgorithm), respectively. | ||
|
||
Both of these classes implement `IHashingAlgorithm<string>` and `IHashingAlgorithmAsync<string>` because they inherit `HashingNonCrypto<string>` and `HashingAlgorithmBase<string>`. This allows you to create common functionality across your program by using the shared methods in different contexts. | ||
|
||
### Getting Started | ||
|
||
To get started using `HashingCrypto` and `HashingNonCrypto` abstract classes in your program, you must create a class that implements one of these. Below are samples that allow calculation of SHA256 and XXH3 hashes using both `HashAlgorithm` and `NonCryptographicHashAlgorithm` abstract classes. | ||
|
||
In your class implementing `HashingCrypto` or `HashingNonCrypto`, you must provide a method, `GetAlgorithm()`, that returns an instance of a hashing class (ie. `SHA256` or `XxHash3`) derived from either `HashAlgorithm` or `NonCryptographicHashAlgorithm`, respectively. This instance will then be used by the base, implemented class to create hashes using those algorithms. | ||
|
||
See the sample implementations below of each. | ||
|
||
## Samples | ||
|
||
After creating a class that inherits `IHashingAlgorithm<T>` (including the below samples), you are able to compute hashes for data of type `T`, using the `IHashingAlgorithm<T>.ComputeHash()` method. This method returns a `string` of the hash of the data. | ||
|
||
#### HashingCrypto | ||
|
||
``` | ||
class SHA256Hasher : HashingCrypto<string> | ||
{ | ||
protected override HashAlgorithm GetAlgorithm() | ||
{ | ||
return SHA256.Create(); // Returns new SHA256 object | ||
} | ||
} | ||
``` | ||
|
||
To create a hash using the SHA256 algorithm, construct this `SHA256Hasher` class. | ||
|
||
It can be cast to `IHashingAlgorithm`: | ||
``` | ||
IHashingAlgorithm<string> sha256 = new SHA256Hasher(); | ||
``` | ||
|
||
It can also be cast to `IHashingAlgorithmAsync` for asynchronous use, because `HashingCrypto` implements it. | ||
``` | ||
IHashingAlgorithmAsync<string> sha256Async = new SHA256Hasher(); | ||
``` | ||
|
||
#### HashingNonCrypto | ||
|
||
``` | ||
class XXH3Hasher(long seed = 0) : HashingNonCrypto<string> | ||
{ | ||
private readonly long _seed = seed; // XxHash3 allows a seed, so we will add seed support to our class | ||
protected override NonCryptographicHashAlgorithm GetAlgorithm() | ||
{ | ||
return new XxHash3(_seed); | ||
} | ||
} | ||
``` | ||
|
||
To create a hash using the XXH3 algorithm, construct this `XXH3Hasher` class. | ||
|
||
It can be cast to `IHashingAlgorithm`: | ||
``` | ||
IHashingAlgorithm<string> xxh3 = new XXH3Hasher(); | ||
``` | ||
|
||
It can also be cast to `IHashingAlgorithmAsync` for asynchronous use, because `HashingNonCrypto` implements it. | ||
``` | ||
IHashingAlgorithmAsync<string> xxh3Async = new XXH3Hasher(); | ||
``` | ||
|
||
#### Create Your Own | ||
|
||
To create your own hashing algorithm, create a class implementing `IHashingAlgorithm` or `IHashingAlgorithmAsync`. Remember, `IHashingAlgorithmAsync` implements `IHashingAlgorithm`, so you must provide a synchronous implementation for it! | ||
|
||
I've chosen to inherit `HashingAlgorithmBase<T>`, because it provides both asynchronous and synchronous support in the base class. The below example provides a synchronous implementation. | ||
|
||
By inheriting `HashingAlgorithmBase`, you make this `XORHash` class an `IHashingAlgorithm<T>` and `IHashingAlgorithmAsync<T>`. | ||
|
||
The below example is a simple XOR hash algorithm: | ||
|
||
``` | ||
class XORHash : HashingAlgorithmBase<object> | ||
{ | ||
protected override byte[] ComputeHash(byte[] bytes) | ||
{ | ||
// Specify the length of the payload to be hashed. | ||
int payloadLength = bytes.Length; // Let's hash the entire payload. | ||
// Specify the length of the returned hash. | ||
int hashLength = 8; // 8 bytes, 16 characters | ||
// Initialize result array to hold the hash of specified length | ||
byte[] result = new byte[hashLength]; | ||
// Perform XOR on the bytes, distributing across each position in result | ||
for (int i = 0; i < payloadLength; i++) | ||
{ | ||
result[i % hashLength] ^= bytes[i]; | ||
} | ||
return result; | ||
} | ||
} | ||
``` | ||
|
||
To create a hash using this sample algorithm, construct this `XORHash` class. | ||
|
||
It can be cast to `IHashingAlgorithm`: | ||
``` | ||
IHashingAlgorithm<object> xor = new XORHash(); | ||
``` | ||
|
||
It can also be cast to `IHashingAlgorithmAsync` for asynchronous use, because `HashingAlgorithmBase` implements it. | ||
``` | ||
IHashingAlgorithmAsync<object> xor = new XORHash(); | ||
``` | ||
|
||
Because we didn't override `HashingAlgorithmBase.ComputeHashAsync()` in the above sample implementation, any calls to `xor.ComputeHashAsync()` will use the default implementation, a `Task.Run()` of the synchronous implementation, `ComputeHash()`. If you'd like to create a specific asynchronous implementation, override `ComputeHashAsync()`. | ||
|
||
### Conclusion | ||
|
||
After creating the `IHashingAlgorithm<T>` or `IHashingAlgorithmAsync<T>` implementing object, you can perform hashing using the methods of `IHashingAlgorithm<T>` or `IHashingAlgorithmAsync<T>`, respectively. | ||
|
||
``` | ||
// Create an IHashingProvider<T>, where T matches the type of your IHashingAlgorithm<T>. | ||
// Assume we have instantiated an IHashingProvider<string> called 'provider' | ||
// See the above samples on how to create an IHashingAlgorithm. | ||
// Assume we have instantiated an IHashingAlgorithm<string> called 'algorithm' | ||
string textPayload = "Hello World!"; | ||
return algorithm.ComputeHash(textPayload, provider); | ||
``` | ||
|
||
We can also do it asynchronously, if our `algorithm` instance is `IHashingAlgorithmAsync<string>` | ||
|
||
``` | ||
// Simulated asynchronous method below by using GetAwaiter().GetResult() | ||
return algorithm.ComputeHashAsync(textPayload, provider).GetAwaiter().GetResult(); | ||
``` | ||
|
||
Remember, `IHashingAlgorithmAsync<T>` implements `IHashingAlgorithm<T>`, so you can perform synchronous hashing using an asynchronous hashing capable object using the methods of `IHashingAlgorithm<T>` on an `IHashingAlgorithmAsync<T>`. |
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
# Providers | ||
|
||
Providers in HashingHandler implement `IHashingProvider<T>` or `IHashingProviderAsync<T>`. Implementers of `IHashingProviderAsync<T>` also implement `IHashingProvider<T>`. | ||
|
||
## Variants | ||
|
||
### IHashingProvider | ||
|
||
`IHashingProvider<T>` is used when an object can convert the data to be hashed of type `T` to a byte array (`byte[]`), so that the byte array can serve as a common type in all hash operations. | ||
|
||
### IHashingProviderAsync | ||
|
||
`IHashingProviderAsync<T>` is offered when an object of type `T` can be converted to a byte array asynchronously. `IHashingProviderAsync<T>` implements `IHashingProvider<T>`, so objects that are capable of handling asynchronous conversions are also able to leverage the synchronous methods of `IHashingProvider<T>`. | ||
|
||
## Examples | ||
|
||
You can find several examples of data types that you may want to create hashes for. | ||
|
||
### Strings | ||
|
||
HashingHandler contains a built-in base class to serve as an `IHashingProvider<T>` for `string` types, `StringHashProviderBase<T>`. Implementers of `StringHashProviderBase<T>` must define how to convert the data of type `T` to a `string`. The base class, `StringHashProviderBase` handles conversion of this string (using the method `ConvertToString`) to bytes, using a byte encoding. | ||
|
||
Adding the below class to your program, which implements `StringHashProviderBase`, will provide a structure for hashing `string` instances. | ||
|
||
``` | ||
class StringProvider : StringHashProviderBase<string> | ||
{ | ||
protected override string ConvertToString(string data) | ||
{ | ||
return data; // Already string, no conversion necessary | ||
} | ||
// Below is not a required field, but overriding it in your class will allow you to use other byte encodings than the default, UTF8. | ||
protected override Encoding HashedDataEncoding => Encoding.UTF16 | ||
} | ||
``` | ||
|
||
Because this `StringProvider` class inherits `StringHashProviderBase`, it also implements `IHashingProvider`. | ||
|
||
To create a provider for converting the `string` data type to `byte[]` for hashing later, construct the example `StringProvider` class. | ||
|
||
``` | ||
IHashingProvider<string> provider = new StringProvider(); | ||
``` | ||
|
||
You now have an `IHashingProvider<string>` that can be passed to an `IHashingAlgorithm<string>` to create a hash. | ||
|
||
``` | ||
// Assume we have initialized the provider as well as an IHashingAlgorithm<string> above. | ||
// The IHashingProvider<string> instance is called 'provider' | ||
// The IHashingAlgorithm<string> instance is called 'algorithm' | ||
string testPayload = "Hello World!"; | ||
string testHash = algorithm.ComputeHash(testPayload, provider); | ||
Console.WriteLine(testHash); | ||
``` | ||
|
||
We can compute the hash on another thread, if you've got an `IHashingAlgorithmAsync<string>`. Let's call the instance of the algorithm `algorithm`. | ||
|
||
``` | ||
string testHash = algorithm.ComputeHashAsync(testPayload, provider).GetAwaiter().GetResult(); | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,4 @@ | ||
- name: Introduction | ||
href: introduction.md | ||
- name: Getting Started | ||
href: getting-started.md | ||
- name: Algorithms | ||
href: algorithms.md | ||
- name: Providers | ||
href: providers.md |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
{{!Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information.}} | ||
{{!include(/^styles/.*/)}} | ||
{{!include(/^fonts/.*/)}} | ||
{{!include(favicon.ico)}} | ||
{{!include(logo.svg)}} | ||
{{!include(search-stopwords.json)}} | ||
<!DOCTYPE html> | ||
<!--[if IE]><![endif]--> | ||
<html> | ||
{{>partials/head}} | ||
|
||
<body> | ||
<!-- Header required for docfx anchor scroll to work --> | ||
<header id="head"></header> | ||
<div class="top-navbar"> | ||
<a class="burger-icon" onclick="toggleMenu()"> | ||
<svg name="Hamburger" | ||
style="vertical-align: middle;" | ||
width="34" height="34" viewBox="0 0 24 24"><path fill="currentColor" fill-rule="evenodd" clip-rule="evenodd" d="M20 6H4V9H20V6ZM4 10.999H20V13.999H4V10.999ZM4 15.999H20V18.999H4V15.999Z"></path></svg> | ||
</a> | ||
|
||
{{>partials/logo}} | ||
</div> | ||
|
||
<div class="body-content"> | ||
<div id="blackout" class="blackout" onclick="toggleMenu()"></div> | ||
|
||
<nav id="sidebar" role="navigation"> | ||
<div class="sidebar"> | ||
{{>partials/navbar}} | ||
<div class="sidebar-item-separator"></div> | ||
{{^_disableToc}} | ||
{{>partials/toc}} | ||
{{/_disableToc}} | ||
</div> | ||
{{>partials/footer}} | ||
</nav> | ||
|
||
<main class="main-panel"> | ||
{{#_enableSearch}} | ||
{{>partials/searchResults}} | ||
{{/_enableSearch}} | ||
|
||
|
||
|
||
<div role="main" class="hide-when-search" > | ||
{{^_disableBreadcrumb}} | ||
{{>partials/breadcrumb}} | ||
{{/_disableBreadcrumb}} | ||
|
||
{{^_disableContribution}} | ||
<div id="contribution"> | ||
{{#docurl}} | ||
<a href="{{docurl}}" class="contribution-link">{{__global.improveThisDoc}}</a> | ||
{{/docurl}} | ||
</div> | ||
{{/_disableContribution}} | ||
|
||
<article class="content wrap" id="_content" data-uid="{{uid}}"> | ||
{{!body}} | ||
</article> | ||
</div> | ||
|
||
{{#_copyrightFooter}} | ||
<div class="copyright-footer"> | ||
<span>{{_copyrightFooter}}</span> | ||
</div> | ||
{{/_copyrightFooter}} | ||
</main> | ||
</div> | ||
|
||
{{>partials/scripts}} | ||
</body> | ||
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
<div class="footer"> | ||
{{{_appFooter}}} | ||
{{^_appFooter}}<strong><a href='https://dotnet.github.io/docfx/'>DocFX</a> + <a href='https://www.singulink.com'>Singulink</a> = ♥</strong>{{/_appFooter}} | ||
</div> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
{{!Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information.}} | ||
|
||
<head> | ||
<meta charset="utf-8"> | ||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1"> | ||
<title>{{#title}}{{title}}{{/title}}{{^title}}{{>partials/title}}{{/title}} {{#_appTitle}}| {{_appTitle}} {{/_appTitle}}</title> | ||
<meta name="viewport" content="width=device-width"> | ||
<meta name="title" content="{{#title}}{{title}}{{/title}}{{^title}}{{>partials/title}}{{/title}} {{#_appTitle}}| {{_appTitle}} {{/_appTitle}}"> | ||
<meta name="generator" content="docfx {{_docfxVersion}}"> | ||
{{#_description}}<meta name="description" content="{{_description}}">{{/_description}} | ||
<link rel="shortcut icon" href="{{_rel}}{{{_appFaviconPath}}}{{^_appFaviconPath}}favicon.ico{{/_appFaviconPath}}"> | ||
<link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500;700&display=swap" rel="stylesheet"> | ||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.7.0/styles/night-owl.min.css"> | ||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.7.2/font/bootstrap-icons.css" integrity="sha384-EvBWSlnoFgZlXJvpzS+MAUEjvN7+gcCwH+qh7GRFOGgZO0PuwOFro7qPOJnLfe7l" crossorigin="anonymous"> | ||
<link rel="stylesheet" href="{{_rel}}styles/config.css"> | ||
<link rel="stylesheet" href="{{_rel}}styles/singulink.css"> | ||
<link rel="stylesheet" href="{{_rel}}styles/main.css"> | ||
<meta property="docfx:navrel" content="{{_navRel}}"> | ||
<meta property="docfx:tocrel" content="{{_tocRel}}"> | ||
{{#_noindex}}<meta name="searchOption" content="noindex">{{/_noindex}} | ||
{{#_enableSearch}}<meta property="docfx:rel" content="{{_rel}}">{{/_enableSearch}} | ||
{{#_enableNewTab}}<meta property="docfx:newtab" content="true">{{/_enableNewTab}} | ||
</head> |
Oops, something went wrong.