As a beginner it seems that a scheme derived from a CSPRNG should be as secure as that CSPRNG. Is this a correct assumption? Are there restrictions or known special cases? A rough outline would be:

  1. Generate an IV using a non-deterministic CSPRNG.
  2. Use that IV to seed a deterministic CSPRNG.
  3. XOR each byte of input with a byte from the d-CSPRNG #2.
  4. Concatenate(IV, output of #3)
  5. Use key to seed a deterministic CSPRNG.
  6. XOR each byte of #4 with a byte from the d-CSPRNG #5

In pseudo-code:

# encrypt
iv = randomBytes(IV_SIZE)
c1 = xorUsingPRNG(plaintext, dCSPRNG(seed = iv))
iv_c1 = iv ++ c1
c2 = xorUsingPRNG(c1, dCSPRNG(seed = key))

# decrypt
iv_c1 = xorUsingPRNG(c2, dCSPRNG(seed = key))
iv = iv_c1[0:IV_SIZE]
c1 = iv_c1[IV_SIZE:]
plaintext = xorUSingPRNG(c1, dCSPRNG(seed = iv))

Both the Key and IV are of reasonable size (meaning they are significantly larger than just a few bits).

Are there any known attacks that would work on such a scheme - under assumption that the CSPRNG used is secure.

If the CSPRNG is secure and produces "random" numbers than the output of (any_data XOR random_numbers) should have the same properties in terms of randomness/distribution for as long as those two are independent.

If the CSPRNG is secure then even if one knows or choses the plaintext it shouldn't be feasible to reconstruct the seed used nor should it be possible to extract the keystream because of the randomization in #3.

Obviously the following doesn't work:

  1. Seed a d-CSPRNG with the key
  2. XOR input with output of d-CSPRNG

because this is trivially broken with known/chosen plaintext attacks.


Your scheme can be easily rewritten to adhere to a more common scheme:

  1. generate a random data key (called "the IV" in your scheme)
  2. use the data key to encrypt a message giving the ciphertext (using a stream cipher)
  3. wrap (encrypt) the data key using a cipher parameterized with the master key and store it with the ciphertext.

And the additional step:

  1. encrypt the ciphertext using a cipher parameterized with the master key as well.

Other than #4 this is a very common construction and known to be secure - given that the parameters are indeed configured / generated correctly.

It is also easy to see that the pass with the master key over the ciphertext is spurious if the previous encryption with the data key is secure. That means that a whole pass of a cipher over the ciphertext is performed for no reason, presuming that the stream cipher using the data key is secure.

Relying on deterministic CSPRNG's is often very dangerous from an implementation perspective. CSPRNG's are generally designed to produce random data. They may automatically reseed at times and the implementation may change between versions. A very good example of this is SHA1PRNG used in Java, which is not well described and had all of the described issues (and more) on Android.

Besides that, CSPRNG's are often designed to be very sturdy - a good stream cipher will generally beat the heck out of a CSPRNG in practice when it comes to generating output. The fact that a stream cipher could be seen as a CSPRNG (with a predetermined seed size and without reseeding) doesn't change that.

Likewise XOR with a static key stream is not a brilliant wrapping mechanism. If any data is leaked the data key (your IV) may be at risk. Theoretically it may be perfectly secure given that the message is randomized, but I'd rather use a wrapping mechanism found in FIPS certified hardware (for instance).

Note that the scheme does not protect the integrity of the ciphertext (nor the wrapped key, but the integrity of the wrapped key can be determined by decrypting integrity protected ciphertext). Generally you should try and use authenticated modes of encryption.

  • $\begingroup$ We should stop mixing the terms CSPRNG's and stream cipher (without further qualification). Although a stream cipher can be seen as a CSPRNG with I/O limitations, the reverse is certainly not the case: you cannot just use a CSPRNG or DRBG as a stream cipher without requiring specific limitations on the CSPRNG in theory and the situation is even worse in practice. $\endgroup$ – Maarten Bodewes Sep 27 '18 at 13:39
  • $\begingroup$ Looking at it again I've noticed that if you skip the IV (in the ciphertext) what you're left with is (plaintext XOR rnd1 XOR rnd2) which is essentially (plaintext XOR keystream_i) which means you can extract the key stream and start encrypting your own texts with it without knowing the key and just re-use the encrypted IV. This is not be enough to actually decrypt anything but at least it allows you to encrypt arbitrary plaintexts to valid ciphertexts without knowing the key which pretty much breaks the security of such a scheme. $\endgroup$ – mroman Sep 27 '18 at 14:16
  • $\begingroup$ Unless one counts that as an integrity issue then I guess it doesn't break the scheme itself because the scheme requires external integrity but my intuition tells me that for a secure scheme it at least shouldn't be easy to be able to encrypt arbitrary plaintexts to valid ciphertexts (that decrypt back to the plaintext) without knowing the key. $\endgroup$ – mroman Sep 27 '18 at 14:18
  • $\begingroup$ Generally a cipher should be protected against an adversary that is allowed to encrypt arbitrary plaintext. Allowing an adversary to perform encryption is - strange as it may sound - not the same as breaking the cipher. Besides that, the whole notion of valid ciphertext only comes into play if there is something that verifies the ciphertext or plaintext to be valid. The best way to do that is to use authenticated encryption and verify the authentication tag before decrypting (or using) the plaintext message. Or, if data comm is intended, an entire secure transport protocol. $\endgroup$ – Maarten Bodewes Sep 27 '18 at 14:25
  • $\begingroup$ No, you're still OK I think: the confidentiality of the plaintext is all an encryption scheme / cipher cares about. It does therefore count as an integrity issue. Note that the adversary should still not be able to infer an IV nor enough information to decrypt unknown plaintext. Beware not to try and attack a cipher by inferring a real usage scenario: use the informational theoretic notions of security instead. Protecting against real usage scenarios is performed by a protocol. $\endgroup$ – Maarten Bodewes Sep 27 '18 at 14:57

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.