How can a low-power microcontroller authenticate itself against a server? - authentication

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.

Related

How to hide / encrypt POST data sent from FLASH to PHP from Tamper Data

Tamper data
There is terrible thing called Tamper Data. It receives all POST'ing data from FLASH to PHP and give ability for user to change values.
Imagine that in flash game (written in ActionScript 3) are score points and time. After match completed score and time variables are sending to PHP and inserting to database.
But user can easy change values with Tamper Data after match completed. So changed values will be inserted to database.
My idea seems that won't work
I had idea to update data in database on every change? I mean If player get +10 score points I need instant to write It to database. But how about time? I need update my table in database every milisecond? Is that protection solution at all? If user can change POST data he can change It everytime also last time when game completed.
So how to avoid 3rd party software like Tamper Data?
Tokens. I've read article about Tokens, there is talking about how to create random string as token and compare It with database, but It's not detailed and I don't have idea how to realise It. Is that good idea? If yes, maybe someone how to realise It practically?
According to me is better way to send both parameter and value in encrypted format like score=12 send like c2NvcmU9MTI= which is base64
function encrypt($str)
{
$s = strtr(base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, md5(SALTKEY), serialize($str), MCRYPT_MODE_CBC, md5(md5(SALTKEY)))), '+/=', '-_,');
return $s;
}
function decrypt($str)
{
$s = unserialize(rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, md5(SALTKEY), base64_decode(strtr($str, '-_,', '+/=')), MCRYPT_MODE_CBC, md5(md5(SALTKEY))), "\0"));
return $s;
}
In general, there is no way to protect the content generated in Flash and sent to server.
Even if you encrypt the data with a secret key, both the key and the encryption algorithm are contained in the swf file and can be decompiled. It is a bit more harder than simply faking the data so it is kind of usable solution but it will not always help.
To have full security, you need to run all game simulation on the server. For example, if player jumped and catched a coin, Flash does not send "score +10" to the server. Instead, it sends player coordinates and speed, and server does the check: where is the coin, where is the player, what is player's speed and can the player get the coin or not.
If you cannot run the full simulation on the server, you can do a partial check by sending data to server at some intervals.
First, never send a "final" score or any other score. It is very easy to fake. Instead, send an event every time the player does something that changes his score.
For example, every time player catches a coin, you send this event to the server. You may not track player coordinates or coin coordinates, but you know that the level contains only 10 coins. So player cannot catch more than 10 coins anyway. Also, player can't catch coins too fast because you know the minimum distance between coins and the maximum player speed.
You should not write the data to database each time you receive it. Instead you need to keep each player's data in memory and change it there. You can use a noSQL database for that, for example Redis.
First, cheaters will always cheat. There's really no easy solution (or difficult one) to completely prevent it. There are lots of articles on the great lengths developers have gone to discourage cheating, yet it is still rampant in nearly every game with any popularity.
That said, here are a few suggestions to hopefully discourage cheating:
Encrypt your data. This is not unbeatable, but will discourage many lazy hackers since they can't just tamper with plain http traffic, they first have to find your encryption keys. Check out as3corelib for AS3 encryption.
Obfuscate your SWFs. There are a few tools out there to do this for you. Again, this isn't unbeatable, but it is an easy way to make it harder for cheaters to find your encryption keys.
Move all your timing logic to the server. Instead of your client telling the server about time, tell the server about actions like "GAME_STARTED" and "SCORED_POINTS". The server then tracks the user's time and calculates the final score. The important thing here is that the client does not tell the server anything related to time, but merely the action taken and the server uses its own time.
If you can establish any rules about maximum possible performance (for example 10 points per second) you can detect some types of cheating on the server. For example, if you receive SCORED_POINTS=100 but the maximum is 10, you have a cheater. Or, if you receive SCORED_POINTS=10, then SCORE_POINTS=10 a few milliseconds later, and again a few milliseconds later, you probably have a cheater. Be careful with this, and know that it's a back and forth battle. Cheaters will always come up with clever ways to get around your detection logic, and you don't want your detection logic to be so strict that you accidentally reject an honest player (perhaps a really skilled player who is out-performing what you initially thought possible).
When you detect a cheater, "honey pot" them. Don't tell them they are cheating, as this will only encourage them to find ways to avoid detection.

Cryptography: Verifying Signed Timestamps

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.

Securing a UDP connection

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.

How does browser generate symmetric key during SSL handshake

