Provided that I have some data I want to cipher and a password to do it:

  1. I generate a random IV
  2. I define c = sha256(password)
  3. I generate an infinite stream where x0 = sha256(IV xor c) and xi = sha256(xi-1 xor c). This produces blocks of 32 bytes and I yield them byte by byte
  4. output = data xor stream

Would this be secure? In case it's not, how insecure is it?

Note: The NSA isn't going to crack it, I just need it to be secure for a user with average-high cryptographic knowledge.

I know it may look similar to Is it feasible to build a stream cipher from a cryptographic hash function? but it has some differences:

  • I use a random IV instead of starting with hash(data)
  • Im xoring c in each phase of the stream generator, so even knowing xi you can't guess xi+1
  • $\begingroup$ Don’t use sha256(password) as that’s the first part (of many) where your idea goes downhill. SHA-256 is not a Password-Based Key Derivation Function. Using a weak password would end in disaster, no matter if you wrap it in SHA-256 or not. I‘ll leave the rest up to others to explain in actual answers. Btw. there are some related Q&As you might want to check: Building a stream-cipher out of a hash function? and Can I construct a feasible stream cipher out of HMAC and a secure hash algorithm? $\endgroup$ – e-sushi Dec 16 '17 at 19:28
  • $\begingroup$ As Yadkee notes, this is actually a slightly different construction from all three linked—which are all, incidentally, different from the stream cipher I would recommend if you absolutely had to build one out of SHA-256, which is the ‘CTR mode’ $\operatorname{SHA-256}(k \mathbin\Vert \operatorname{le64enc}(0)) \mathbin\Vert \operatorname{SHA-256}(k \mathbin\Vert \operatorname{le64enc}(1)) \mathbin\Vert \cdots$, maybe with a nonce. None of this changes the substance of my answer, of course, which is that to build a stream cipher out of SHA-256 for your application is to meow up the wrong tree. $\endgroup$ – Squeamish Ossifrage Dec 16 '17 at 22:29

The stream cipher part is cryptographically fine given a uniform random key and a unique nonce per message, since SHA-256 shows no evidence of failing preimage resistance, but it's stupidly slow because SHA-256 is designed for the much more expensive collision resistance. There's no reason to prefer it over, for example, XSalsa20.

The password-based key derivation function is problematic if you ever use passwords chosen by a process with entropy much below 128 bits, like most people do, because the cost to the adversary of testing a guess for the password is negligible. You should use a modern password-based key derivation function like scrypt or argon2 to derive the key.

Overall, when you're composing things like this, you should be concerned more with what you're actually trying to protect here. Don't mess with inventing your own stream cipher—that's a solved problem. To do this you need to articulate what you're trying to do in your application with what resources, how the adversary can manipulate those resources, and what you want to make sure the adversary can't do in spite of that. Then you can decide how to use crypto to prevent the adversary's shenanigans—and you'll almost certainly need some authentication in there beyond encryption.


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.