Skip to content

Commit

Permalink
Merge pull request #10 from AndreyRusyaev/feature/sha3-implementation
Browse files Browse the repository at this point in the history
Sha3 support
  • Loading branch information
AndreyRusyaev committed Jan 27, 2024
2 parents 51b871e + f53a232 commit 5d4d94d
Show file tree
Hide file tree
Showing 54 changed files with 2,062 additions and 319 deletions.
134 changes: 103 additions & 31 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,37 +1,37 @@
# acryptohashnet
A pure C# implementation of well-known cryptographic hash functions for .Net Standard 2.0 compatible platforms (.Net Framework, .Net Core, Mono, Xamarin, UWP, Unity).
A pure C# implementation of cryptographic hash functions for .Net Standard 2.0 compatible platforms (.Net Framework, .Net Core, Mono, Xamarin, UWP, Unity).

# Features
* Pure managed implementations,
* Compatible with System.Security.Cryptography.HashAlgorithm and can be used everywhere as a simple replacement of the target hash algorithm,
* Fast and has low memory footprint (less GC).

* Pure managed C# implementation,
* Compatible with System.Security.Cryptography.HashAlgorithm and can be used everywhere as a simple drop replacement for the target hash algorithm,
* Extremely fast, highly optimized with low memory footprint (less GC time).

# Usage examples

## MD5 of file
## MD5

``` csharp
using System;
using System.IO;
using System.Linq;
using System.Text;

static class Program
{
static void Main(string[] args)
{
var hashAlgorithm = new acryptohashnet.MD5();

using(var stream = File.OpenRead(@"C:\Windows\System32\explorer.exe"))
static void Main(string[] args)
{
var hashBytes = hashAlgorithm.ComputeHash(stream);
Console.WriteLine("Hash: {0}", hashBytes.ToHexString());
var message = "Test Message";

var hashAlgorithm = new acryptohashnet.MD5();
Console.WriteLine("MD5: {0}", hashAlgorithm.ComputeHash(message.ToUtf8Bytes()).ToHexString());
}
}

static string ToHexString(this byte[] input) => string.Join("", input.Select(x => x.ToString("x2")));
static byte[] ToUtf8Bytes(this string input) => Encoding.UTF8.GetBytes(input);
static string ToHexString(this byte[] input) => string.Join("", input.Select(x => x.ToString("x2")));
}
```

## SHA512 of string
## SHA256 (SHA2-256 bits)

``` csharp
using System;
Expand All @@ -40,36 +40,108 @@ using System.Text;

static class Program
{
static void Main(string[] args)
{
var hashAlgorithm = new acryptohashnet.SHA512();
var hashBytes = hashAlgorithm.ComputeHash("message digest".ToUtf8Bytes());
Console.WriteLine("Hash: {0}", hashBytes.ToHexString());
}

static byte[] ToUtf8Bytes(this string input) => Encoding.UTF8.GetBytes(input);
static string ToHexString(this byte[] input) => string.Join("", input.Select(x => x.ToString("x2")));
static void Main(string[] args)
{
var message = "Test Message";

var hashAlgorithm = new acryptohashnet.Sha2_256();
Console.WriteLine("SHA256: {0}", hashAlgorithm.ComputeHash(message.ToUtf8Bytes()).ToHexString());
}

static byte[] ToUtf8Bytes(this string input) => Encoding.UTF8.GetBytes(input);
static string ToHexString(this byte[] input) => string.Join("", input.Select(x => x.ToString("x2")));
}
```

## Compute string message hash via HashAlgorithm interface (MD5, SHA1, SHA256, SHA3-512)

``` csharp
static class Program
{
static void Main(string[] args)
{
var md5 = new acryptohashnet.MD5();
var sha1 = new acryptohashnet.SHA1();
var sha2_256 = new acryptohashnet.Sha2_256();
var sha3_512 = new acryptohashnet.Sha3_512();

var message = "Lorem ipsum is placeholder text commonly used in the graphic, " +
"print, and publishing industries for previewing layouts and visual mockups.";

Console.WriteLine("MD5: {0}", md5.ComputeHash(message.ToUtf8Bytes()).ToHexString());
Console.WriteLine("SHA1: {0}", sha1.ComputeHash(message.ToUtf8Bytes()).ToHexString());
Console.WriteLine("SHA256: {0}", sha2_256.ComputeHash(message.ToUtf8Bytes()).ToHexString());
Console.WriteLine("SHA3-512: {0}", sha3_512.ComputeHash(message.ToUtf8Bytes()).ToHexString());
}

static byte[] ToUtf8Bytes(this string input) => System.Text.Encoding.UTF8.GetBytes(input);
static string ToHexString(this byte[] input) => string.Join("", input.Select(x => x.ToString("x2")));
}
```

