diff --git a/SabreTools.Hashing/MessageDigest/MD2.cs b/SabreTools.Hashing/MessageDigest/MD2.cs
index 1714526..5884ac7 100644
--- a/SabreTools.Hashing/MessageDigest/MD2.cs
+++ b/SabreTools.Hashing/MessageDigest/MD2.cs
@@ -4,7 +4,6 @@ using static SabreTools.Hashing.MessageDigest.Constants;
namespace SabreTools.Hashing.MessageDigest
{
///
- /// Uses the inefficient reference implementation for now
public class MD2 : MessageDigestBase
{
///
@@ -44,11 +43,70 @@ namespace SabreTools.Hashing.MessageDigest
///
public override void TransformBlock(byte[] data, int offset, int length)
{
- // Loop and process all bytes sequentially
- while (length > 0)
+ // If there is buffer to fill and it will meet the limit
+ if (_byteCount > 0 && _byteCount + length >= 16)
{
- Update(data[offset++]);
- length--;
+ // Fill the buffer from the input
+ for (int i = 0; i < 16 - _byteCount; i++)
+ {
+ // Add new character to buffer
+ _digest[16 + _byteCount + i] = data[offset + i];
+ _digest[32 + _byteCount + i] = (byte)(data[offset + i] ^ _digest[_byteCount + i]);
+
+ // Update checksum register C and value L
+ _lastByte = _checksum[_byteCount] ^= MD2SBox[0xff & (data[offset + i] ^ _lastByte)];
+ }
+
+ // Set the new values
+ offset += 16 - _byteCount;
+ length -= 16 - _byteCount;
+ _byteCount = 0;
+
+ // Run the update
+ Update();
+ }
+
+ /// Process any standalone blocks
+ while (length >= 16)
+ {
+ // Fill the buffer from the input
+ for (int i = 0; i < 16; i++)
+ {
+ // Add new character to buffer
+ _digest[16 + i] = data[offset + i];
+ _digest[32 + i] = (byte)(data[offset + i] ^ _digest[i]);
+
+ // Update checksum register C and value L
+ _lastByte = _checksum[i] ^= MD2SBox[0xff & (data[offset + i] ^ _lastByte)];
+ }
+
+ // Set the new values
+ offset += 16;
+ length -= 16;
+ _byteCount = 0;
+
+ // Run the update
+ Update();
+ }
+
+ // Save the remainder in the buffer
+ if (length > 0)
+ {
+ // Fill the buffer from the input
+ for (int i = 0; i < length; i++)
+ {
+ // Add new character to buffer
+ _digest[16 + _byteCount] = data[offset];
+ _digest[32 + _byteCount] = (byte)(data[offset] ^ _digest[i]);
+
+ // Update checksum register C and value L
+ _lastByte = _checksum[_byteCount] ^= MD2SBox[0xff & (data[offset] ^ _lastByte)];
+
+ // Set the new values
+ offset++;
+ length--;
+ _byteCount = (byte)((_byteCount + 1) & 15);
+ }
}
}
@@ -57,16 +115,12 @@ namespace SabreTools.Hashing.MessageDigest
{
// Determine the pad length
byte padLength = (byte)(16 - _byteCount);
- for (int i = 0; i < padLength; i++)
- {
- Update(padLength);
- }
- // Append the checksum
- for (int i = 0; i < 16; i++)
- {
- Update(_checksum[i]);
- }
+ // Pad the block
+ byte[] padding = new byte[padLength];
+ Array.Fill(padding, padLength);
+ TransformBlock(padding, 0, padLength);
+ TransformBlock(_checksum, 0, _checksum.Length);
}
///
@@ -86,36 +140,18 @@ namespace SabreTools.Hashing.MessageDigest
/// digest is being computed. This routine will be called for each
/// message byte in turn.
///
- private void Update(byte c)
+ /// The following is a more efficient version of the loop
+ private void Update()
{
- // TODO: The part from here until "Transform D if i = 0"
- // can be moved into the main TransformBlock. All it's doing
- // is ensuring that 16 bytes exist before it starts processing
-
- // Add new character to buffer
- _digest[16 + _byteCount] = c;
- _digest[32 + _byteCount] = (byte)(c ^ _digest[_byteCount]);
-
- // Update checksum register C and value L
- _lastByte = _checksum[_byteCount] ^= MD2SBox[0xff & (c ^ _lastByte)];
-
- // Increment i by one modulo 16
- _byteCount = (byte)((_byteCount + 1) & 15);
-
- // Transform D if i = 0
- if (_byteCount == 0)
+ byte t = 0;
+ for (byte j = 0; j < 18; j++)
{
- byte t = 0;
- for (byte j = 0; j < 18; j++)
+ for (byte i = 0; i < 48; i++)
{
- // The following is a more efficient version of the loop
- for (byte i = 0; i < 48; i++)
- {
- t = _digest[i] = (byte)(_digest[i] ^ MD2SBox[t]);
- }
-
- t += j;
+ t = _digest[i] = (byte)(_digest[i] ^ MD2SBox[t]);
}
+
+ t += j;
}
}
}