Take the 2-minute tour ×
Cryptography Stack Exchange is a question and answer site for software developers, mathematicians and others interested in cryptography. It's 100% free, no registration required.

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))
  (ironclad:digest-sequence
   :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?

EDIT:

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 ()
    (cl-base64:usb8-array-to-base64-string
     (ironclad:random-data 32 prng) :uri t)))

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

share|improve this question
    
Might be interesting for you to read too: "Why use an Initialization Vector (IV)?" and "Why, or when, to use an Initialization Vector?" –  e-sushi Oct 16 '13 at 20:21
add comment

1 Answer 1

up vote 3 down vote accepted
  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.

share|improve this answer
1  
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? –  Inaimathi Oct 16 '13 at 19:45
    
@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. –  e-sushi Oct 16 '13 at 20:27
1  
Ironclad appears to have support for CSPRNGs. –  Stephen Touset Oct 16 '13 at 22:00
    
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? –  Stephen Touset Oct 16 '13 at 22:01
    
@StephenTouset - That... solves my problem entirely. I'll edit the snippet into the question; code gets stripped of newlines in comments. –  Inaimathi Oct 16 '13 at 22:22
show 2 more comments

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.