## Compute hash of file via HashAlgorithm interface (MD5, SHA1, SHA256, SHA3-512)

``` csharp
static class Program
{
static void Main(string[] args)
{
var md5 = new acryptohashnet.MD5();
var sha1 = new acryptohashnet.SHA1();
var sha2_256 = new acryptohashnet.Sha2_256();
var sha3_512 = new acryptohashnet.Sha3_512();

using (var file = File.OpenRead(@"C:\Windows\explorer.exe"))
{
Console.WriteLine("MD5: {0}", md5.ComputeHash(file).ToHexString());

file.Position = 0; // Rewind stream to beginning
Console.WriteLine("SHA1: {0}", sha1.ComputeHash(file).ToHexString());

file.Position = 0; // Rewind stream to beginning
Console.WriteLine("SHA256: {0}", sha2_256.ComputeHash(file).ToHexString());

file.Position = 0; // Rewind stream to beginning
Console.WriteLine("SHA3-512: {0}", sha3_512.ComputeHash(file).ToHexString());
}
}

static string ToHexString(this byte[] input) => string.Join("", input.Select(x => x.ToString("x2")));
}
```

# Implemented hash functions
# Implemented hash algorithms

## MD Family
All functions designed and specified by [Ron Rivest](https://en.wikipedia.org/wiki/Ron_Rivest).
* MD2, specification: [RFC 1319](docs/rfc1319.txt).
* MD4, specification: [RFC 1320](docs/rfc1320.txt).
* MD5, specification: [RFC 1321](docs/rfc1320.txt).

## SHA Family
Secure Hash Standard [[pdf]](docs/fips180-3_final.pdf)
## SHA0 & SHA1
Secure Hash Standard [[pdf]](docs/NIST.FIPS.180-4.pdf)

## SHA2 Family
Secure Hash Standard [[pdf]](docs/NIST.FIPS.180-4.pdf)

Published as standard by "National Institute of Standards and Technology".

* SHA-0,
* SHA-1,
* SHA-256,
* SHA-384,
* SHA-512
* SHA2-224 (also known as SHA224),
* SHA2-256 (also known as SHA256),
* SHA2-384 (also known as SHA384),
* SHA2-512 (also known as SHA512)

## SHA3 Family
SHA-3 Standard: Permutation-Based Hash and Extendable-Output Functions [[pdf]](docs/NIST.FIPS.202.pdf)

Published as standard by "National Institute of Standards and Technology".

* SHA3-224,
* SHA3-256,
* SHA3-384,
* SHA3-512

## RIPEMD
RIPEMD-160: A Strengthened Version of RIPEMD [[pdf]](docs/AB-9601.pdf)
Expand Down
1 change: 1 addition & 0 deletions build/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pwsh -ExecutionPolicy ByPass -NoProfile -file ./build.ps1
Binary file added docs/Damgaard_DesignPrincipleForHashFunctions.pdf
Binary file not shown.
Binary file added docs/Keccak-implementation-3.2.pdf
Binary file not shown.
Binary file added docs/Keccak-submission-3.pdf
Binary file not shown.
Binary file added docs/Merkle_Thesis1979.pdf
Binary file not shown.
Binary file added docs/NIST.FIPS.180-4.pdf
Binary file not shown.
Binary file added docs/NIST.FIPS.202.pdf
Binary file not shown.
Binary file added docs/S.Lucks_DesignPrincipleForHashFunctions.pdf
Binary file not shown.
Binary file added docs/Sakura.pdf
Binary file not shown.
Binary file removed docs/fips180-3_final.pdf
Binary file not shown.
Binary file not shown.
17 changes: 0 additions & 17 deletions readme.txt

This file was deleted.

16 changes: 4 additions & 12 deletions src/acryptohashnet.Benchmarks/Program.cs
Original file line number Diff line number Diff line change
@@ -1,13 +1,5 @@
using BenchmarkDotNet.Configs;
using BenchmarkDotNet.Jobs;
using BenchmarkDotNet.Running;
using BenchmarkDotNet.Running;

namespace acryptohashnet.Benchmarks
{
internal static class Program
{
static void Main(string[] args) => BenchmarkSwitcher
.FromAssembly(typeof(Program).Assembly)
.Run(args);
}
}
BenchmarkSwitcher
.FromAssembly(typeof(Program).Assembly)
.Run(args);
2 changes: 1 addition & 1 deletion src/acryptohashnet.Benchmarks/SHA256Benchmark.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public class SHA256Benchmark

private System.Security.Cryptography.SHA256Managed systemManagedImpl = new System.Security.Cryptography.SHA256Managed();

private global::acryptohashnet.SHA256 acryptohashnetImpl = new global::acryptohashnet.SHA256();
private global::acryptohashnet.Sha2_256 acryptohashnetImpl = new global::acryptohashnet.Sha2_256();

[ParamsSource(nameof(InputSource))]
public byte[] Input { get; set; }
Expand Down
2 changes: 1 addition & 1 deletion src/acryptohashnet.Benchmarks/SHA384Benchmark.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public class SHA384Benchmark

private System.Security.Cryptography.SHA384Managed systemManagedImpl = new System.Security.Cryptography.SHA384Managed();

private global::acryptohashnet.SHA384 acryptohashnetImpl = new global::acryptohashnet.SHA384();
private global::acryptohashnet.Sha2_384 acryptohashnetImpl = new global::acryptohashnet.Sha2_384();

[ParamsSource(nameof(InputSource))]
public byte[] Input { get; set; }
Expand Down
2 changes: 1 addition & 1 deletion src/acryptohashnet.Benchmarks/SHA512Benchmark.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public class SHA512Benchmark

private System.Security.Cryptography.SHA512Managed systemManagedImpl = new System.Security.Cryptography.SHA512Managed();

private global::acryptohashnet.SHA512 acryptohashnetImpl = new global::acryptohashnet.SHA512();
private global::acryptohashnet.Sha2_512 acryptohashnetImpl = new global::acryptohashnet.Sha2_512();

[ParamsSource(nameof(InputSource))]
public byte[] Input { get; set; }
Expand Down
37 changes: 31 additions & 6 deletions src/acryptohashnet.Benchmarks/SHAFamilyBenchmark.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,21 @@ public class SHAFamilyBenchmark

private global::acryptohashnet.SHA1 sha1Impl = new global::acryptohashnet.SHA1();

private global::acryptohashnet.SHA256 sha256Impl = new global::acryptohashnet.SHA256();
private global::acryptohashnet.Sha2_224 sha2_224Impl = new global::acryptohashnet.Sha2_224();

private global::acryptohashnet.SHA384 sha384Impl = new global::acryptohashnet.SHA384();
private global::acryptohashnet.Sha2_256 sha2_256Impl = new global::acryptohashnet.Sha2_256();

private global::acryptohashnet.SHA512 sha512Impl = new global::acryptohashnet.SHA512();
private global::acryptohashnet.Sha2_384 sha2_384Impl = new global::acryptohashnet.Sha2_384();

private global::acryptohashnet.Sha2_512 sha2_512Impl = new global::acryptohashnet.Sha2_512();

private global::acryptohashnet.Sha3_224 sha3_224Impl = new global::acryptohashnet.Sha3_224();

private global::acryptohashnet.Sha3_256 sha3_256Impl = new global::acryptohashnet.Sha3_256();

private global::acryptohashnet.Sha3_384 sha3_384Impl = new global::acryptohashnet.Sha3_384();

private global::acryptohashnet.Sha3_512 sha3_512Impl = new global::acryptohashnet.Sha3_512();

[ParamsSource(nameof(InputSource))]
public byte[] Input { get; set; }
Expand All @@ -30,12 +40,27 @@ public class SHAFamilyBenchmark
public byte[] Sha1Impl() => sha1Impl.ComputeHash(Input);

[Benchmark]
public byte[] Sha256Impl() => sha256Impl.ComputeHash(Input);
public byte[] Sha2_224Impl() => sha2_224Impl.ComputeHash(Input);

[Benchmark]
public byte[] Sha2_256Impl() => sha2_256Impl.ComputeHash(Input);

[Benchmark]
public byte[] Sha2_384Impl() => sha2_384Impl.ComputeHash(Input);

[Benchmark]
public byte[] Sha2_512Impl() => sha2_512Impl.ComputeHash(Input);

[Benchmark]
public byte[] Sha3_224Impl() => sha3_224Impl.ComputeHash(Input);

[Benchmark]
public byte[] Sha3_256Impl() => sha3_256Impl.ComputeHash(Input);

[Benchmark]
public byte[] Sha384Impl() => sha384Impl.ComputeHash(Input);
public byte[] Sha3_384Impl() => sha3_384Impl.ComputeHash(Input);

[Benchmark]
public byte[] Sha512Impl() => sha512Impl.ComputeHash(Input);
public byte[] Sha3_512Impl() => sha3_512Impl.ComputeHash(Input);
}
}
35 changes: 35 additions & 0 deletions src/acryptohashnet.Benchmarks/Sha3_224Benchmark.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using System.Collections.Generic;

