I'm writing a peer to peer network protocol based on private/public key pair trust. To verify and deduplicate messages sent by a host, I use timestamp verification. A host does not trust another host's message if the signed timestamp has a delta (to the current) of greater than 30 seconds or so.
I just ran into the interesting problem that my test server and my second client are about 40 seconds out of sync (fixed by updating ntp).
I was wondering what an acceptable time difference would be, and if there is a better way of preventing replay attacks? Supposedly I could have one client supply a random text to hash and sign, but unfortunately this wont work as in this situation I have to write messages once.
A host does not trust another host's message if the signed timestamp has a delta (to the current) of greater than 30 seconds or so.
Time based is notoriously difficult. I can't tell you the problems I had with mobile devices that would not or could not sync their clock with the network.
Counter based is usually easier and does not DoS itself.
I was wondering what an acceptable time difference would be...
Microsoft's Active Directory uses 5 minutes.
if there is a better way of preventing replay attacks
Counter based with a challenge/response.
I could have one client supply a random text to hash and sign, but unfortunately this wont work as in this situation I have to write messages once...
Perhaps you could use a {time,nonce} pair. If the nonce has not been previously recorded, then act on the message if its within the time delta. Then hold the message (with {time,nonce}) for a windows (5 minutes?).
If you encounter the same nonce again, don't act on it. If you encounter an unseen nonce but its out of the time delta, then don't act on it. Purge your list of nonces on occasion (every 5 minutes?).
I'm writing a peer to peer network protocol based...
If you look around, then you will probably find a protocol in the academic literature.
Related
I'm pondering a client-server auth protocol based on sending and validating a nonce|HMAC(nonce|datetime, shared_secret). I want to allow for small discrepancies between machine times.
I want to introduce a datetime so that nonces can't be reused indefinitely, but I don't want to store a list of used nonces on the server. However, one can't expect machine clocks to be in perfect sync. If I round the time to, say, nearest five minutes, that would cause a false negative if the client's time is 10:59 and the server time is 11:01. So, basically, I'm looking for a way to uniquely identify a time interval that won't be subject to rollover.
Is there a standard solution to this?
So here's what I was hoping I could avoid:
nonce/HMAC combinations that last forever (i. e. replay attacks)
storing nonces on the server between auth requests
more than one roundtrip (e. g. challenge/response)
If there is no solution, that's also a valid answer. I'll go to one of those approaches.
In order to prevent replay attacks, I'm implementing a mechanism where the client has to send to the server a nonce token, which is comprised of an UUID and a timestamp. They are both generated by the client.
However, I'm having concerns regarding the timestamp. I understand that for this to work, the clocks of the server and the clients must be in sync. I do not have control over the clients and, intuitively, it seems unrealistic to expect the server and clients' clocks to be fully in sync. As such, I expect that a client's clock might be a few seconds too early or too late.
Moreover, I expect a few seconds difference between the time the client has sent the nonce token and the time the server has received it. I expect the gap to be more important if the client's connection is poor.
Because of those concerns, I have decided to:
Reject timestamps more than 2 minutes old;
Reject timestamps set up more than 10 seconds into the future.
I would like the input of programmers who've dealt with timestamp validation. Do you see issues with the choices I've made regarding timestamp validation? What are the issues you have encountered?
Thanks!
I have been trying to find out exactly how SSL works, and have found descriptions of the packet sequence that starts the conversation, but not how requests are processed. Here is a link to an example showing the initial handshake:
https://www.eventhelix.com/RealtimeMantra/Networking/SSL.pdf
Once communication is established, both sides are sharing a private session key which is updated every so often. I would like to know details on:
I assume that an attacker cannot just replicate an observed packet and execute it multiple times? This is a so-called replay attack.
How is encryption done using AES-256? If both sides simply applied the algorithm, then a replay attack would work. So I assume there is some kind of chaining so that each packet uses different encryption.
The session key switches every interval (like once every 30 or 60 minutes. How does this exchange work? What messages are exchanged, and what happens if a method is sent before the exchange that arrives after the switch?
The underlying mechanism most recently is TLS 1.2. Is this the same for SSL and SSH, or are the two protocols different?
An explanation is always good but a link to relevant documentation would also be extremely helpful. If these interlocking parts are too much, I can split out into a separate question, but there is a lot of overlapping information in the above sections.
I assume that an attacker cannot just replicate an observed packet and execute it multiple times? This is a so-called replay attack.
Correct. TLS is immune from replay attacks.
How is encryption done using AES-256? If both sides simply applied the algorithm, then a replay attack would work. So I assume there is some kind of chaining so that each packet uses different encryption.
There is chaining, and sequence numbers, and also a MAC for each message.
The session key switches every interval (like once every 30 or 60 minutes. How does this exchange work? What messages are exchanged
Another ClientHello with the same sessionID, and an 'abbreviated handshake' after that, that changes the session key. Details in RFC 2246.
and what happens if a method is sent before the exchange that arrives after the switch?
The switch is by mutual agreement, and any message that arrives before the same sender's ChangeCipherSpec message is decrypted under the old parameters.
The underlying mechanism most recently is TLS 1.2. Is this the same for SSL and SSH, or are the two protocols different?
They are different.
For a personal MMO game project I am implementing a homebrew reliable UDP-based protocol in java. Given my current setup I beleive it would be relatively simple for a snooper to hijack a session, so in order to prevent this I am taking the opportunity to learn a little cryptology. Its very interesting.
I can successfully create a shared secret key between the client and server using a Diffie-Hellman key exchange (a very clever concept), but now I need to use this to guarantee the authenticity of the packets. My preliminary testing so far has shown that the couple of different ciphers Ive tried bloat the amount of data a bit, but I would like to keep things as small and fast as possible.
Given that I am only trying to authenticate the packet and not nessecarily conceal the entire payload, I have the idea that I could put an 8 byte session ID generated from the secret key into the packet header, encrypt the whole packet, and hash it back down to 8 bytes. I take the unencrypted packet and put the 8 byte hash into the place of the session ID and then send it off.
Would this be secure? It feels a little inelegant to encrypt the whole packet only to send it unencrypted - is there a better/faster way to achieve my goal? Please note I would like to do this myself since its good experience so Im not so interested in 3rd party libraries or other protocol options.
If both peers have access to a shared secret (which they should, since you're talking about Diffie-Hellman), you could simply store a hash of the datagram in its header. The receiver checks to see if it matches.
As an added security measure, you could also add a "challenge" field to your datagram and use it somewhere in the hashing process to prevent replays.
So this hash should cover:
The shared secret
A challenge
The contents of the datagram
EDIT
The "challenge" is a strictly incrementing number. You add it to your datagram simply to change the hash every time you send a new message. If someone intercepts a message, it cannot resend it: the receiver makes sure it doesn't accept it.
Currently I am working on an embedded project. The client side is an 8bits MCU and the server side is computer.
As part of goal, I want to minimize the chance people copy our product. During the initialization phase, the server send its serial number to client and client do some simple calculation with its serial number then send result back to server. The server checks the result to a pre-calculated, hardcoded value, if match the client is authentic.
The problem is the calculated serial number that sent back to server is always fixed. Any copycat company can figure it out quite easily with a logic analyzer. I want to make the transmitting serial number seems random bits from time to time but still be able to decrypt back to its original value. A good example using AES encryption (notice every time you press the Encrypt It button a seemingly random text is generated, but as you decrypt it, then it reverts to the original text.)
Due to ROM/RAM and process power limitation in 8bits MCU I can’t fit a complete AES routine in it, so AES is out of a solution. Is there an easy and efficiency algorithm just to randomize the transmission?
Use a key pair. On initialization:
Client tells server "I am online"
Server encrypts a verification message, which only the client will be able to decode
Client sends back the decrypted message
There should be no need for the server's key to be hardcoded - it can be generated based on a timestamp (only an answer within an acceptable range is accepted) or the codes can be generated on an as-needed basis with a timeout to prevent them from being stored for a long term.
Have the server send either a monotonically-increasing counter or a timestamp to the client, alongside the serial number. The client then includes that in the calculation it performs.
Because the server always sends a different request, the response will always be different (of course, if the market is lucrative enough your competitors can always disassemble your MCU code and figure out how to replicate it, but there's really no stopping that).
A different idea might be to require the 8 bit controller to send a CRC of the date, time and serial number to the server. The server can verify it is a unique serial and send a CRC with date, time and authorization code.
You might also look into the rolling code algorythms used for garage doors openers to see if they could be applied to your application.