I have pushed some code to GitHub to demonstrate the usage of symmetric key encryption in PHP. It is a small key-value storage library and it (optionally) offers ability to encrypt the stored information. I would like to hear your comments about a couple of design decisions I made:

Encryption is done using AES in CBC mode (random IV), with "encrypt-then-MAC" authentication. The information is basically a PHP array, which is serialized and optionally compressed (gzdeflate). This string is then encrypted. I would like to hear some opinions would it be worth it to add an another ("inner") MAC verification, which would take care of checking that the data is valid after uncompression? At first, this sounds like a waste of time, since there is already one MAC check. But on the other hand, this could counter some issues that might arise because of errors in the uncompression layer etc. Any comments about this?

Another thing, crypto experts recommends that when using CTR mode, the nonce should be generated using a unique and increasing "message number". However, in TCrypto there is no way to keep a list of such message numbers, so I have made the decision not to use CTR mode. Do you think it would be safe to use CTR mode by generating the "nonce" randomly (/dev/urandom)? Encryption keys in TCrypto are derived using a constant key, timestamps and the IV (this ensures the encryption keys are unique for each encryption operation).


Any other comments?

Thanks a lot!


  • Welcome to IT Security! A request to help make the site work better: I suggest you split this up -- one question per question, please. Your two questions are unrelated.
    – D.W.
    Jul 10, 2011 at 1:42

2 Answers 2

  1. There is no need for an inner MAC. It is not clear to me what issue you are referring. I am assuming your scheme works like this: compress the data, then apply encrypt-then-MAC to the compressed data. If the MAC digest is valid, then you can be sure that after decrypting you will be processing the same data that the sender sent, so there is no need to have another MAC.

  2. It depends which variant of CTR mode you use, and how the counter is formed. In the simplest form, to encrypt a n-block message under the IV v, we use v, v+1, v+2, .., v+n-1 as the counters, so let me assume that's what you are doing (if not, please specify). Generating a random 128-bit counter using /dev/urandom is fine.

  3. It sounds like you are doing something fancy to generate the key used to encrypt each message. I cannot comment on that, because you haven't provided enough specifics on what you are doing.

If you split this up into multiple questions, and provide more details, we may be able to provide you with better answers.

  • About the inner MAC, I'm dropping the idea to use it. I'll create a new question about this nonce creation issue.
    – timoh
    Jul 10, 2011 at 7:52
  • About the key generation, I set up the key for each encryption using a "constant secret" and some variable data (timestamps and initializing vector). I hash them together and use the result as a key.
    – timoh
    Jul 10, 2011 at 8:30

Compression and encryption are very easy to test and bugs are usually noticed quickly. So there's no need to have another MAC inside. I've never seen such a configuration, and also it would be sufficient to only have a CBC or similar for that case. I suggest to simply put a bunch of automated tests after the build/install routine.

To my knowledge, there is no difference in the recommendation of the IV choice between different cipher modes. Schneier&Ferguson recommend in Practical Cryptography to use a counter as IV. Using a random value is equally secure as long as you have a mostly working PRNG.

If the keys are truly unique for each encryption, it would not matter at all how the IV is chosen. The IV is specifically for doing multiple encryptions with the same key. But you probably cannot rely on that, since the time might be constant or reset for some reason. (Genrally, you should not assume a working clock in your crypto :-)) So you should still use a counting IV or include /dev/random into the current key.

Instead of encrypt-then-mac, you could use a ciphermode with combined encryption and authentication, such as GCM or CCM. If I remember correctly, the advantage of CTR is only that the encryption of a message can be parallelized.

Disclaimer: I'm not a cryptographer.

  • I have the same kind of feelings about the IV construction. Maybe someone with a deeper cryptographic experience can confirm this? GCM, CCM etc. are (at least for now) out of the question, since there is no native support for them in Mcrypt/OpenSSL. Also, the same "nonce construction issue" affects them (the nonce should be constructed for them the same way as it is constructed for CTR).
    – timoh
    Jul 9, 2011 at 20:36
  • 2
    @pepe: "there is no difference in the recommendation of the IV choice between different cipher modes" - not quite. Some modes require the IV to be uniformly random or cryptographically pseudorandom (e.g., CBC mode in its standard form). Some only require it to be unique, but it is OK for it to be predictable (e.g., a variant of CBC mode where the IV is encrypted before use; some variants of CTR mode).
    – D.W.
    Jul 10, 2011 at 1:50
  • 1
    @pepe: "you should still use... /dev/random" - Not good advice. The correct advice is to use /dev/urandom (not /dev/random) -- search on this site to learn more why.
    – D.W.
    Jul 10, 2011 at 1:51
  • @D.W. He already has a secret key, he only wants to derive a key. Apart from the fact that I only meant "use the OS's PRNG", I see little reason to use /dev/urandom for that. In practice, this is a waste of entropy that will slow down other parts of the system. Remember he wants to do that in PHP, and appearantly wants to run it in a web service. You are right about CBC. But using /dev/urandom is, again, not very optimal. Instead I'd rather use a hybrid approach with a "master IV" like in they key derivation. Or rather just use a ciphermode that does not have such flaws.
    – pepe
    Jul 10, 2011 at 12:51
  • @pepe, I wonder if you have it backwards. Applications should almost never be using /dev/random; any place where you are considering /dev/random, it is likely that /dev/urandom is a better choice. Of course, using an application-internal random number generator (seeded by /dev/urandom) may be even better than querying /dev/urandom every time, if your application needs a lot of random numbers.
    – D.W.
    Jul 10, 2011 at 23:55

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .