I have been writing a class that encrypts and decrypts with block ciphers. I want to use Counter Mode(CTR/CM). We know that Counter Mode generates a keystream basing on counters, then XOR the keystream with plaintext to produce ciphertext. So, one can decrypt as long as he can reproduce the keystream, that is, to reproduce the counter and get the right key.

I observed that the decrypt method of a cipher is not necessary in CTR mode, since to reproduce the keystream we only need to encrypt counter blocks again.

So why can't I replace the ordinary cipher with a hash function(thus make key part of the counter) or a HMAC function(which accepts a key)? Are hash functions not-so-pseudorandom when compared to ciphers in keystream generation, or there's more reason?

p.s.: This question also works with OFB mode -- hashing an IV with or without a key again and again also produce something looks like a keystream.

p.s.2: an example:

1)Let's construct a counter of 16 bytes:


Here we get 3 blocks.

2)Then use HMAC of MD5 to generate keystream:

key = 'This is a key.'
stream[0] = HMAC('This is a key.','aPADDING00000000').hexdigest()
stream[1] = HMAC('This is a key.','aPADDING00000001').hexdigest()
stream[2] = HMAC('This is a key.','aPADDING00000002').hexdigest()

# now stream is:
# ['73f2e665c30aaec5bbead51166aaa85f',
#  '91392d0755638fbce5c689f96b02494f',
#  '1d18a81751179858d151dd86179385f9']

stream_str = "".join(stream).decode('hex') # stream_str = '73f2 ... 85f9'.decode('hex')

3) Now stream_str looks very much like a keystream. To encrypt:

plaintext = 'This is a plaintext that has length of 48 bytes.'
ciphertext = stream_xor(plaintext,stream_str) # stream_xor XORs the two inputs bit by bit.

or, to decrypt:

decrypted = stream_xor(ciphertext,stream_str) # ciphertext produced before. 
  • No offence intended, but I have no idea what you are talking about. I think you got some of the basic concepts and terminology wrong... Modes of operation like CTR, OFB, CBC, etc. are used with block ciphers, but you are talkign about stream ciphers. Also hashes != encryption and vice versa. – Tie-fighter Jul 17 '12 at 15:22
  • I don't think I have made concepts wrong. Block ciphers can be used as stream ciphers when combined with certain modes of operation, e.g. CTR, OFB. Please refer to link. – Lucifer Orichalcum Jul 17 '12 at 15:25
  • Block cipher mess up the input block with a key, so can a hash function. Another fact: CTR is plaintext independent, so as long as we can generate and reproduce a keystream, we can encrypt and decrypt, with no relation to a cipher's decrypt method. This is odd to me. – Lucifer Orichalcum Jul 17 '12 at 15:33
  • 3
    Maybe this should be migrated to cryptography... – Tie-fighter Jul 18 '12 at 0:34
  • 1
    @Tie-fighter I have found an interesting encryption system: Snuffle. link. That's just my idea. – Lucifer Orichalcum Jul 26 '12 at 1:22

Angelo Rosiello and Roberto Carrozzo proposed this exact scheme (hash based OFB) in a 2005 paper called "ARC: a Synchronous stream cipher from hash functions" and showed that it is secure as long as a strong cryptographic hash function is used and the hash function is pseudo-random.

But the question is: why use a hash function instead of a block cipher? Block ciphers such as AES have proven more resilient over time to attack compared to hash functions. AES is generally faster than a SHA256 HMAC. What advantage is there to using HMAC for this?

  • The cited paper by Rosiello et al. presents a similar OFB-based scheme, but it is not exactly the same as substituting HMAC for the cipher in OFB. – B-Con Aug 14 '12 at 21:18

So why can't I replace the ordinary cipher with a hash function(thus make key part of the counter) or a HMAC function(which accepts a key)? Are hash functions not-so-pseudorandom when compared to ciphers in keystream generation, or there's more reason?

In theory, CTR can work with any secure PRF. With a 16-byte block size, a block cipher (modeled as a PRP) acts enough like a PRF that it can be used as one, but any PRF will work. HMAC is a hash-based PRF, so it works in CTR mode.

(I think that OFB has the same property of working with any secure PRF. It would certainly seem to make sense, but I don't see any explicit references confirming it.)


You can, however why would you want to? The point of block and stream ciphers is to increase the strength of encryption protocols when data is supposed to be decrypted. If you use a hash method then you can't decrypt the data as hashes are one way.

If you are trying to create key data rather than encrypt data then yes you could do it this way, however you're re-inventing the wheel.

  • 2
    I have included an example in my question. Hope this will make it clear. In CTR mode, I do not need to decrypt anything. To decrypt, one only need to regenerate the correct keystream(then bitwise XOR with the ciphertext). – Lucifer Orichalcum Jul 18 '12 at 0:00

See NIST SP800-90A which describes some pseudo-random number generators, in particular Hash_DRBG and HMAC_DRBG, which are hash-based in a way similar to what you suggest. The hard part is to design the system such that security can somehow be proven (i.e. reduced to a "reasonable" assumption on the hash function itself).

A good reason to use them is in embedded systems with limited code size, and which already have an implementation of a hash function for other usages.

A good reason not to use them is that they tend to be quite slower than block ciphers and, even more so, specialized stream ciphers.


You can use a hash function or HMAC in a CTR mode construction to create a secure stream cipher. This doesn't work with hash functions that only try to provide collision and pre-image resistance, but requires some pseudo randomness properties. Luckily most modern hash functions have this property.

As a practical example you could look at the Salsa20 stream-cipher, which is essentially a hash function in CTR mode.

With OFB you need to be careful. You need to mix in the key on each step, and not just on the first. In particular $ C_i = Hash(C_{i-1}) $ is trivially vulnerable to a known plaintext attack. If you learn part of the keystream, you can predict the whole keystream after that point.

There are a few related questions on crypto.SE:

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.