using BenchmarkDotNet.Attributes;

namespace acryptohashnet.Benchmarks
{
[MemoryDiagnoser]
public class Sha3_224Benchmark
{
private System.Security.Cryptography.SHA256 cryptoProviderImpl = System.Security.Cryptography.SHA256.Create();

private System.Security.Cryptography.SHA256Managed systemManagedImpl = new System.Security.Cryptography.SHA256Managed();

private global::acryptohashnet.Sha2_224 sha2_224AcryptohashnetImpl = new global::acryptohashnet.Sha2_224();

private global::acryptohashnet.Sha3_224 sha3_224AcryptohashnetImpl = new global::acryptohashnet.Sha3_224();

[ParamsSource(nameof(InputSource))]
public byte[] Input { get; set; }

public IEnumerable<byte[]> InputSource { get; } = TestSuite.BinaryMessages;

[Benchmark]
public byte[] Sha256CryptoProvider() => cryptoProviderImpl.ComputeHash(Input);

[Benchmark]
public byte[] Sha256SystemManaged() => systemManagedImpl.ComputeHash(Input);

[Benchmark]
public byte[] Sha2_224AcryptoHashNet() => sha2_224AcryptohashnetImpl.ComputeHash(Input);

[Benchmark]
public byte[] Sha3_224AcryptoHashNet() => sha3_224AcryptohashnetImpl.ComputeHash(Input);
}
}
35 changes: 35 additions & 0 deletions src/acryptohashnet.Benchmarks/Sha3_256Benchmark.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using System.Collections.Generic;

