4

I have a hash algorithm object (SHA1 in this case) which I feed with data in order to finally get the hashed result upon calling the Result property.

The problem is that once m_HashAlgorithm.Hash property has been called, the object can no longer be used for feeding. If I try to feed it, I get: System.Security.Cryptography.CryptographicUnexpectedOperationException: Hash must be finalized before the hash value is retrieved.

I need to be able to get the an intermediate hash result but keep feeding and get another result later. Is there a way to achieve it?

private readonly HashAlgorithm m_HashAlgorithm;

public DigitalSignatureCreator(HashAlgorithm hashAlgorithm)
{
    m_HashAlgorithm = hashAlgorithm;

    m_MemoryStreamEncrypt = new MemoryStream();
    m_CryptoStreamEncrypt = new CryptoStream(m_MemoryStreamEncrypt, m_HashAlgorithm, CryptoStreamMode.Write);
}

public void Feed(byte[] data, int offset, int count)
{
    m_CryptoStreamEncrypt.Write(data, offset, count);
}

public byte[] Result
{
    get
    {
          return m_HashAlgorithm.Hash;
    }
}
4
  • OT: you probably shouldn't be using SHA1 for anything crypto... Commented Aug 26, 2013 at 15:42
  • I do RSA on the result. But that's irrelevant to the question Commented Aug 26, 2013 at 15:51
  • That's why I said OT. But well spotted... Commented Aug 26, 2013 at 15:52
  • @MitchWheat Depends on the way it is used, but for digital signatures it is not the best. You would still need the private key some control of the signing function to do anything useful when SHA-1 is finally cracked though. Of course, for new protocols, use a form of SHA-256 or SHA-512. Commented Aug 26, 2013 at 17:13

2 Answers 2

4

You need to call HashFinal prior to obtaining the result:

http://msdn.microsoft.com/en-us/library/system.security.cryptography.hashalgorithm.hashfinal.aspx

Based on the way the hash algorithm works (block-cipher), you can't obtain an ACCURATE intermediate result since it won't compute the blocks correctly mid-data. This is because it must pad the final data block to ensure the correct value and remain cryptographically "strong". In other words, since the data blocks depend on prior blocks, you need all data to generate the correct result. .NET tries to help you with this fact by denying access to the cipher results until finalized. You feed the hash all data and then finalize to get the properly computed result.

I'd pose this question to you: why do you need intermediate results? Is there a reason which you can approach or solve from a different angle? Give us the why and we can perhaps help with alternatives.

You should also take care to properly close/dispose your streams after use.

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks but it doesn't answer the question
Based on the way the hash works, you can't obtain an intermediate result since it won't compute the block-cipher portions correctly. You feed it all data and then finalize to get the properly computed result. Why do you need intermediate results?
Thanks. First of all, regarding your explanation of how block cipher works - it would still be possible to get an "intermediate" result if the internal implementation would perform the finalize step but somehow save the previous state for future use and restore it after giving the hash result. This is the kind of solution I was hoping for. Regarding why I need intermediate results: see next comment
The program calculates hash of a stream that arrives from an external location in real time (i.e not of a file). A configuration change in the program can signal that the stream will no longer be arriving for an unknown duration (which is the intermediate point), but this configuration can change again to signal that the same stream is arriving again. At this point I have to continue exactly where I left off.
Regarding the first question - yes, you could definitely keep a byte stream or array of the data sent in and internally calculate final on the current progress. On the second bit, I'm not sure how the hash helps you but clearly that's too in depth for this question... I'd go about doing the final in intermediate steps internally. Should work out well.
2

I guess you cannot do this using the HashAlgorithm. So if you want to do this you may have to rely on a hash implementation you can alter, such as the one in the Bouncy Castle libraries (very permissive libraries, so you can just get the state from the code).

Be warned that attacks on hash extensions are well known, so you may want to take another look at your protocol.

If you want to use standard algorithm implementations I would recommend you to look at hash tree implementations, which are common among file sharing protocols.

2 Comments

Thanks. using an external library is not an option for me but thanks to yours and DavidH answers I understand that the solution can only be to change the design itself, so that intermediate will not be needed at all.
@galbarm That's definitely the best option. As said, if you look at other protocols then hash trees are probably the way to go. Intermediate states are not defined in any standard and may be different for hash implementations.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.