HashLib4CSharp - Comprehensive Hashing Library written in C#

Xor-el

Member
Joined
May 28, 2020
Messages
16
Programming Experience
3-5
HashLib4CSharp is a comprehensive and easy to use hashing library written in C#. it provides flexible interfaces that makes usage a breeze. Hashing can be done in single pass or incremental mode. it also provides methods to clone the internal state of each hash object.
it provides Adapter classes that makes it easily pluggable to methods that accepts the Standard .NET HashAlgorithm, HMAC or DeriveBytes abstract base classes as the need may apply.

All functionality of the library is tested using the nunit framework.

This Library is built against NET Standard 2.1.

* Do note that this is a C# port of my HashLib4Pascal library with various improvements.

GitHub Repository URL
HashLib4CSharp
 
@Xor-el : Why did you define your own exceptions here:
https://github.com/Xor-el/HashLib4CSharp/blob/master/HashLib4CSharp/src/Utils/HashLibException.cs:
/*
(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
{ *                             HashLib4CSharp Library                              * }
{ *                      Copyright (c) 2020 Ugochukwu Mmaduekwe                     * }
{ *                 GitHub Profile URL <https://github.com/Xor-el>                  * }

{ *  Distributed under the MIT software license, see the accompanying LICENSE file  * }
{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }

{ *                              Acknowledgements:                                  * }
{ *                                                                                 * }
{ *   This library was sponsored by Sphere 10 Software (https://www.sphere10.com)   * }
{ *         for the purposes of supporting the XXX (https://YYY) project.           * }
{ *                                                                                 * }
(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
*/

using System;

namespace HashLib4CSharp.Utils
{
    public class HashLibException : Exception
    {
        protected HashLibException(string message) : base(message)
        {
        }
    }

    public sealed class NullReferenceHashLibException : HashLibException
    {
        internal NullReferenceHashLibException(string message) : base(message)
        {
        }
    }

    public sealed class InvalidOperationHashLibException : HashLibException
    {
        internal InvalidOperationHashLibException(string message) : base(message)
        {
        }
    }

    public sealed class IndexOutOfRangeHashLibException : HashLibException
    {
        internal IndexOutOfRangeHashLibException(string message) : base(message)
        {
        }
    }

    public class ArgumentHashLibException : HashLibException
    {
        internal ArgumentHashLibException(string message) : base(message)
        {
        }
    }

    public sealed class ArgumentInvalidHashLibException : ArgumentHashLibException
    {
        internal ArgumentInvalidHashLibException(string message) : base(message)
        {
        }
    }

    public sealed class ArgumentNullHashLibException : ArgumentHashLibException
    {
        public ArgumentNullHashLibException(string message) : base(message)
        {
        }
    }

    public sealed class ArgumentOutOfRangeHashLibException : ArgumentHashLibException
    {
        internal ArgumentOutOfRangeHashLibException(string message) : base(message)
        {
        }
    }

    public sealed class NotImplementedHashLibException : HashLibException
    {
        internal NotImplementedHashLibException(string message) : base(message)
        {
        }
    }

    public class IOHashLibException : HashLibException
    {
        internal IOHashLibException(string message) : base(message)
        {
        }
    }

    public sealed class FileNotFoundHashLibException : IOHashLibException
    {
        internal FileNotFoundHashLibException(string message) : base(message)
        {
        }
    }
}

when the .NET Framework documentation says:
Choosing standard exceptions
When you have to throw an exception, you can often use an existing exception type in the .NET Framework instead of implementing a custom exception. You should use a standard exception type under these two conditions:
  • You are throwing an exception that is caused by a usage error (that is, by an error in program logic made by the developer who is calling your method). ...
  • You are handling an error that can be communicated to the caller with an existing .NET Framework exception. You should throw the most derived exception possible. ...
and
Implementing custom exceptions
In the following cases, using an existing .NET Framework exception to handle an error condition is not adequate:

  • When the exception reflects a unique program error that cannot be mapped to an existing .NET Framework exception.
  • When the exception requires handling that is different from the handling that is appropriate for an existing .NET Framework exception, or the exception must be disambiguated from a similar exception. For example, if you throw an ArgumentOutOfRangeException exception when parsing the numeric representation of a string that is out of range of the target integral type, you would not want to use the same exception for an error that results from the caller not supplying the appropriate constrained values when calling the method.
 
Also there is a lot of use of unsafe pointers in the code. I've only done a brief scan so far, but I believe a majority of it can be replaced with using Span<byte> so that you don't have to compile with the unsafe flag on.
 
Also there is a lot of use of unsafe pointers in the code. I've only done a brief scan so far, but I believe a majority of it can be replaced with using Span<byte> so that you don't have to compile with the unsafe flag on.

