Synook Posted June 22, 2008 Share Posted June 22, 2008 Hello everyone,Recently I wrote an algorithm in PHP to generate a random alphanumeric PI "N" based on a key, that could then be checked against the same key. Before they get used for some secure application, however, I'd like to get you guys to check whether there are any flaws in the logic. <?php /*--------------------------------------------------------------------------------------- PIN Generator and Checker ----------------------------------------------------------------------------------------- These PIN functions generate and check random PINs based on an averaging algorithm. PINs are given uniquness for each application through a set of eight "keys". The keys should be numbers between 13 and 20 (other values are possible but will result in more non-alphanumeric PINs which are rejected). ----------------------------------------------------------------------------------------- Functions copyright (C) RoundedDesign 2008. All rights reserved. This notice must remain intact. ---------------------------------------------------------------------------------------*/ //pin_generate(int $length, array $keys) //This function will generate a PIN of length $length //$keys is an array of the length of the PIN being generated. Numbers should be around 13 - 20 function pin_generate($length, $keys) { do {//Enter a do .. while loop if ($length < 3) return false; //PINs can't be < 3 chars long $char[1] = rand(0,35); //Random char1 $char[2] = rand(0,35); //Random char2 for ($i = 3; $i <= $length; $i++) {//Loop for remaining chars $refchar = $i - 2; //Take the char 2 behind the current one as reference $char[$i] = 2 * $keys[$i - 1] - $char[$refchar]; //Find the value so that the average of the current char and the reference equals that of the key for the current char } $pin = ""; //Initiallize the pin variable for ($i = 1; $i <= $length; $i++) { //Loop through all the PIN's values $k = $char[$i] + 48; //Convert from base number into ASCII if ($k > 57) $k += 39; //... $pin .= chr($k); //Append to pin } } while (!preg_match("/^[a-z0-9]+$/i", $pin)); //This code will sometimes generate PINs with non-alphanumeric characters so we must try again if so return $pin; //Return the generated PIN } //pin_check(int $pin, array $keys) //This function will check a PIN generated by pin_gererate(). The keys have to be the same for it to match function pin_check($pin, $keys) { if (!preg_match("/^[a-z0-9]+$/i", $pin)) return false; //PINs can't have non-alphanumeric chars if (strlen($pin) < 3) return false; //PINs can't be less than 3 chars $length = strlen($pin); //Assign the length to $length (more efficient) for ($i = 1; $i <= $length; $i++) { //Loop through the chars $key = ord(substr($pin, $i - 1, 1)); //Get ASCII value from character $key -= 48; //Convert to base number if ($key > 10) $key -= 39; //... $base[$i] = $key; //Store to the array of base values if ($i >= 3 && ($base[$i] + $base[$i - 2]) / 2 != $keys[$i - 1]) return false; //If the current character is of position 3 or more and does not comply to the algorithm then return false } return true; //Everything passed, return true }?> If you like syntax highlighting: http://roundeddesign.com/lab/pin.phpsThanks Link to comment Share on other sites More sharing options...
boen_robot Posted June 22, 2008 Share Posted June 22, 2008 I think I'm missing the point of this. What's wrong with sha1() and other hashing algorithms? They too generate ony alphanumeric characters, right? If the generated values are too short - use an algoritm that uses more (like sha512). If they're too long, strip out characters that are after a certain known point (i.e. the length of the PIN).Other than that, I see no real errors in your code or logic. The only thing is that you may check for both the length and format inside the regex, instead of calling strlen() afterwards, like: if (!preg_match("/^[a-z0-9]{3,}$/i", $pin)) return false; //PINs must be at least 3 alphanumeric chars Link to comment Share on other sites More sharing options...
midnite Posted June 22, 2008 Share Posted June 22, 2008 interestingYet i worry, average's friend is even numbers. And, most likely, even alternate PIN are all even/odd. Will it loss some of variations? If you want to know if it's secure, try to calculate another key with a certain PIN, or calculate another PIN with a certain key.i am not good in Maths. Just hope i can give you some ideas =) Link to comment Share on other sites More sharing options...
Synook Posted June 23, 2008 Author Share Posted June 23, 2008 I think I'm missing the point of this. What's wrong with sha1() and other hashing algorithms? They too generate ony alphanumeric characters, right? If the generated values are too short - use an algoritm that uses more (like sha512). If they're too long, strip out characters that are after a certain known point (i.e. the length of the PIN).These functions are to create a string of characters that can then be checked to see whether they conform to a certain pattern. For example, they could be used in place of a password, where each person is given one PIN (of many possible for the chosen keys) and then upon authentication the PIN is verified.Sort of like what you get in program registration, where you have to enter the authorization code to be able to use the product. Link to comment Share on other sites More sharing options...
justsomeguy Posted June 23, 2008 Share Posted June 23, 2008 First, I'm not sure what's going on with the first 2 characters. Since they aren't significant to the generation algorithm then you might as well generate them automatically instead of having the user send them. Also, since the keys array and the length are connected, you can leave out the length and just have them pass the keys array. So a keys array with 8 elements would result in a PIN with 10 characters.Some of the key arrays have predictable pins. If there are a lot of zeros in the keys array then the patterns start showing up, it would be easy to create a pin based on the key, or if you saw a certain pin you might be able to guess the key.I'm a little worried about the formula you use though:$char[$i] = 2 * $keys[$i - 1] - $char[$refchar];It seems like it would be easy to generate the key array from the PIN. You know that the first 2 characters are random, so you can have this for the third character, assuming that the numeric value of it after the calculations is 19, and the first character is 15:19 = 2 * X - 1534 = 2X34/2 = 17 = XSo you know that the third (or first) element in the keys array is 17. It seems like you would be able to generate the key based off the PIN.Regardless, you have a return statement in the first function that you should move out of the loop, you don't need to check if the $length is greater than 3 every time through the loop. Link to comment Share on other sites More sharing options...
Synook Posted June 23, 2008 Author Share Posted June 23, 2008 Hmm ok it seems you are right JSG. Bother. Hmm... *thinking* :)Thanks for the comments. Link to comment Share on other sites More sharing options...
justsomeguy Posted June 23, 2008 Share Posted June 23, 2008 Yeah, any formula where you generate numbers based off the previous numbers is going to be a little weak. I haven't studied enough about encryption to understand the theory behind developing a strong cypher though. Link to comment Share on other sites More sharing options...
Recommended Posts
Archived
This topic is now archived and is closed to further replies.