For each nth block needed for the length of the plaintext, XOR x with n and hash it with SHA-256 to form b[n].

Let p[n] be the nth 256-bit block in the plaintext and c[n] be the nth block in the ciphertext. Then c[n] := b[n] XOR p[n].

Send the unencrypted nonce along with the ciphertext.

To decrypt c[n], XOR it with b[n] to retrieve p[n].

Is this secure? If so, then why do we need AES-256?

If this is not secure, then is there any mode of operation for which SHA-256 is secure as a block cipher? Specifically, it would need to be used in cipher feedback, output feedback, or any other mode that only uses the cipher in the encryption direction.

For anyone reading this, I believe it would be better to call the 256-bit random value an IV rather than nonce. The value must be random to get the CPA security in this scheme. If a non-random but unique value (nonce) such as a counter was used, the CPA game would be easily defeated (because OP decided to use XOR rather than concatenation on the input to SHA). Just for completeness.
–
PayaMay 19 at 17:46

4 Answers
4

Well, as far as we know, the mode you suggest should be secure. Now, to be honest, AES256 versus your mode isn't quite a fair comparison; your mode gives somewhat less theoretical security; if you encrypt a known $2^n$ block message, the key can be recovered with $2^{256-n}$ effort; however, this observation doesn't really affect the practical security.

However, as for why AES might be preferable:

AES is faster. Performance, of course, varies wildly between platforms and implementations; but taking as an example the CryptoC++ benchmarks, we see AES256 listed as 18.2 cycles per output, while SHA256 takes about 31 cycles per output. Note: SHA256 is listed as 15.8 cycles per byte; however, that is bytes of input; a single SHA256 compression evaluation takes 64 bytes of input, and hence takes 1011 cycles; in your use, you use a single SHA256 compression evaluation to generate 32 bytes of keystream; hence 1011/32 = 31.6 cycles per byte of output.

AES can be used on contexts other than counter mode. That is, AES is invertable (if you know the key); that sometimes comes in handy.

However, the most important point is: AES has been far more extensively analyzed in this context. SHA256 has been analyzed fairly heavily for collision resistance; however, I don't know if anyone has really looked at the question "if we have a large number of hashes of related but unknown images, can we gdeduce what the image is?". With AES, we known that people have been attacking it with this question in mind.

I guess the testing aspect is the most important since no one wants to be solely responsible for the potential failure of a system -- if SHA-256 in CTR fails, its implementer is held accountable; if AES-256 fails, everyone is screwed. Though you say a $2^{256}$-block known message can enable key recovery with an effort of 1... how is that possible?
–
JordanJan 14 '12 at 6:18

@Jordan: Ok, you are correct. With a known $2^n$ message, it takes $2^{256-n}$ test encryptions, and comparing that list of blocks with the $2^n$ known blocks; if $n<128$, this first step dominates (and so the second step can be ignored for estimating speed). If we get to silly values of $n$, this isn't as true.
–
ponchoJan 14 '12 at 15:24

The CTR mode of encryption is defined in general for any cryptographically strong pseudo-random function (PRF). You can build such a PRF from a hash function.

For CTR, you produce a key stream by concatenating:

$$F(k,0) || F(k,1) || ... || F(k,m)$$

where $F$ is your secure PRF, $k$ is your key, and $m$ is the the length of your plaintext divided by the output size of $F$. To rewrite it in your mode's notation:

b[n] = F(k,n)

But $F$ can be any secure PRF. It can be AES but it doesn't have to be, AES is just the popular choice.

Since you want to use SHA-256, you can use a hash-based PRF. You have effectively tried to build one, but a commonly accepted PRF, like HMAC, would be better. If you use HMAC with SHA-256 as your hash function, you have effectively built CTR mode using SHA-256. To do so, your b[n] would change from your function:

b[n] = SHA-256(SHA-256(nonce XOR key) XOR n)

to the HMAC function:

b[n] = SHA-256(key XOR opad || SHA-256(key XOR IPAD || (nonce || n)))

The HMAC scheme will require two hashes every block, whereas your scheme allowed you to only calculate the first hash once, so the HMAC scheme will be roughly twice as slow.

It's worth noting that HMAC is not proven to be a perfect PRF, but it's widely regraded as a PRF. It's definitely a safer PRF choice than a home-made construction. I can't speak as to how secure your scheme is -- it certainly looks plausible, but that doesn't really mean anything -- but it's none better than HMAC.

And since you're so close to HMAC already, if you need to use SHA-256 to build CTR-style encryption, I would recommend you use that (or some other hash-based PRF) instead.

Also, on a side note regarding your closing comment: CTR produces a stream cipher. We commonly use a block cipher to build it, but CTR mode is actually a stream cipher. So we can build a stream cipher from SHA-256, but that's distinct from being able to build a block cipher from it. I think what you meant is that you have a set of schemes you're thinking about (OFB, CFB, CTR, and maybe others) and want to know which of them a hash can be used to fulfill. Given the ability to turn a hash into a PRF, the answer would include CTR.

Using HMAC halves the output speed, and the gain is rather dubious. (Though if you need a fast streamcipher, you wouldn't use SHA-2 in the first place.)
–
CodesInChaos♦Mar 9 '13 at 9:11

2

Actually, one can share part of the HMAC calculation, i.e. the hashing of the first blocks with key XOR opad and key XOR ipad, as they depend on neither nonce nor n. You still need to process two blocks of SHA-256 input per block of output, though, i.e. still half the speed of the original proposal.
–
Paŭlo EbermannMar 10 '13 at 18:11