Skip to content

Commit

Permalink
Update docs
Browse files Browse the repository at this point in the history
  • Loading branch information
simon-techkid committed Nov 30, 2024
1 parent fe4d271 commit 1f55e72
Show file tree
Hide file tree
Showing 7 changed files with 232 additions and 13 deletions.
25 changes: 25 additions & 0 deletions Samples/HashingHandlerSamples.sln
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.11.35327.3
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HashingHandlerSamples", "src\HashingHandlerSamples.csproj", "{8D2696BC-FB37-4E71-8FDA-DC741EC9D972}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{8D2696BC-FB37-4E71-8FDA-DC741EC9D972}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{8D2696BC-FB37-4E71-8FDA-DC741EC9D972}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8D2696BC-FB37-4E71-8FDA-DC741EC9D972}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8D2696BC-FB37-4E71-8FDA-DC741EC9D972}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {5F4650F6-A119-4F26-A645-C2F72B5881C4}
EndGlobalSection
EndGlobal
15 changes: 15 additions & 0 deletions Samples/src/HashingHandlerSamples.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="HashingHandler" Version="1.7.0" />
<PackageReference Include="HashingHandler.Formats.String" Version="1.3.0" />
</ItemGroup>

</Project>
124 changes: 124 additions & 0 deletions Samples/src/Program.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
using HashingHandler;
using HashingHandler.Formats.String;
using System.IO.Hashing;
using System.Security.Cryptography;
using System.Text;

namespace HashingHandlerSamples;

class Program
{
static void Main(string[] args)
{
// Synchronous Only
/*
IHashingAlgorithm<string> sha256 = new SHA256Hasher();
IHashingAlgorithm<string> xxh3 = new XXH3Hasher();
IHashingAlgorithm<string> xor = new XORHash();
*/

// Synchronous and Asynchronous
IHashingAlgorithmAsync<string> sha256 = new SHA256Hasher();
IHashingAlgorithmAsync<string> xxh3 = new XXH3Hasher();
IHashingAlgorithmAsync<string> xor = new XORHash();

// Hash provider of string data
IHashingProvider<string> provider = new StringHashProvider(Encoding.UTF8);

// Synchronous Only
/*
IHashVerifier<string> stringVerifier = new StringHashVerifier();
*/

// Synchronous and Asynchronous
IHashVerifierAsync<string> stringVerifier = new StringHashVerifier();

// Base64 encoding of hash bytes
IStringEncodingAsync base64 = new Base64Hashes();

while (true)
{
Console.Write("Enter some text: ");
string text = Console.ReadLine() ?? string.Empty;

// Sha256
string hashSha256 = sha256.ComputeHash(text, provider);
bool matchSha = stringVerifier.VerifyHash(text, hashSha256, sha256); // True, hashes match

// Sha256 in base64
string hashSha256Base64 = sha256.ComputeHash(text, provider, encoding: base64);
bool matchShaBase64 = stringVerifier.VerifyHash(text, hashSha256Base64, sha256, encoding: base64); // True, hashes match

// Xxh3
string hashXxh3 = xxh3.ComputeHash(text, provider);
bool matchXxh3 = stringVerifier.VerifyHash(text, hashXxh3, xxh3); // True, hashes match

// XOR
string hashXor = xor.ComputeHashAsync(text, provider).GetAwaiter().GetResult();
bool matchXor = stringVerifier.VerifyHash(text, hashXor, xor); // True, hashes match

// False, because SHA256 and XXH3 are different algorithms that produce different hashes for the same data.
bool testFail = stringVerifier.VerifyHash(text, hashXxh3, sha256);

// False, because sha256 is not encoded in base64
bool testFail2 = stringVerifier.VerifyHash(text, hashSha256, sha256, base64);

Console.WriteLine();
Console.WriteLine($"SHA256: {hashSha256} {matchSha}");
Console.WriteLine($"SHA256 Base64: {hashSha256Base64} {matchShaBase64}");
Console.WriteLine($"XXH3: {hashXxh3} {matchXxh3}");
Console.WriteLine($"XOR: {hashXor} {matchXor}");
Console.WriteLine($"Fail test success: {!testFail} {!testFail2}");
Console.WriteLine();
}
}
}

