diff options
author | chai <215380520@qq.com> | 2023-10-12 22:09:49 +0800 |
---|---|---|
committer | chai <215380520@qq.com> | 2023-10-12 22:09:49 +0800 |
commit | 8d2a2cd5de40e2b94ef5007c32832ed9a063dc40 (patch) | |
tree | a63dfbe815855925c9fb8f2804bd6ccfeffbd2eb /Tools/Hazel-Networking/Hazel/Crypto/Sha256Stream.cs | |
parent | dd0c5d50e377d9be1e728463670908a6c9d2c14f (diff) |
+hazel-networking
Diffstat (limited to 'Tools/Hazel-Networking/Hazel/Crypto/Sha256Stream.cs')
-rw-r--r-- | Tools/Hazel-Networking/Hazel/Crypto/Sha256Stream.cs | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/Tools/Hazel-Networking/Hazel/Crypto/Sha256Stream.cs b/Tools/Hazel-Networking/Hazel/Crypto/Sha256Stream.cs new file mode 100644 index 0000000..1903693 --- /dev/null +++ b/Tools/Hazel-Networking/Hazel/Crypto/Sha256Stream.cs @@ -0,0 +1,86 @@ +using System; +using System.Security.Cryptography; + +namespace Hazel.Crypto +{ + /// <summary> + /// Streams data into a SHA256 digest + /// </summary> + public class Sha256Stream : IDisposable + { + /// <summary> + /// Size of the SHA256 digest in bytes + /// </summary> + public const int DigestSize = 32; + + private SHA256 hash = SHA256.Create(); + private bool isHashFinished = false; + + struct EmptyArray + { + public static readonly byte[] Value = new byte[0]; + } + + /// <summary> + /// Create a new instance of a SHA256 stream + /// </summary> + public Sha256Stream() + { + } + + /// <summary> + /// Release resources associated with the stream + /// </summary> + public void Dispose() + { + this.hash?.Dispose(); + this.hash = null; + + GC.SuppressFinalize(this); + } + + /// <summary> + /// Reset the stream to its initial state + /// </summary> + public void Reset() + { + this.hash?.Dispose(); + this.hash = SHA256.Create(); + this.isHashFinished = false; + } + + /// <summary> + /// Add data to the stream + /// </summary> + public void AddData(ByteSpan data) + { + while (data.Length > 0) + { + int offset = this.hash.TransformBlock(data.GetUnderlyingArray(), data.Offset, data.Length, null, 0); + data = data.Slice(offset); + } + } + + /// <summary> + /// Calculate the final hash of the stream data + /// </summary> + /// <param name="output"> + /// Target span to which the hash will be written + /// </param> + public void CopyOrCalculateFinalHash(ByteSpan output) + { + if (output.Length != DigestSize) + { + throw new ArgumentException($"Expected a span of {DigestSize} bytes. Got a span of {output.Length} bytes", nameof(output)); + } + + if (this.isHashFinished == false) + { + this.hash.TransformFinalBlock(EmptyArray.Value, 0, 0); + this.isHashFinished = true; + } + + new ByteSpan(this.hash.Hash).CopyTo(output); + } + } +} |