views:

128

answers:

2

I'm looking at generating pseudo-random one-time-passwords that are time sensitive.

To send a message, the user enters their password which gets hashed together with the message. The resultant hash is sent with the message to the server for verification. The server performs the same hash and compares its value to the one provided.

verificationKey = Hash(message + password);

This works fine to verify the message against the user, but I need to prevent repeated submissions by an attacker. An attacker could just submit the same information again and it would be accepted.

Essentially, I need a loose time-based key to include in the hash. Something that will mean a different hash value for different times, but with enough leeway to account for delays in communication.

verificationKey = Hash(message + password + time);

Obviously if the time value is specific, any mismatch between client and server will cause problems. Even if the time value is rounded to the nearest whole hour, there'll be a point in time (x:30) where the values could be different due to the time taken communicating the message.

Can anyone give any suggestions about how I'd go about getting a loose time value like this?

+1  A: 

One approach would be to hash with the time and then also append the time (after obfuscating it). When you get the message, strip the time, decrypt it, and then do a TimeSpan comparison against the server time. If it is close enough, you can then decrypt the whole message.

Mark Brittingham
Why encrypt the timestamp? Adding it in plain text would probably do or did I miss something?
Daniel Brückner
Well, if you are worried about a hacker and you assume he's got the smarts to figure out it is a timestamp, you've given him some info that he can use against you. It doesn't have to be encrypted, really, just an XOR to obfuscate would remove the obviousness of an HHMM string.
Mark Brittingham
Not a bad solution either :)
Damovisa
Thanks for the upvote. This would work but danbruc's answer is better.
Mark Brittingham
+2  A: 

Just round the timestamp to a few seconds - maybe 2, 5, or 10. The server has to try just twice to verify - once with the current and once with the last timestamp.

Daniel Brückner
+1 I like your suggestion - just try the previous and next. It is pretty simple computationally and easy to implement.
Mark Brittingham
Yeah, that's not a bad solution, although it may have to check three times - once with the current, once with the previous, and once with the next (in case the server times are out).
Damovisa