I was thinking of doing symmetric encryption using just hashing and simple XOR encryption. It would work as:

  1. Alice and Bob share a symmetric key
  2. Alice manages to send an (authenticated) IV to Bob
  3. Bob and Alice both combine the IV with the symmetric key and use it to seed a PRNG
  4. the output of the PRNG is hashed (SHA256)
  5. whenever a message needs to be sent, the data is XORed with the hashed PRNG output

Are there any serious issues with this approach? If indeed there aren't any, why would one use a SHA256/AES combo with 2 points of failure instead of just relying on the existence of one way functions like SHA256? Why use AES at all?

  • 2
    $\begingroup$ You've invented a slightly odd and complicated stream cipher. It would be simpler to use an actual stream cipher (e.g. ChaCha or AES-CTR ;-) instead of the undefined "PRNG" and remove the hashing. (I'm avoiding subject of authenticated encryption.) $\endgroup$ Commented Jun 16, 2014 at 8:53
  • $\begingroup$ I think you're right, the PRNG is not even necessary, to get the next hash it could simply take the previous hash as input (possibly adding a 'nonce' at every iteration). But why rely on ciphers like AES if all you need is SHA256? $\endgroup$ Commented Jun 16, 2014 at 9:20
  • $\begingroup$ @KrisDeGreve: Dedicated stream ciphers are faster (compare SHA-256 vs. Salsa20 and note that a hash-based stream cipher won't be as fast as the hash alone). All hash functions are also not necessarily good enough for such a construction – see here. $\endgroup$
    – otus
    Commented Jun 16, 2014 at 9:27
  • $\begingroup$ So basically this IS more or less how stream ciphers work, only that their hashing algorithm is less restricted and therefore faster. It still seems to me you're taking twice the risk by betting on 2 separate hashing functions instead of just 1 (esp considering hardware implementations where the performance difference would (neglecting some extra transistors) entirely disappear). $\endgroup$ Commented Jun 16, 2014 at 9:55
  • $\begingroup$ @KrisDeGreve: If you would like to rely on one function for both hashing and encryption, you should start with a function designed for both. For example, Keccak or Skein. If you only need a hash for authentication, authenticated AES modes also qualify. $\endgroup$
    – otus
    Commented Jun 16, 2014 at 13:09

1 Answer 1


It is possible to turn a hash function into a stream cipher; there are several methods for that, and the simplest is to compute $h(K||IV||x)$ for hash function $h$, initialization vector $IV$, and successive values of a counter $x$. This yields an arbitrarily long sequence of pseudo-random blocks (32 bytes per invocation if $h$ is SHA-256). Then XOR that stream with the data to encrypt or decrypt.

We don't usually do that for two main reasons:

  • Security of the scheme is not that easy to characterize. A "secure" hash function (resistant to collisions and preimages) will not necessarily imply a secure stream cipher that way. (Very) roughly speaking, the stream cipher is secure if the hash function behaves like a random oracle.

  • Performance sucks. Hash function are efficient at processing a lot of input data, not at generating a lot of output data.

It is of course quite tempting to have a unique primitive diversified into multiple usages; it would save space in code. However, in embedded systems where ROM size is at a premium (in particular smart cards), CPU power and RAM are even more scarce, and AES performs better than SHA-256 along these metrics.

Sponge hash functions, like the upcoming SHA-3 (Keccak), have an internal structure which is kind-of "reversible", meaning that they are good at input and at output. A Keccak core should allow both secure hashing and efficient pseudo-random generation (i.e. encryption, with a XOR).

Conversely, authenticated encryption modes like GCM use a block cipher for both encryption and integrity, the latter replacing what would have been classically done with a hash function (with HMAC).

  • $\begingroup$ Thanks for your answer and all this information. It's not just tempting because of code-reuse, it seems to make a lot more sense to put your trust in just 1 instead of 2 pieces of software. It's similar to the RSA-AES combo in SSL, it suffices to break one OR the other, weakening reliability for the sole purpose of simplified key distribution. Now I'm also starting to wonder why it isn't common practice to use multiple stream ciphers in sequence to further improve this 'reliability'... $\endgroup$ Commented Jun 16, 2014 at 13:28
  • $\begingroup$ Maybe I should also mention that my application is PC-based so I'm not that worried about performance, I'm also already stuck with SHA256 (or similar) to build hash based signatures. $\endgroup$ Commented Jun 16, 2014 at 13:51
  • 1
    $\begingroup$ Well, don't forget that when you use a hash function as a stream cipher, you are actually trusting two "pieces of software": the hash function itself, and the construction which turns it into a stream cipher. Either may be subject to design and implementation weaknesses. $\endgroup$ Commented Jun 16, 2014 at 14:06
  • $\begingroup$ You're right, I'd have to add trust in this 'random oracle' property of the hash function... I'll look into Keccak, maybe it's exactly what I'm looking for. Thanks again, also to otus and Matt. $\endgroup$ Commented Jun 16, 2014 at 15:08
  • $\begingroup$ It's possibly of note that some stream ciphers and hash functions have very similar cores, such as Blake2 and ChaCha. $\endgroup$ Commented Jul 22, 2014 at 6:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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