class Base64Hashes : StringEncodingBase
{
public override string ConvertToString(byte[] bytes)
{
return Convert.ToBase64String(bytes);
}
}

class SHA256Hasher : HashingCrypto<string>
{
protected override HashAlgorithm GetAlgorithm()
{
return SHA256.Create(); // Returns new SHA256 object
}
}

class XXH3Hasher(long seed = 0) : HashingNonCrypto<string>
{
private readonly long _seed = seed;

protected override NonCryptographicHashAlgorithm GetAlgorithm()
{
return new XxHash3(_seed);
}
}

class XORHash : HashingAlgorithmBase<string>
{
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;
}
}
10 changes: 6 additions & 4 deletions docfx/docs/algorithms.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ algorithm = new XORHash(); // change
algorithm = new GenericAsyncHasher(algorithm); // change
```

### Working with implementers of `IHashingAlgorithmAsync<T>`
### Working with `IHashingAlgorithmAsync<T>` instances

The following types are `IHashingAlgorithmAsync<T>`:

Expand All @@ -175,9 +175,9 @@ IHashingAlgorithm<string> xor = new XORHash();
asyncAlgorithm = new GenericAsyncHasher(xor); // change
```

### Creating hashes using our `IHashingAlgorithm<T>` or `IHashingAlgorithmAsync<T>` types
### Creating hashes using `IHashingAlgorithm<T>` instances

After creating the `IHashingAlgorithm<T>` or `IHashingAlgorithmAsync<T>` implementing object, you can perform hashing using the methods of `IHashingAlgorithm<T>` or `IHashingAlgorithmAsync<T>`, respectively.
After creating the `IHashingAlgorithm<T>` implementing object, you can perform hashing using the methods of `IHashingAlgorithm<T>`.

```
// Create an IHashingProvider<T>, where T matches the type of your IHashingAlgorithm<T>.
Expand All @@ -189,7 +189,9 @@ string textPayload = "Hello World!";
string hash = algorithm.ComputeHash(textPayload, provider);
```

We can also do it asynchronously, if our `algorithm` instance is `IHashingAlgorithmAsync<string>` and our method is `async`.
### Creating hashes using `IHashingAlgorithmAsync<T>` instances

After creating the `IHashingAlgorithmAsync<T>` implementing object, you can perform asynchronous or synchronous hashing using the methods of `IHashingAlgorithmAsync<T>` or `IHashingAlgorithm<T>`, respectively.

```
// Simulated asynchronous method below by using GetAwaiter().GetResult()
Expand Down
8 changes: 6 additions & 2 deletions docfx/docs/providers.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,9 @@ Providers in HashingHandler implement `IHashingProvider<T>` or `IHashingProvider

## Examples

### Implementing `IHashingProvider<T>` and `IHashingProviderAsync<T>`
### Implementing `IHashingProvider<T>`

Below are some examples of classes that implement either `IHashingProvider<T>` or `IHashingProviderAsync<T>`.
Below are some examples of classes that implement `IHashingProvider<T>`.

#### String - `IHashingProvider<string>`

