This is a multi-layer problem, and I want to take you through the whole thing rather than just asking about IVs. Bear with me. Also, all code below is in Common Lisp because that's what I'm using, but if there are any complaints, I'll edit to put up pseudocode.

I'm trying to put together a procedure which will produce hard-to-guess session tokens for use in a server implementation. What I've got so far is

(ql:quickload (list :ironclad :cl-base64))
(setf *random-state* (make-random-state t))

(defmethod sha256 ((message integer))
   :sha256 (ironclad:integer-to-octets message)))

(let ((cipher (ironclad:make-cipher :aes :mode :ecb :key (sha256 (random (expt 2 1024)))))
      (counter (random (expt 2 512))))
  (defun new-session-token ()
    (let ((raw (ironclad:integer-to-octets (incf counter))))
      (ironclad:encrypt-in-place cipher raw)
      (cl-base64:usb8-array-to-base64-string raw :uri t))))

A side question here: what vulnerabilities does this approach have over using AES in counter mode?

The way to use this in counter-mode would be to change the line that defines cipherto :

(let ((cipher (ironclad:make-cipher 
           :aes :key (sha256 (random (expt 2 1024))) 
           :mode :ctr :initialization-vector [16-element vector goes here])

My questions are as follows:

  • What properties does that IV need? The only one I've seen mentioned is uniqueness, which implies that it doesn't have to be secret.
  • Do I need to generate a new one each time I generate a session token?
  • What's a good way of generating one?


As per comment by Stephen Touset, Ironclad supports CSPRNG out of the box (more specifically, it supports Fortuna. For my purposes, the above functions can be replaced with

(let ((prng (ironclad:make-prng :fortuna)))
  (defun new-session-token ()
     (ironclad:random-data 32 prng) :uri t)))

ironclad:make-prng seems inconsistent in runtime; I've timed between 8 and 70 seconds.

  1. Don't use ECB mode. ECB mode is fundamentally unsound except in very specific use-cases.

  2. IVs have different requirements depending on the mode. In CBC mode, the requirement is "unpredictability", which is typically construed to mean "cryptographically random". CTR mode only requires that the IV be a nonce (e.g., is guaranteed to be unique).

  3. A new IV must be used for each and every use of a key for an encryption operation.

  4. IVs do not need to be kept secret. They are considered public information.

  5. SHA-256(rand) is not a cryptographically strong random number generator. Hash functions evenly distribute existing entropy. If your underlying random source is predictable (e.g., has low entropy), hashing it does not improve that. Use a real CSPRNG.

  6. In almost all contexts, you want to use authenticated encryption. GCM mode, EAX mode, and CCM mode satisfy this requirement. Non-authenticated encryption modes can allow attackers to modify ciphertexts in ways that have well-defined effects on the underlying plaintext.

If you want to generate hard-to-guess symmetric keys, just use a cryptographically-strong source of random numbers. If you need to establish these keys over an insecure channel, use something like the Diffie-Hellman key exchange.

You appear to be very new to cryptography. In general, I would strongly caution against working with ciphers at this low a level – the details are extremely important, and they are very difficult for amateurs to get right. The fact that you have already made multiple serious mistakes in fewer than 20 lines of code should give you an indication of just how difficult it actually is.

Unfortunately, I am not personally familiar with any higher-level abstractions for this sort of stuff for Common Lisp.

  • 1
    $\begingroup$ Correct, I'm very new and not hiding the fact. If I knew of an off-the-shelf solution, I'd be using it. I'm not trying to generate "keys" in the cryptographic sense; that was just an unfortunate word choice. My understanding of a session token is that it's basically the output of a CSPRNG; a piece of data that's difficult to guess regardless of how many examples a particular attacker has seen, or how much of your implementation they've read. On that basis, if I had a CSPRNG, I'd just use it directly rather than jumping through these AES hoops. Can you recommend one? $\endgroup$
    – Inaimathi
    Oct 16 '13 at 19:45
  • $\begingroup$ @Inaimathi Reference recommendations are a bit off-topic, but you can find multiple CSPRNGs by using your favorite search engine, or by looking at the well-known standards, including NIST SP 800-90A which describes the CSPRNGs named Hash_DRBG, HMAC_DRBG, and CTR_DRBG. $\endgroup$
    – e-sushi
    Oct 16 '13 at 20:27
  • 1
    $\begingroup$ Ironclad appears to have support for CSPRNGs. $\endgroup$ Oct 16 '13 at 22:00
  • $\begingroup$ What is the purpose and expected use of the "session tokens"? A shared key for encryption? One-time authentication? Do both sides need to generate identical tokens independently from one-another? $\endgroup$ Oct 16 '13 at 22:01
  • $\begingroup$ @StephenTouset - That... solves my problem entirely. I'll edit the snippet into the question; code gets stripped of newlines in comments. $\endgroup$
    – Inaimathi
    Oct 16 '13 at 22:22

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.