Say, you're user "bob". You log in with your password on 2014-07-30H12:00:00 and the server, using your scheme, sets your cookie token to:
enc("bob", K)+enc("2014-07-30H12:00:00", K)
However, bob is malicious. While his boss Alice is away from her desk, he checks her browser cookies and finds out her token:
enc("alice", K)+enc("2014-07-30H13:00:00", K)
Bob doesn't need to know the secret key K on the server, since the value of
enc("alice", K) never changes, so all he needs to do in order to spoof being user "alice" at any time in the future is to change his own cookie to replace the output of
enc("bob", K) with the output of
The scheme with the hmac suggested above is not vulnerable to this attack. The server's returned token is something like this:
Bob can try to change "bob" to "alice", but when the server performs the validation calculation, the calculated sha256 hash won't match, and it will be obvious that either the username or timestamp have been tampered with. Bob cannot possibly calculate the hash, since he doesn't know the secret key used by the server.
The validation operation of
hmac() are extremely fast and take microseconds to perform. They will probably be faster than decrypting the tokens. Obviously, you'd be sending the token over a safe channel, such as over https using a secure cookie, so there is little need to additionally encrypt the username and timestamp in addition to the hmac.
Edited to add:
Even if you use the following instead:
this is still not good enough. Getting encryption just right is extremely difficult and the chances are there will be weaknesses in your implementation (all tokens issued to "alice" will start the same way unless you do the right thing with randomness and initialization). Since the attacker will know both the plaintext and cryptotext, there is a number of attacks they can try to figure out what the value of K is, unless you use the right algorithm with correct initialization parameters.
Furthermore, all good crypto always incorporates hmac for integrity checking anyway, so by attempting to simplify the process you'll end up either weakening it, or making it more complicated and computationally intensive.
Just stick to the
username+timestamp+hmac(sha256, username+timestamp, K) recommendation and transfer it to the client over a secure channel. It's a scheme that known to work well.