using BenchmarkDotNet.Attributes;

namespace acryptohashnet.Benchmarks
{
[MemoryDiagnoser]
public class Sha3_256Benchmark
{
private System.Security.Cryptography.SHA256 cryptoProviderImpl = System.Security.Cryptography.SHA256.Create();

private System.Security.Cryptography.SHA256Managed systemManagedImpl = new System.Security.Cryptography.SHA256Managed();

private global::acryptohashnet.Sha2_256 sha2_256AcryptohashnetImpl = new global::acryptohashnet.Sha2_256();

private global::acryptohashnet.Sha3_256 sha3_256AcryptohashnetImpl = new global::acryptohashnet.Sha3_256();

[ParamsSource(nameof(InputSource))]
public byte[] Input { get; set; }

public IEnumerable<byte[]> InputSource { get; } = TestSuite.BinaryMessages;

[Benchmark]
public byte[] Sha2_256CryptoProvider() => cryptoProviderImpl.ComputeHash(Input);

[Benchmark]
public byte[] Sha2_256SystemManaged() => systemManagedImpl.ComputeHash(Input);

[Benchmark]
public byte[] Sha2_256AcryptoHashNet() => sha2_256AcryptohashnetImpl.ComputeHash(Input);

[Benchmark]
public byte[] Sha3_256AcryptoHashNet() => sha3_256AcryptohashnetImpl.ComputeHash(Input);
}
}
Loading

0 comments on commit 5d4d94d

Please sign in to comment.