Partially Encrypted Buttons( a flexible approach to encrypted data) |
home page std.css Encrypt program prime.html crypto.js |
A problem with the PayPal interface is that it leaves the price of an item hanging out there for anyone to modify. This can present some problems for automated systems where the item is sent out if the IPN indicates successful payment.
This article will investigate the use of encryption techniques to verify the acceptable range of prices on all received orders.
PayPal offers two approaches to protecting data with encryption. The first is a Button Factory interface for Single Item Purchase (_xclick) which only permits the use of a few fields. Option fields are not included. This approach does not allow dynamic modification of data (size, color).
The second is a dynamic encryption method using either Java or Perl within your server. To work properly it requires a product database within your server to obtain accurate price information. The drawbacks and limitations are rather severe here - the biggest is that you have to have a monster server application running for users complete with product database. The next problem is that this method also only supports the SIP method.
The question I cannot answer with the 2nd approach, is if you have to go to the server in the first place, what is the purpose of then encrypting the data when you are going to send to PayPal over an SSL link? This makes no sense to me at all.
What we need to do is to somehow make certain that the prices of goods being ordered are within acceptable limits. Prices may vary depending on things such as size, or quantity ordered (discounts). So a tee-shirt with a base price of $20.00 may vary in price from $15 to $23 depending on selections made at the time of the order.
What we need to do is to look at the returned price in IPN and make sure it has not been messed with - that it is within an acceptable range. We do this by encrypting some data, and then using that data to check out the ordered items in the data returned to us by the IPN process.
In the example of the tee-shirt, above, we might want to encrypt the price range of 15 to 23 to verify that the returned price is within that range.
A simple way I am going to describe is to use the item number of each item as part of a key value for encryption. The data I am going to encrypt is something like a query string in format to make reading it easier for code.
This can be a problem, depending on the languages used for client-side and server-side implementation. The problems come from the different number of significant digits carried for numbers, and the integer/real characteristics in different languages.
This example uses JavaScript which has 16+ significant digits for numbers, and has no differentiation between real and integer numbers (they are all of type real, internally). Your language may not support that many significant digits, or may not move freely between real and integer numbers. You simply MUST test the random number generator you select on both your server, and a general JavaScript supporting browser. If they do not produce the exact same numbers for the same key, then you must adjust the generator to make sure that it does - NO EXCEPTIONS!
Once the random number generator can be repeated in your browser, AND your server, then you are ready to go. What is encrypted with the browser must be decrypted by your server code.
To find out what I'm doing, you need to read this article - crypto techniques.
Using that article as a guide, here is what I'm going to do... Take certain information from a FORM, and certain information about what may happen within that FORM, and encrypt it. In particular, I'm going to take item_number, minimum price per item and maximum price per item, and encrypt them and place the result (manually) into the option field so I can read it when PayPal returns an order to me.
Above is the front-end processing necessary to include protective encrypted information within your PayPal button. What we did for each item was to encrypt some basic information, and include it within the items on our site. This information is sent to PayPal, and PayPal returns it to us so we can decrypt it and compare it with the other information PayPal returned. If it doesn't match, then someone has tried to cheat us.
We encrypted that data before we built our site, and put it into our site. It gets sent to PayPal, and PayPal returns it to us. We then decrypt it and check things out. The user never sees our encryption/decryption algorithm, and does not have access to it, and has no idea what we encrypted (63 characters that he cannot tell anything about).
My very simple example includes item_number, and a min/max price range. You can put in there whatever you want - up to 63 chars (before encryption). If you had site-wide discounts (or any other site-wide paramaters that might affect price) then you could encrypt that data (100 characters before encryption) and put it into the "custom" field. It's all up to you.
This puts things entirely into your hands, and gives you complete flexibility. Modify the button contents (size, color, discounts) all you want - just make sure your encrypted string takes all possibilities into account.
In the real world you would encrypt more data than I did for this simple example. And include tricks like putting garbage data into certain fields (data that is ignored except to add to the encrypted data). If you have a discount structure, you might want to include that in the encrypted data so you can calculate the exact price based on quantity. You can encrypt up to 63 characters, and that is really quite a bit of information - use your imagination.
Also, you can use separator characters to indicate "fields", such as an &. Here is a string for encryption that has the item number, a garbage field, base price of 10, and a discount structure of 2-4 for 9 and 5+ for 8. When you get the IPN back you can calculate what the exact price should be (and all in just 29 characters)...
?A101b,garbage&A=10&D=2,9,5,8
Create the data string so that it may be easily parsed by your server.
Here is a possible key for the above encryption string. Remember that it must contain the unique item number in it - there must be a different key for every item in your site! And item_number is the way to know what that key value is. It also ensures that the encrypted string is correct for that item (prevents someone form copying the encrypted string from a cheaper item, and using it for a more expensive item)!
my-key,A101b,junk
If someone knew exactly what you were doing, then he could fake you out by creating a FORM to send to PayPal using the item_number, price and the encrypted string from a cheaper item. This is countered by only shipping based on item_number.
As you can see, this takes a little thought. You must have a unique identifier for every item of your site, and that unique identifier must be part of both every key value, and every data value of the encryption. And it must "appear" in plain-text somewhere in the data PayPal returns for each item! And, you must ship based on that unique identifier. Incorporate those things into your process, and no one will ever cheat you again! If you want to get real nasty, then take the unique identifier and reverse it in your key, or encrypted data strings.
Possible data value 1 - 9.00,13.00,A101b,12345
Possible data value 2 - 90.00,130.00,A103ax,12
Possible key value 1 - Spec-key,A101b,Stinky. Ls
Possible key value 2 - Spec-key,A103ax,Stinky. Ls
Notice that the data values are all the same length (used a pad field), the position of the unique ID is not the first in the list, and the key contains the unique ID with stuff from me that only I can contribute to make my key extra-unique (two people may come up with the same "item_number" - that's why you need special extra stuff in there).
We have sent stuff to PayPal with our special encrypted data in it. We get a response back via IPN, so now what? What do we do with the order? But really important is, if we detect a problem, just how do we interact with PayPal over this matter?
In our server we get the data back from PayPal, and we must make some decisions about this order...
When I asked PayPal if they had a rejection response to an IPN notification, I was initially disappointed that they did not. After some thinking, I realized that PayPal is just a collection agent - why put on them the responsibility to refund money? They have done their job and collected what they thought was owed us!
If WE detect a problem (cheaters), then the responsibility is on US to do something about it. PayPal has done their job of collecting the money they thought was due us, and now WE have to step up to the plate and exercise OUR responsibility. PayPal gives us the tools, and all we have to do is to use them. (No APIs for this, yet, but that is another problem.)
We detect attempted fraud. We accept the payment via IPN. We do not ship the goods (route msg to fraud dept). We refund the money (nastygram). We notify PayPal. We smile that we avoided being cheated. And we notice that fraud attempts have gone down because people don't know what that encryption stuff is within our site.
Just some random thoughts. Being able to encrypt data from prying eyes has all sorts of uses. These cases assume you have access to your server (your own, or leased), and are able to program it. Client to your server communication... (action="call.to.your.server")
The ability to hide certain data from clients while it is in plain view (but enctypted) has uses beyond imagination. You can include stuff within your HTML pages that takes the place of product databases (looking up price, but not available quantity) - the offloading of "knowlege" from server to client page... The ability to include special bits of encrypted data that uniquely identify the originating source of a transaction...
Having data in your server prevents others from acessing it - but so does having it encrypted within your HTML pages.
This is not "casual" encryption.
Contact me concerning this article at
paypalhelper@aol.com.
Mention "partial encryption" in your note.
Individual help starting at $25.00 for simple JS solutions.