diff --git a/HashifyNet/Algorithms/XxHash/XxHash3_Implementation.cs b/HashifyNet/Algorithms/XxHash/XxHash3_Implementation.cs index 063a822..3d89cfe 100644 --- a/HashifyNet/Algorithms/XxHash/XxHash3_Implementation.cs +++ b/HashifyNet/Algorithms/XxHash/XxHash3_Implementation.cs @@ -34,6 +34,15 @@ namespace HashifyNet.Algorithms.XxHash3 { + /// + /// Provides an implementation of the XXH3 (XXHash3) hashing algorithm, supporting both 64-bit and 128-bit hash sizes. + /// + /// This class is designed to compute non-cryptographic hash values using the XXH3 algorithm. It + /// supports streaming input data and is configurable via an instance. The hash size is + /// fixed at either 64 or 128 bits, as specified in the configuration. This implementation is optimized for + /// performance and is suitable for scenarios requiring fast, high-quality non-cryptographic hashing, such as checksums + /// or hash-based data structures. + [HashAlgorithmImplementation(typeof(IXxHash3), typeof(XxHash3Config))] internal class XxHash3_Implementation : StreamableHashFunctionBase, IXxHash3 @@ -103,3 +112,4 @@ protected override IHashValue FinalizeHashValueInternal(CancellationToken cancel } } + diff --git a/HashifyNet/Core/DataType/HashValue.cs b/HashifyNet/Core/DataType/HashValue.cs index db3658e..89f8ec9 100644 --- a/HashifyNet/Core/DataType/HashValue.cs +++ b/HashifyNet/Core/DataType/HashValue.cs @@ -38,8 +38,12 @@ namespace HashifyNet.Core.Utilities { /// - /// Implementation of + /// Represents a hash value and its associated bit length. /// + /// This class provides a representation of a hash value as an immutable sequence of bytes, along with + /// its bit length. It includes methods to convert the hash value into various formats, such as Base64, hexadecimal, + /// and numeric types. The hash value is immutable and ensures that the provided bit length matches the actual length + /// of the hash in bits. public class HashValue : IHashValue { @@ -54,12 +58,12 @@ public class HashValue public int BitLength { get; } /// - /// Initializes a new instance of . + /// Creates a new instance of the class that is a representation of a hash value and its bit length computed by a hasher. /// - /// The hash. - /// Length of the hash, in bits. - /// - /// ;bitLength must be greater than or equal to 1. + /// The hash computed by a hasher. + /// The expected bit length of the given . + /// Thrown if the given hash is . + /// Thrown if the parameter is smaller than 1. public HashValue(IEnumerable hash, int bitLength) { if (hash == null) @@ -82,16 +86,6 @@ public HashValue(IEnumerable hash, int bitLength) BitLength = bitLength; } - /// - /// - /// - /// - /// - public string AsBase64String(Base64FormattingOptions formattingOptions = Base64FormattingOptions.None) - { - return Convert.ToBase64String(Hash.ToArray(), formattingOptions); - } - /// /// /// @@ -106,223 +100,216 @@ public BigInteger AsBigInteger() /// /// /// - [CLSCompliant(false)] - public ulong AsUInt64() + public Guid AsGuid() { - byte[] data = AsByteArray(); - if (data.Length > 8) + if (BitLength > 128) { - throw new InvalidOperationException("Hash is too large to fit in a UInt64."); + throw new InvalidOperationException("Hash must be smaller than or equal to 16 bytes."); } - ulong result = 0; - for (int i = 0; i < data.Length; i++) - { - result |= (ulong)data[i] << (8 * i); - } - return result; - } - /// - /// - /// - /// - /// - public Guid AsGuid() - { byte[] data = AsByteArray(); - if (data.Length != 16) + if (data.Length < 16) { - throw new InvalidOperationException("Hash must be exactly 16 bytes to convert to a GUID."); + byte[] paddedData = new byte[16]; + Array.Copy(data, paddedData, data.Length); + data = paddedData; } return new Guid(data); } + #region Non-CLS-Compliant API /// - /// + /// Gets the hash value as an unsigned 64-bit integer. If the bit length is greater than 64, an exception is thrown. + /// This API is not CLS-Compliant. /// - /// - /// - public int AsInt32() + /// An unsigned 64-bit integer value. + [CLSCompliant(false)] + public ulong AsUInt64() { - byte[] data = AsByteArray(); - if (data.Length > 4) - { - throw new InvalidOperationException("Hash is too large to fit in an Int32."); - } - int result = 0; - for (int i = 0; i < data.Length; i++) - { - result |= data[i] << (8 * i); - } - return result; + return (ulong)AsNumber64(); } /// - /// + /// Gets the hash value as an unsigned 32-bit integer. If the bit length is greater than 32, an exception is thrown. + /// This API is not CLS-Compliant. /// - /// - /// + /// An unsigned 32-bit integer. [CLSCompliant(false)] public uint AsUInt32() { - byte[] data = AsByteArray(); - if (data.Length > 4) - { - throw new InvalidOperationException("Hash is too large to fit in a UInt32."); - } - uint result = 0; - for (int i = 0; i < data.Length; i++) - { - result |= (uint)data[i] << (8 * i); - } - return result; + return (uint)AsNumber32(); } + /// + /// Gets the hash value as a unsigned 16-bit integer. If the bit length is greater than 16, an exception is thrown. + /// This API is not CLS-Compliant. + /// + /// An unsigned 16-bit integer. + [CLSCompliant(false)] + public ushort AsUInt16() + { + return (ushort)AsNumber16(); + } + #endregion + /// /// /// /// - /// - public long AsInt64() + public int AsInt32() { - byte[] data = AsByteArray(); - if (data.Length > 8) - { - throw new InvalidOperationException("Hash is too large to fit in an Int64."); - } - long result = 0; - for (int i = 0; i < data.Length; i++) - { - result |= (long)data[i] << (8 * i); - } - return result; + return AsNumber32(); } /// /// /// /// - /// - public short AsInt16() + public long AsInt64() { - byte[] data = AsByteArray(); - if (data.Length > 2) - { - throw new InvalidOperationException("Hash is too large to fit in an Int16."); - } - short result = 0; - for (int i = 0; i < data.Length; i++) - { - result |= (short)(data[i] << (8 * i)); - } - return result; + return AsNumber64(); } /// /// /// /// - /// - [CLSCompliant(false)] - public ushort AsUInt16() + public short AsInt16() { - byte[] data = AsByteArray(); - if (data.Length > 2) - { - throw new InvalidOperationException("Hash is too large to fit in a UInt16."); - } - ushort result = 0; - for (int i = 0; i < data.Length; i++) - { - result |= (ushort)(data[i] << (8 * i)); - } - return result; + return AsNumber16(); } /// /// /// /// - /// public char AsChar() { - byte[] data = AsByteArray(); - if (data.Length > 2) - { - throw new InvalidOperationException("Hash is too large to fit in a Char."); - } - char result = (char)0; - for (int i = 0; i < data.Length; i++) - { - result |= (char)(data[i] << (8 * i)); - } - return result; + return (char)AsNumber16(); } /// /// /// /// - /// public float AsSingle() { - byte[] data = AsByteArray(); - if (data.Length != 4) + int l = AsNumber32(); + unsafe { - throw new InvalidOperationException("Hash must be exactly 4 bytes to convert to a Single."); + return *(float*)&l; } - return BitConverter.ToSingle(data, 0); } /// /// /// /// - /// public double AsDouble() { - byte[] data = AsByteArray(); - if (data.Length != 8) + long l = AsNumber64(); + unsafe { - throw new InvalidOperationException("Hash must be exactly 8 bytes to convert to a Double."); + return *(double*)&l; } - return BitConverter.ToDouble(data, 0); } /// /// /// /// - /// public decimal AsDecimal() { + return AsNumber128_96(); + } + + private decimal AsNumber128_96() + { + if (BitLength < 1) + throw new ArgumentException("Bit Length cannot be smaller than 1."); + + if (BitLength > 96) + throw new NotSupportedException("Bit Length greater than 96 is not supported."); + + byte[] data = AsByteArray(); + + byte[] dataPadded = new byte[12]; + Array.Copy(data, dataPadded, data.Length); + + int lo = (int)Endianness.ToUInt32LittleEndian(dataPadded, 0); + int mid = (int)Endianness.ToUInt32LittleEndian(dataPadded, 4); + int hi = (int)Endianness.ToUInt32LittleEndian(dataPadded, 8); + return new decimal(lo, mid, hi, false, 0); + } + + private long AsNumber64() + { + if (BitLength < 1) + throw new ArgumentException("Bit Length cannot be smaller than 1."); + + if (BitLength > 64) + throw new NotSupportedException("Bit Length greater than 64 is not supported."); + byte[] data = AsByteArray(); - if (data.Length != 16) + + long num = 0; + for (int i = 0; i < data.Length; ++i) + { + num |= (long)data[i] << (8 * i); + } + + return num; + } + + private int AsNumber32() + { + if (BitLength > 32) { - throw new InvalidOperationException("Hash must be exactly 16 bytes to convert to a Decimal."); + throw new NotSupportedException("Bit Length greater than 32 is not supported."); } - int[] bits = new int[4]; - for (int i = 0; i < 4; i++) + + return (int)AsNumber64(); + } + + private short AsNumber16() + { + if (BitLength > 16) { - bits[i] = BitConverter.ToInt32(data, i * 4); + throw new NotSupportedException("Bit Length greater than 16 is not supported."); } - return new decimal(bits); + + return (short)AsNumber64(); } /// /// /// /// - /// public DateTime AsDateTime() { - byte[] data = AsByteArray(); - if (data.Length != 8) + long ticks = AsNumber64(); + if (ticks < 0) + { + ticks &= long.MaxValue; + } + + if (BitLength < 64) { - throw new InvalidOperationException("Hash must be exactly 8 bytes to convert to a DateTime."); + double maxHashValue = (double)(1L << BitLength); + ticks = (long)(ticks / maxHashValue * DateTime.MaxValue.Ticks); } - long ticks = BitConverter.ToInt64(data, 0); + + if (ticks < DateTime.MinValue.Ticks) + { + ticks = DateTime.MinValue.Ticks; + } + + if (ticks > DateTime.MaxValue.Ticks) + { + ticks = DateTime.MaxValue.Ticks; + } + return new DateTime(ticks); } @@ -330,15 +317,30 @@ public DateTime AsDateTime() /// /// /// - /// public DateTimeOffset AsDateTimeOffset() { - byte[] data = AsByteArray(); - if (data.Length != 8) + long ticks = AsNumber64(); + if (ticks < 0) { - throw new InvalidOperationException("Hash must be exactly 8 bytes to convert to a DateTimeOffset."); + ticks &= long.MaxValue; } - long ticks = BitConverter.ToInt64(data, 0); + + if (BitLength < 64) + { + double maxHashValue = (double)(1L << BitLength); + ticks = (long)(ticks / maxHashValue * DateTimeOffset.MaxValue.Ticks); + } + + if (ticks < DateTimeOffset.MinValue.Ticks) + { + ticks = DateTimeOffset.MinValue.Ticks; + } + + if (ticks > DateTimeOffset.MaxValue.Ticks) + { + ticks = DateTimeOffset.MaxValue.Ticks; + } + return new DateTimeOffset(ticks, TimeSpan.Zero); } @@ -346,15 +348,30 @@ public DateTimeOffset AsDateTimeOffset() /// /// /// - /// public TimeSpan AsTimeSpan() { - byte[] data = AsByteArray(); - if (data.Length != 8) + long ticks = AsNumber64(); + if (ticks < 0) { - throw new InvalidOperationException("Hash must be exactly 8 bytes to convert to a TimeSpan."); + ticks &= long.MaxValue; } - long ticks = BitConverter.ToInt64(data, 0); + + if (BitLength < 64) + { + double maxHashValue = (double)(1L << BitLength); + ticks = (long)(ticks / maxHashValue * TimeSpan.MaxValue.Ticks); + } + + if (ticks < TimeSpan.MinValue.Ticks) + { + ticks = TimeSpan.MinValue.Ticks; + } + + if (ticks > TimeSpan.MaxValue.Ticks) + { + ticks = TimeSpan.MaxValue.Ticks; + } + return new TimeSpan(ticks); } @@ -377,14 +394,17 @@ public string AsBinaryString() /// /// /// - public string AsBase85() + public string AsBase85String() { + if (BitLength < 1) + return ""; + const string Base85Alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz!#$%&()*+-;<=>?@^_`{|}~"; byte[] data = AsByteArray(); - if (data.Length == 0) return ""; var builder = new StringBuilder(); int value = 0; int count = 0; + foreach (byte b in data) { value = (value << 8) | b; @@ -410,12 +430,25 @@ public string AsBase85() return builder.ToString(); } + /// + /// + /// + /// + /// + public string AsBase64String(Base64FormattingOptions formattingOptions = Base64FormattingOptions.None) + { + return Convert.ToBase64String(Hash.ToArray(), formattingOptions); + } + /// /// /// /// - public string AsBase58() + public string AsBase58String() { + if (BitLength < 1) + return ""; + const string Base58Alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; byte[] data = AsByteArray(); @@ -442,13 +475,14 @@ public string AsBase58() /// /// /// - public string AsBase32() + public string AsBase32String() { + if (BitLength < 1) + return ""; + const string Base32Alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"; byte[] data = AsByteArray(); - if (data.Length == 0) return ""; - var builder = new StringBuilder(); int bitsRead = 0; int buffer = 0; @@ -481,9 +515,31 @@ public string AsBase32() /// /// /// - /// + /// + public string AsHexString() => AsHexString(false); + + /// /// - /// + /// + /// + /// + public string AsHexString(bool uppercase) + { + var stringBuilder = new StringBuilder(Hash.Length); + var formatString = uppercase ? "X2" : "x2"; + + foreach (var byteValue in Hash) + { + stringBuilder.Append(byteValue.ToString(formatString)); + } + + return stringBuilder.ToString(); + } + + /// + /// + /// + /// public BitArray AsBitArray() { return new BitArray(Hash.ToArray()) @@ -504,37 +560,26 @@ public byte[] AsByteArray() /// /// /// - /// - /// - /// - public string AsHexString() => AsHexString(false); - - /// - /// - /// - /// - /// - /// - /// - public string AsHexString(bool uppercase) + /// + /// + /// + public virtual IHashValue Coerce(int bitLength) { - var stringBuilder = new StringBuilder(Hash.Length); - var formatString = uppercase ? "X2" : "x2"; - - foreach (var byteValue in Hash) + if (bitLength < 1) { - stringBuilder.Append(byteValue.ToString(formatString)); + throw new ArgumentOutOfRangeException(nameof(bitLength), $"{nameof(bitLength)} must be greater than or equal to 1."); } - return stringBuilder.ToString(); + return new HashValue(ArrayHelpers.CoerceToArray(Hash.ToArray(), bitLength), bitLength); } /// - /// Returns a hash code for this instance. + /// Computes a hash code for the current object. /// - /// - /// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. - /// + /// The hash code is calculated based on the values of the property and the + /// elements of the collection. This ensures that objects with the same data produce the same hash + /// code. + /// An integer representing the hash code for the current object. public override int GetHashCode() { unchecked @@ -553,24 +598,24 @@ public override int GetHashCode() } /// - /// Determines whether the specified , is equal to this instance. + /// Determines whether the specified object is equal to the current object. /// - /// The to compare with this instance. - /// - /// true if the specified is equal to this instance; otherwise, false. - /// + /// The object to compare with the current object. This can be . + /// if the specified object is an and is equal to the current object; + /// otherwise, . public override bool Equals(object obj) { return Equals(obj as IHashValue); } /// - /// Indicates whether the current object is equal to another object of the same type. + /// Determines whether the current hash value is equal to the specified instance. /// - /// An object to compare with this object. - /// - /// true if the current object is equal to the parameter; otherwise, false. - /// + /// This method performs a fixed-time comparison of the hash values to mitigate timing attacks. The + /// comparison takes into account the bit length of the hash and the hash data itself. + /// The instance to compare with the current instance. + /// if the current hash value is equal to ; otherwise, . public bool Equals(IHashValue other) { if (other == null || other.BitLength != BitLength) @@ -586,10 +631,19 @@ public bool Equals(IHashValue other) } /// - /// + /// Compares the current hash value to another hash value and determines their relative order. /// - /// - /// + /// The comparison is performed based on the bit length of the hash values and their byte-by-byte + /// content. If the bit lengths differ, the hash with the smaller bit length is considered less. If the bit lengths + /// are equal, the comparison proceeds byte by byte, and any remaining bits in the final byte are compared using a bit + /// mask. + /// The hash value to compare with the current instance. Cannot be . + /// A signed integer that indicates the relative order of the hash values: + /// Less than zero if the current instance is less than . Zero if the current instance is equal to . Greater than zero if the current instance is greater than + /// . + /// Thrown if is . public int CompareTo(IHashValue other) { _ = other ?? throw new ArgumentNullException(nameof(other)); @@ -627,21 +681,5 @@ public int CompareTo(IHashValue other) return 0; } - - /// - /// - /// - /// - /// - public virtual IHashValue Coerce(int bitLength) - { - if (bitLength < 1) - { - throw new ArgumentOutOfRangeException(nameof(bitLength), $"{nameof(bitLength)} must be greater than or equal to 1."); - } - - return new HashValue(ArrayHelpers.CoerceToArray(Hash.ToArray(), bitLength), bitLength); - } } } - diff --git a/HashifyNet/Core/DataType/IHashValue.cs b/HashifyNet/Core/DataType/IHashValue.cs index a0dacba..91cfd56 100644 --- a/HashifyNet/Core/DataType/IHashValue.cs +++ b/HashifyNet/Core/DataType/IHashValue.cs @@ -41,208 +41,150 @@ public interface IHashValue : IEquatable, IComparable { /// - /// Gets the length of the hash value in bits. + /// Gets the length of the hash in bits. /// - /// - /// The length of the hash value in bits. - /// int BitLength { get; } /// - /// Gets resulting byte array. + /// Gets the hash value as an immutable array of bytes. /// - /// - /// The hash value. - /// - /// - /// Implementations should coerce the input hash value to be size in bits. - /// ImmutableArray Hash { get; } /// - /// Converts the hash value to a bit array. + /// Gets the hash value as a . If the bit length is greater than 128, an exception is thrown. /// - /// A instance to represent this hash value. - BitArray AsBitArray(); + /// A Guid representation of the underlying hash value. + /// Thrown if is greater than 128. + Guid AsGuid(); /// - /// Converts the immutable array to a byte array representation. + /// Gets the hash value as a . /// - /// A byte array that represents the current immutable array. - byte[] AsByteArray(); + /// The created instance. + BigInteger AsBigInteger(); /// - /// Converts the hash value to a hexadecimal string. + /// Gets the hash value as a signed 32-bit integer. If the bit length is greater than 32, an exception is thrown. /// - /// A hex string representing this hash value. - string AsHexString(); + /// A signed 32-bit integer. + int AsInt32(); /// - /// Converts the hash value to a hexadecimal string. + /// Gets the hash value as a signed 64-bit integer. If the bit length is greater than 64, an exception is thrown. /// - /// true if the result should use uppercase hex values; otherwise false. - /// A hex string representing this hash value. - string AsHexString(bool uppercase); + /// A signed 64-bit integer. + long AsInt64(); /// - /// Converts the hash value to a the base64 string. + /// Gets the hash value as a signed 16-bit integer. If the bit length is greater than 16, an exception is thrown. /// - /// Formatting options for the generated base64 string. - /// A base64 string representing this hash value. - string AsBase64String(Base64FormattingOptions formattingOptions = Base64FormattingOptions.None); + /// A signed 16-bit integer. + short AsInt16(); /// - /// Converts the hash value to a representation with the specified bit length. + /// Gets the hash value as a Unicode character. If the bit length is greater than 16, an exception is thrown. /// - /// This method allows the caller to adjust the bit length of the hash value to meet specific - /// requirements. The resulting hash value may be truncated or padded, depending on the specified bit - /// length. - /// The desired bit length of the resulting hash value. Must be a positive integer. - /// An instance representing the hash value with the specified bit length. - IHashValue Coerce(int bitLength); + /// A unicode character. + char AsChar(); /// - /// Converts the current hash to its equivalent representation. + /// Gets the hash value as a single-precision floating point number. If the bit length is greater than 32, an exception is thrown. /// - /// This method uses the byte array representation of the hash to construct the . - /// A that represents the current hash. - BigInteger AsBigInteger(); + /// A single-precision floating point number. + float AsSingle(); /// - /// Converts the hash value to a . + /// Gets the hash value as a double-precision floating point number. If the bit length is greater than 64, an exception is thrown. /// - /// The hash must be exactly 16 bytes in length to be converted to a . If the hash - /// length is not 16 bytes, an exception is thrown. - /// A representation of the hash value. - /// Thrown if the hash is not exactly 16 bytes in length. - Guid AsGuid(); + /// A double-precision floating point number. + double AsDouble(); /// - /// Converts the hash value to a 32-bit integer representation. + /// Gets the hash value as a decimal number. If the bit length is greater than 96, an exception is thrown. /// - /// This method interprets the hash value as a little-endian byte array and converts it to an . If the hash value exceeds 4 bytes, an exception is thrown. - /// A 32-bit integer representation of the hash value. - /// Thrown if the hash value exceeds 4 bytes in length. - int AsInt32(); + /// A decimal number. + decimal AsDecimal(); /// - /// Converts the hash value to a 64-bit signed integer. + /// Gets the hash value as a . The hash value is interpreted as the number of ticks (100-nanosecond intervals) since 12:00:00 midnight, January 1, 0001. /// - /// This method interprets the hash value as a little-endian byte array and converts it to a 64-bit - /// signed integer. If the hash value exceeds 8 bytes, an exception is thrown. - /// A 64-bit signed integer representation of the hash value. - /// Thrown if the hash value is larger than 8 bytes. - long AsInt64(); + /// The generated instance. + DateTime AsDateTime(); /// - /// Converts the hash value to a 16-bit signed integer. + /// Gets the hash value as a . The hash value is interpreted as the number of ticks (100-nanosecond intervals) since 12:00:00 midnight, January 1, 0001. /// - /// This method interprets the hash value as a little-endian byte array and converts it to a 16-bit - /// signed integer. If the hash value exceeds 2 bytes in length, an exception is thrown. - /// A 16-bit signed integer representation of the hash value. - /// Thrown if the hash value exceeds 2 bytes in length. - short AsInt16(); + /// The generated instance. + DateTimeOffset AsDateTimeOffset(); /// - /// Converts the hash value to a representation. + /// Gets the hash value as a . The hash value is interpreted as the number of ticks (100-nanosecond intervals). /// - /// This method interprets the hash as a sequence of bytes and converts it into a . - /// If the hash contains more than two bytes, an exception is thrown. - /// A representation of the hash value. - /// Thrown if the hash contains more than two bytes, as it cannot be represented as a . - char AsChar(); + /// The generated instance. + TimeSpan AsTimeSpan(); /// - /// Converts the hash value to a single-precision floating-point number. + /// Gets the hash value as a binary string. Each byte is represented by 8 bits, with leading zeros if necessary. /// - /// The hash must be exactly 4 bytes in length to perform the conversion. If the hash length is not 4 - /// bytes, an is thrown. - /// A representation of the hash value. - /// Thrown if the hash is not exactly 4 bytes in length. - float AsSingle(); + /// The generated binary string. + string AsBinaryString(); /// - /// Converts the hash value to a representation. + /// Gets the hash value as a Base85-encoded string. If the bit length is not a multiple of 8, the last byte is padded with zeros. /// - /// The hash must be exactly 8 bytes in length to perform the conversion. If the hash length is not - /// 8 bytes, an exception is thrown. - /// A representation of the hash value. - /// Thrown if the hash is not exactly 8 bytes in length. - double AsDouble(); + /// The generated base85 string. + string AsBase85String(); /// - /// Converts the hash value to a representation. + /// Gets the hash value as a Base64-encoded string. If the bit length is not a multiple of 8, the last byte is padded with zeros. /// - /// The hash must be exactly 16 bytes in length to be converted to a . If the - /// hash length is not 16 bytes, an exception is thrown. - /// A representation of the hash value. - /// Thrown if the hash is not exactly 16 bytes in length. - decimal AsDecimal(); + /// The formatting options for generating base64 encoded string. + /// The generated base64 encoded string. + string AsBase64String(Base64FormattingOptions formattingOptions = Base64FormattingOptions.None); /// - /// Converts the hash value to a instance. + /// Gets the hash value as a Base58-encoded string. If the bit length is not a multiple of 8, the last byte is padded with zeros. /// - /// The hash must be exactly 8 bytes long to represent a valid . If the hash - /// length is not 8 bytes, an exception is thrown. - /// A instance created from the hash value. - /// Thrown if the hash is not exactly 8 bytes long. - DateTime AsDateTime(); + /// The generated base58 string. + string AsBase58String(); /// - /// Converts the hash value to a . + /// Gets the hash value as a Base32-encoded string. If the bit length is not a multiple of 8, the last byte is padded with zeros. /// - /// The hash must be exactly 8 bytes long to perform the conversion. The resulting is created with a UTC offset of . - /// A representation of the hash value. - /// Thrown if the hash is not exactly 8 bytes long. - DateTimeOffset AsDateTimeOffset(); + /// The generated base32 string. + string AsBase32String(); /// - /// Converts the hash value to a instance. + /// Gets the hash value as a hexadecimal string, using lowercase letters for 'a' to 'f'. /// - /// The hash value must be exactly 8 bytes long to be converted to a . If the - /// hash length is not 8 bytes, an exception is thrown. - /// A representing the hash value. - /// Thrown if the hash value is not exactly 8 bytes long. - TimeSpan AsTimeSpan(); + /// The hexadecimal string. + string AsHexString(); /// - /// Converts the current hash to its binary string representation. + /// Gets the hash value as a hexadecimal string. /// - /// This method generates a binary string where each byte of the hash is represented as an - /// 8-character binary value, padded with leading zeros if necessary. The resulting string concatenates the binary - /// representations of all bytes in sequence. - /// A string containing the binary representation of the hash. - string AsBinaryString(); + /// Indicating to use uppercase letters. + /// The hexadecimal string. + string AsHexString(bool uppercase); /// - /// Encodes the current hash as a Base85-encoded string. + /// Gets the hash value as a . /// - /// This method converts the hash's data, represented as a byte array, into a Base85-encoded string - /// using the ASCII85 encoding scheme. Base85 encoding is a compact representation of binary data that uses a set of - /// 85 printable ASCII characters. - /// A Base85-encoded string representation of the hash's data. Returns an empty string if the byte array is empty. - string AsBase85(); + /// The created instance. + BitArray AsBitArray(); /// - /// Converts the current hash to its Base58-encoded string representation. + /// Gets the hash value as a modifiable byte array. /// - /// This method uses the Base58 encoding scheme, which is commonly used in applications such as - /// cryptocurrency addresses. The encoding excludes visually ambiguous characters such as '0', 'O', 'I', and - /// 'l'. - /// A Base58-encoded string representation of the current hash. - string AsBase58(); + /// The modifiable byte array. + byte[] AsByteArray(); /// - /// Converts the current hash to a Base32-encoded string representation. + /// Converts the current hash value to a new representation with the specified bit length. /// - /// The Base32 encoding uses the alphabet "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567" and appends padding - /// characters ('=') to ensure the output length is a multiple of 8. This method processes the hash's data as a - /// byte array and encodes it into Base32 format. - /// A Base32-encoded string representation of the hash's data. Returns an empty string if the hash's data is - /// empty. - string AsBase32(); + /// The desired bit length of the resulting hash value. Must be greater than or equal to 1. + /// An instance representing the hash value coerced to the specified bit length. + /// Thrown if is less than 1. + IHashValue Coerce(int bitLength); } } diff --git a/HashifyNet/HashifyNet.csproj b/HashifyNet/HashifyNet.csproj index f1e36f7..8dc47a4 100644 --- a/HashifyNet/HashifyNet.csproj +++ b/HashifyNet/HashifyNet.csproj @@ -1,4 +1,4 @@ - + netstandard2.0;net8.0 @@ -67,8 +67,11 @@ - - + + + + + @@ -91,9 +94,8 @@ Deskasoft International HashifyNET Copyright © Deskasoft International - 5.0.0 + 5.0.1 hashing;hash;algorithms;security;crypto;non-crypto;CLS-compliant;VB.NET;F# - LICENSE True False False @@ -106,6 +108,8 @@ logo.png ..\HashifyNET.publickey $(MSBuildProjectName.Replace("Net", "NET")) + $(Company) + MIT diff --git a/README.md b/README.md index 6172176..61aa9b4 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ HashifyNET ================= -HashifyNET is a CLS-Compliant .NET library designed to offer a common interface for a wide range of [cryptographic](https://en.wikipedia.org/wiki/List_of_hash_functions#Keyed_cryptographic_hash_functions) and [non-cryptographic](https://en.wikipedia.org/wiki/List_of_hash_functions#Non-cryptographic_hash_functions) hashing algorithms, while also providing built-in implementations of numerous well-known hash functions. +HashifyNET is a CLS-Compliant, platform-independent .NET library designed to offer a common interface for a wide range of [cryptographic](https://en.wikipedia.org/wiki/List_of_hash_functions#Keyed_cryptographic_hash_functions) and [non-cryptographic](https://en.wikipedia.org/wiki/List_of_hash_functions#Non-cryptographic_hash_functions) hashing algorithms, while also providing built-in implementations of numerous well-known hash functions. All functionality of the library is tested using [xUnit](https://github.com/xunit/xunit). A primary requirement for each release is 100% code coverage by these tests. All code within the library is commented using Visual Studio-compatible XML comments. @@ -238,3 +238,4 @@ License HashifyNET is released under the terms of the MIT license. See [LICENSE](https://github.com/deskasoft/HashifyNET/blob/master/LICENSE) for more information or see http://opensource.org/licenses/MIT. +