Any suggestions of an example where using span<byte> would be a better fit instead of unsafe code?
 
@Xor-el : Why did you define your own exceptions here:
https://github.com/Xor-el/HashLib4CSharp/blob/master/HashLib4CSharp/src/Utils/HashLibException.cs:
/*
(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
{ *                             HashLib4CSharp Library                              * }
{ *                      Copyright (c) 2020 Ugochukwu Mmaduekwe                     * }
{ *                 GitHub Profile URL <https://github.com/Xor-el>                  * }

{ *  Distributed under the MIT software license, see the accompanying LICENSE file  * }
{ *          or visit http://www.opensource.org/licenses/mit-license.php.           * }

{ *                              Acknowledgements:                                  * }
{ *                                                                                 * }
{ *   This library was sponsored by Sphere 10 Software (https://www.sphere10.com)   * }
{ *         for the purposes of supporting the XXX (https://YYY) project.           * }
{ *                                                                                 * }
(* &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& *)
*/

using System;

namespace HashLib4CSharp.Utils
{
    public class HashLibException : Exception
    {
        protected HashLibException(string message) : base(message)
        {
        }
    }

    public sealed class NullReferenceHashLibException : HashLibException
    {
        internal NullReferenceHashLibException(string message) : base(message)
        {
        }
    }

    public sealed class InvalidOperationHashLibException : HashLibException
    {
        internal InvalidOperationHashLibException(string message) : base(message)
        {
        }
    }

    public sealed class IndexOutOfRangeHashLibException : HashLibException
    {
        internal IndexOutOfRangeHashLibException(string message) : base(message)
        {
        }
    }

    public class ArgumentHashLibException : HashLibException
    {
        internal ArgumentHashLibException(string message) : base(message)
        {
        }
    }

    public sealed class ArgumentInvalidHashLibException : ArgumentHashLibException
    {
        internal ArgumentInvalidHashLibException(string message) : base(message)
        {
        }
    }

    public sealed class ArgumentNullHashLibException : ArgumentHashLibException
    {
        public ArgumentNullHashLibException(string message) : base(message)
        {
        }
    }

    public sealed class ArgumentOutOfRangeHashLibException : ArgumentHashLibException
    {
        internal ArgumentOutOfRangeHashLibException(string message) : base(message)
        {
        }
    }

    public sealed class NotImplementedHashLibException : HashLibException
    {
        internal NotImplementedHashLibException(string message) : base(message)
        {
        }
    }

    public class IOHashLibException : HashLibException
    {
        internal IOHashLibException(string message) : base(message)
        {
        }
    }

    public sealed class FileNotFoundHashLibException : IOHashLibException
    {
        internal FileNotFoundHashLibException(string message) : base(message)
        {
        }
    }
}

when the .NET Framework documentation says:

and
Thanks a lot for this suggestion, will implement it as indicated.
 
@Skydiver, for cases like this

"you would not want to use the same exception for an error that results from the caller not supplying the appropriate constrained values when calling the method"

What type of inbuilt exception do you recommend? Is "ArgumentException" okay for such scenario?
 
I tend to use ArgumentException and put a more detailed message about why an argument was invalid. It only in the cases when I need to let the caller be able to distinguish between multiple different kinds of ArgumentException's that may result from a single line of code that I create a custom exception. That custom exception would still derive from the most specific built in exception that I can find, but I would create a subclass that even further distinguishes it. That way the caller can choose to catch a specific exception, or they can choose to catch a more generic exception.
 
Can you please suggest an appropriate comment header style.
I would suggest just to keep it simple:
C#:
/*
HashLib4CSharp Library
Copyright (c) 2020 Ugochukwu Mmaduekwe
GitHub Profile URL <https://github.com/Xor-el>

Distributed under the MIT software license, see the accompanying LICENSE file
or visit http://www.opensource.org/licenses/mit-license.php.

Acknowledgements:
This library was sponsored by Sphere 10 Software (https://www.sphere10.com)
for the purposes of supporting the XXX (https://YYY) project.
*/
 
I saw that you picked up the 2 pull requests I sent last night regarding the performance test UI. I'll probably get around to doing a pull from your repo soon. I've been busy debugging the CRC32 code because my Span implementation was failing the unit tests. Just figured it about 5 minutes ago. I'll post here soon with a comparison of the unsafe vs. span code.
 
I saw that you picked up the 2 pull requests I sent last night regarding the performance test UI. I'll probably get around to doing a pull from your repo soon. I've been busy debugging the CRC32 code because my Span implementation was failing the unit tests. Just figured it about 5 minutes ago. I'll post here soon with a comparison of the unsafe vs. span code.
Yes I did, thanks for those and also thanks a lot for your time.
 
Back
Top Bottom