I have a small confusion on SSL handshake between browser and server in a typical https web scenario:
What I have understood so far is that in the process of SSL handshake, client (browser in this case) encrypts a randomly selected symmetric key with the public key (certificate received from server). This is sent back to the server, server decrypts it (symmetric key) with the private key. This symmetric key is now used during rest of the session to encrypt/decrypt the messages at both the ends. One of main reasons to do so is given as faster encryption using symmetric keys.
Questions
1) How does browser pick and generates this "randomly" selected symmetric key?
2) Do developers (or/and browser users) have control on this mechanism of generating symmetric keys?
Here is a very good description of how HTTPS connection establishment works. I will provide summary how session key is acquired by both parties (client and server), this process is known as "a key agreement protocol", here how it works:
The client generates the 48 byte “pre-master secret” random value.
The client pads these bytes with random data to make the input equal to 128 bytes.
The client encrypts it with server's public key and sends it to the server.
Then master key is produced by both parties in following manner:
master_secret = PRF(
pre_master_secret,
"master secret",
ClientHello.random + ServerHello.random
)
The PRF is the “Pseudo-Random Function” that’s also defined in the
spec and is quite clever. It combines the secret, the ASCII label, and
the seed data we give it by using the keyed-Hash Message
Authentication Code (HMAC) versions of both MD5 and SHA-1 hash
functions. Half of the input is sent to each hash function. It’s
clever because it is quite resistant to attack, even in the face of
weaknesses in MD5 and SHA-1. This process can feedback on itself and
iterate forever to generate as many bytes as we need.
Following this procedure, we obtain a 48 byte “master secret”.
Quoting from a this great video on network video, minute 1:18:07
Well where do you get randomness on your computer because your
computer is a deterministic device?
Well it collects entropies like your mouse stroke movements, your key
stroke movements and the timing of your hard disk, it tries to collect
all that randomness from the universe into a pull so that it can generate random keys just for one connection [this session]. And if that randomness is broken and its happened many times
in the last 30 years, then none of this works. If the adversary can
figure what your randomness can be then they can guess your keys. So use good randomness.
Note: the keys are created per session.

Synchronizing a variable between client and server

Say I've got a client-side counter variable. When I send a request to the server, I send this variable's value, then increment it by one (for the next request to the server). The server keeps track of this counter independantly, and checks to make sure that the count sent by the client is 1 more than it's own (server-side) copy of the count. This is all fine and dandy, but consider the following situation:
The client sends, say, 23 to the server.
The server receives 23, validates it, and increments its own counter to 23.
The server returns the All-Okay code to the client
-BUT-
Along the way from the server to the client, the return code gets corrupted. The client thus thinks that the server did not update its counter, and so leaves the client-side counter at 23. From this point onwards, the client and server are out of sync.
Does anybody know any robust schemes that would work in the face of such possible corruption/errors?
Thanks,
Cameron
Instead of using a linearly increasing counter, you can use a random "nonce" value of a good 64 bits of entropy or more. When the server receives a request from the client, the server checks to see whether the nonce matches the last one it sent the client. If so, then the request is processed and the server generates a new random nonce value to send in the response.
The server can keep the last two nonce values to send to the client. If the client sends the old value, then the server assumes that the most recent message to the client might have been lost.
The above method assumes that your goal is to prevent two different clients from using the same credentials to communicate with the server. The advantage of using the nonce method is that the next value can't easily be predicted.
The easy answer is to make one of the client or server the owner of the resource, instead of making both own its own copy of the resource.
If you're using a reliable protocol like TCP though, you don't have to worry about the message not getting to the client.
A good thing to follow when doing client/server work though is to make all operations idempotent. That is to say each function could be called one or many times without any side effects. In this case you wouldn't have an 'increment' function at all. Instead you'd have a 'set' function.
How about just not having the client update its local copy until the server acknowledges the update of the server counter.
So:
Client calculates next value
Client sends next value to server
Server checks that next value is valid (not already seen)
Server updates counter to next value (if needed)
Server notifies client that next value has been received
Client updates local counter to next value
If the server does not receive the client update, the client merely resends the calculated next value. If the client does not receive the next value confirmation, it will resend the next value, but the server having already seen it does not update, but merely acknowledges. Eventually, the client sees the server's message and continues. This covers the case of lost messages.
If you are concerned about corruption, calculate a checksum on the message and send that as well. Recalculate the checksum on receipt and compare it to the one sent. Generally the network stack does this for you, though, so I wouldn't worry too much about it unless your are running your own protocol.