From 9f556e5cadeeb1562c8b555d9e82f3c1fb9c3f69 Mon Sep 17 00:00:00 2001 From: Matthew Endsley Date: Tue, 13 Apr 2021 17:21:27 -0700 Subject: [PATCH] Stream data blocks directly to SHA256 This removes the need to buffer all data in a MemoryStream to simply hash it when required. --- Hazel/Crypto/Sha256Stream.cs | 36 +++++++++++++++++------------------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/Hazel/Crypto/Sha256Stream.cs b/Hazel/Crypto/Sha256Stream.cs index 8fb53cd..0c23f89 100644 --- a/Hazel/Crypto/Sha256Stream.cs +++ b/Hazel/Crypto/Sha256Stream.cs @@ -1,5 +1,4 @@ using System; -using System.IO; using System.Security.Cryptography; namespace Hazel.Crypto @@ -14,7 +13,12 @@ namespace Hazel.Crypto /// public const int DigestSize = 32; - private MemoryStream innerStream = new MemoryStream(); + private SHA256 hash = SHA256.Create(); + + struct EmptyArray + { + public static readonly byte[] Value = new byte[0]; + } /// /// Create a new instance of a SHA256 stream @@ -28,12 +32,8 @@ namespace Hazel.Crypto /// public void Dispose() { - if (this.innerStream != null) - { - this.Reset(); - this.innerStream.Dispose(); - this.innerStream = null; - } + this.hash?.Dispose(); + this.hash = null; GC.SuppressFinalize(this); } @@ -43,10 +43,8 @@ namespace Hazel.Crypto /// public void Reset() { - ByteSpan buffer = this.innerStream.GetBuffer(); - buffer.SecureClear(); - - this.innerStream.SetLength(0); + this.hash?.Dispose(); + this.hash = SHA256.Create(); } /// @@ -54,7 +52,11 @@ namespace Hazel.Crypto /// public void AddData(ByteSpan data) { - this.innerStream.Write(data.GetUnderlyingArray(), data.Offset, data.Length); + while (data.Length > 0) + { + int offset = this.hash.TransformBlock(data.GetUnderlyingArray(), data.Offset, data.Length, null, 0); + data = data.Slice(offset); + } } /// @@ -70,12 +72,8 @@ namespace Hazel.Crypto throw new ArgumentException($"Expected a span of {DigestSize} bytes. Got a span of {output.Length} bytes", nameof(output)); } - using (SHA256 sha256 = SHA256.Create()) - { - this.innerStream.Position = 0; - ByteSpan digest = sha256.ComputeHash(this.innerStream); - digest.CopyTo(output); - } + this.hash.TransformFinalBlock(EmptyArray.Value, 0, 0); + new ByteSpan(this.hash.Hash).CopyTo(output); } } } -- 2.39.5