We're designing a PIC based system. We would like that users enter a serial key (registration key) like the one commonly found in desktop software. For our system, we will have the user's email address and/or his cellphone number. The system is a standalone device with a keyboard and display. The system will allow the user to pay by punching in a specific registration code that he purchased via SMS. The user will send a SMS to a server. The server would use the provided user's email or/and phone number and generate a unique registration key. Does anyone has clues on how to get started?
I am targeting this answer at what can realistically be achieved on a PIC microprocessor.
I would generate a random number on the PIC, the common way to do this is to use the A2D as a noise generator and repeatedly sample the LSB. Once you have this, append a check digit or two and display it to the user. The check digits will allow you (on the server that receives the text) to guard against billing the user for a miss-typed code.
On the server, take the users code, strip the check digits, run it through a Linear Feedback Shift Register that is pre-loaded with a secret value. Charge the user, if the payment clears, text back the output code.
Your PIC chip needs to know the secret too, and repeats the calculation. You might want to try Microchips CRC Generator hardware eg. AN1148 shows how to use the hardware LSFR. Load in the secret, then clock in the random challenge. Compare this to what the user keys in - a result that matches most likely means a purchase.
I'd have a supervisor mode if this is a kiosk, rather than single device, to allow the re-loading of another secret code, or pattern of LFSR taps, secured by physical access and store this in the NVRAM. This way you can at least change the encoding over time, or in response to a break. Add NVRAM counters to compare local purchases against server approvals to monitor slippage. Watch your wear-levelling though!
This is only as 'secure' as your secret and technique staying private. It would be relatively trivial for anyone who can dump a hex image from your machine to reverse the algorithm from the assembler, although presumably anyone with physical access has simpler techniques to get the product without paying. Similarly anyone willing to guess the technique, buy a code and another for validation could guess the technique and do a brute force search for the secret.
I don't think full public key cryptography is viable on these machines, so this is a compromise. Porting OpenSSL is going to be non trivial and use up a significant portion of your developer time and code space. If it's not a missile launch code, or you need to protect users details, or guarantee votes in an election, public key cryptography is probably more than required for your revenue protection case. Caveat emptor.
Use an MD5 hash. This will create a 128-bit key, so you can represent that as 32 hex characters. A hash never can guarantee uniqueness, but the length will decrease the chances of coinciding hashes. If 32 hex characters is too long you can truncate it to the desired length.
If you need a unique serial key you have to append a unique number, like customer number, to the hashed user data, so that it's not included in the hash calculation.
If a registration code must work on one and only one device and no other devices, then this could be a good use for public/private key architecture.
It works like this: Your server will have a public key and a private key. The private key is always kept secret. The public key is viewable to anyone who wants to see it (although we won't be needing to do that in this case). If the server encrypts something with its private key, then only its public key can decrypt it. If somebody else encrypts something with its public key, then only the server can decrypt it with its private key.
This accomplishes two things
By having the server encrypt ("sign") something with its private key, we can verify that it's really coming from the server by decrypting it with its public key. We can authenticate the source of the message.
If we encrypt something with its public key, then only the server can ever decrypt it, thus we can send it messages that no one else but the server can read.
If we have the device have its own set of public and private keys, and a copy of the server's public key, then we can establish messages between the two that no-one else can read.
So you could have a system that work like this:
Server side, a database schema that maps device serial numbers to their public keys. When someone makes a purchase, they must provide this serial number. When a purchase request comes in via SMS, the server stores the phone number and looks up the device's public key from the provided serial number. When it is found, it will hash, then encrypt the SMS phone number using the device's public key, then that entire cipher would then be encrypted again using the server's private key. It sends this back to the user via SMS.
When the user punches in this hex string, the device will first decrypt using the server's public key - this is to ensure that it actually came from the server. That removes the first layer. Then it decrypts using its own secret private key, this should give you the hashed SMS number. Get the user to enter in their phone number and hash it. If the hashes match, then procede.
If you need to have sessions that expire, include a time stamp along with phone number hash before the encryption on the server side and have the device make the decision of whether or not that key is still fresh.
Here is a primer on public/private key architecture: https://en.wikipedia.org/wiki/Public-key_cryptography
What you would be interested in is:
- Choosing a method to generate public/private key pairs
- Choosing an encryption method to encrypt data using this keys.
If the system will have a serial number that you generate burned into a protected area of the code space, you could simply program each unit with an activation key along with the serial number. This would require you to ensure that you keep track of the issued serial numbers and associated activation codes, but if the codes are generated randomly, you could avoid the risk of someone discovering the algorithm used to generate the keys. If you don't want to worry about keeping track of all the issued keys, you could use an algorithm to generate them, and have some attribute of the algorithm set differently for each batch of devices (you could, for example, encrypt the keys for each batch with a hash of the lottery numbers drawn for the New York State Lotto the Friday before the batch was produced. Even if your own records were destroyed, you would be able to go back and find out what the numbers were, but it's unlikely someone would be able to reverse-engineer the fact that the lottery numbers were the source data for the hash, especially since the number of discrete batches would be small compared to the number of units.
If you will be using a serial number which you are not supplying (e.g. a device serial number burned into a flash chip) then you have two main choices: have the device use the serial number to compute what the key should be, or have software in the factory (outside the device) munge the serial number in a confidential way to yield a key which, when munged a certain way by the device, will yield the serial number. The latter approach has the advantage that even if someone were to reverse-engineer the key-validation code in the device, they would be unable to generate keys that would work for arbitrary serial numbers. It would, however, have the disadvantage that keys would probably have to be a minimum of 128 bytes to have anything resembling security (given today's advances in CPU technology, 256 bytes would be better). Not a problem if your device would be connected to a PC or portable memory device for purposes of activation, but not so great if people are entering a code via thumbwheel.
You could generate a digital signature from the users user's email or/and phone number using the OpenSSL libary that has public key cryptography functions that would be suitable. It might be hard to find space for code for verification in a PIC chip in which case a simpler and much less secure system based on a checksum/hash on the email/phone number may have to suffice- in that case be sure to salt the email/phone number to prevent users from discovering the checksum algorithm by trial and error.