i will be providing api keys to my partner sites and they will be using code that i give them to to generate "tokens".
these tokens will be automatically present on forms which the partner sites' users will click on and reach my site. when they reach my site, i will need to validate that they indeed came from a partner site.
how do i validate this? the apikey will be secret, but what is presented in the form will NOT be, so it must not be possible for smart users to reverse engineer my algorithm.
EDITA
Option1: I get teh client page to send across md5($apikey.$time) AND $time (in plaintext). When i get it, i use time and my copy of apikey to generate md5($apikey.$time). if it matches and is within 1 hour (or whatever), i let the request proceed.
Option2: I already have $userid,开发者_运维百科 $requestcommandoption coming in as well. I can do the following:
$input = $userid.'-'.$requestcommandoption.'-'.$time;
$encrypted_data = mcrypt_ecb (MCRYPT_3DES, $apikey, $input, MCRYPT_ENCRYPT);
when i get it at my end, i can do:
$decrypted_data = mcrypt_ecb (MCRYPT_3DES, $apikey, $encrypted_data, MCRYPT_DECRYPT);
and then check the 2 inputs if they are the same, and the 3rd if its within 1 hour?
EDITB
How secure does this sound? (code borrowed from http://onlamp.com/pub/a/php/2001/07/26/encrypt.html?page=3)
// on client
$apikey="test123";
$userid = '577';
$requestcommandoption = 'delete-all';
$time = mktime();
echo "time = $time<p>";
$input = $userid.'-'.$requestcommandoption.'-'.$time;
// Encryption Algorithm
$cipher_alg = MCRYPT_RIJNDAEL_128;
// Create the initialization vector for added security.
$iv = mcrypt_create_iv(mcrypt_get_iv_size($cipher_alg, MCRYPT_MODE_ECB), MCRYPT_RAND);
// Encrypt $string
$encrypted_string = mcrypt_encrypt($cipher_alg, $apikey, $input, MCRYPT_MODE_CBC, $iv);
$transmitted = bin2hex($encrypted_string);
// sent from client to server
print "Encrypted string: ".$transmitted."<p>";
// received on server
$encrypted_string = pack("H*" , $transmitted);
$decrypted_string = mcrypt_decrypt($cipher_alg, $apikey, $encrypted_string, MCRYPT_MODE_CBC, $iv);
print "Decrypted string: $decrypted_string";
Looks as if you're implementing something similar to open authentication - the process twitter/facebook etc use for enabling partner sites.
I'd recommend that you take a look at oAuth - http://oauth.net/ - there are plenty of libraries and php samples.
If you really want to do something simple, then assuming you've got a record of the API keys you've handed out, I would write the client script so that it makes an md5 hash of the key with another bit of information on the form - a username for example (lets call the hashed string the request key and the username the username), and I'd include an identifier for the partner (which we'll call partner_id).
So when the form submits it has the requestkey, username and partner_id.
When your server receives the request you can look up the secret key for the partner using the partner_id, then md5 the secret key you've got, with the supplied user name and see if it matches the md5 key sent with the form.
@frank...
[Adding this as a result of your comment]
In order to make the key that is sent over the wire disposable, you can get the client web page to request a temporary session key - your server generates one (using a combination of date + time + a secret word), saves it as a temp key in the partners table (alongside their permanent key) and sends it back to the client. The client app then MD5's this with the permanent key and submits this with the form. You then look up the permanent and temp keys and hash them together and compare the result with the hash you've been sent.
does that seem ok?
What about GUIDs? Of course, you would have to track the issued GUIDs.
http://php.net/manual/en/function.com-create-guid.php
You should check out OAuth and OAuth 2 standards. They're widely used for authorization and many APIs (Facebook, Twitter, etc.)
精彩评论