Expand Down Expand Up @@ -67,6 +67,10 @@ class DateTimeProvider : IHashingProvider<DateTime>
}
```

### Implementing `IHashingProviderAsync<T>`

Below are some examples of classes that implement `IHashingProviderAsync<T>` and `IHashingProvider<T>`.

#### Stream - `IHashingProviderAsync<Stream>`

In some cases, you may want to convert hashable data types to `byte[]` asynchronously. This can be done with implementers of `IHashingProviderAsync<T>`.
Expand Down
54 changes: 54 additions & 0 deletions docfx/docs/verifiers.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Verifiers

Verifiers in HashingHandler implement `IHashVerifier<T>` or `IHashVerifierAsync<T>`. Implementers of `IHashVerifierAsync<T>` also implement `IHashVerifier<T>`.

## Variants

### IHashVerifier

`IHashVerifier<T>` is used for accessing hash verifier classes. These classes allow for the verification of data against expected hashes.

### IHashVerifierAsync

`IHashVerifierAsync<T>` allows the asynchronous use of `IHashVerifier<T>`. It implements `IHashVerifier<T>`, so objects capable of asynchronous verification are also able to leverage synchronous methods.

### HashVerifierBase

`HashVerifierBase<T>` is the primary base class for implementations of both `IHashVerifierAsync<T>` and `IHashVerifier<T>`, providing methods for both. It provides support for both synchronous and asynchronous hash verification, using `public` methods `bool VerifyHash()` and `Task<bool> VerifyHashAsync()`.

### HashVerifierGeneric

`HashVerifierGeneric<T>` provides a generic implementation of `HashVerifierBase<T>`. It can be constructed with the required `IHashingProvider<T>` and optional `StringComparison` setting for the comparison of the hash strings.

## Examples

If you'd like to provide type-flexible hash verification, use an implementation of `HashVerifierBase<T>` or a `HashVerifierGeneric<T>` rather than making your own implementation of `IHashVerifier<T>` or `IHashVerifierAsync<T>`. Only make your own `IHashVerifier<T>` or `IHashVerifierAsync<T>` if you'd like to use a different string comparison method than [`string.Equals()`](https://learn.microsoft.com/dotnet/api/system.string.equals) for hash strings.

### Implementing `HashVerifierGeneric<T>`

`HashVerifierGeneric<T>` is a non-abstract class implementation of the abstract class `HashVerifierBase<T>`, meaning you can instantiate it and re-use it for verifications of the same data type, `T`.

```
public class MyClass
{
public static bool VerifyHash(DateTime data, string expectedHash)
{
// Create an IHashingProvider<DateTime> called 'provider'.
IHashVerifier<DateTime> verifier = CreateVerifier(provider);
// Create an IHashingAlgorithm<DateTime> called 'algorithm'.
// Optionally, create an IStringEncoding called 'encoding' to use for hash byte encoding.
// Not doing this will interpret the hash calculation as Hexadecimal string by default.
return verifier.VerifyHash(data, expectedHash, algorithm, encoding) // encoding is an optional parameter.
}
// could also return IHashVerifier<DateTime> because HashVerifierGeneric is IHashVerifierAsync.
private static IHashVerifier<DateTime> CreateVerifier(IHashingProvider<DateTime> provider)
{
return new HashVerifierGeneric(provider); // StringComparison is an optional parameter for the constructor.
}
}
```
9 changes: 2 additions & 7 deletions src/HashingAlgorithmBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,7 @@ public string ComputeHash(T data, IHashingProvider<T> provider, IStringEncoding?
return encoding.ConvertToString(hashBytes);
}

public Task<string> ComputeHashAsync(T data, IHashingProvider<T> provider, CancellationToken cancellationToken = default, IStringEncoding? encoding = null)
{
return Task.Run(() => AsyncHashComputation(data, provider, cancellationToken, encoding), cancellationToken);
}

private async Task<string> AsyncHashComputation(T data, IHashingProvider<T> provider, CancellationToken cancellationToken, IStringEncoding? encoding)
public async Task<string> ComputeHashAsync(T data, IHashingProvider<T> provider, CancellationToken cancellationToken = default, IStringEncoding? encoding = null)
{
encoding ??= new StringExtensions();

Expand All @@ -56,7 +51,7 @@ private async Task<string> AsyncHashComputation(T data, IHashingProvider<T> prov
}

byte[] hashBytes = await ComputeHashAsync(bytes, cancellationToken);

if (encoding is IStringEncodingAsync asyncEncoding)
{
return await asyncEncoding.ConvertToStringAsync(hashBytes);
Expand Down

0 comments on commit 1f55e72

Please sign in to comment.