Jump to content

PIN algorithms


Synook

Recommended Posts

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

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

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

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

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

Hmm ok it seems you are right JSG. Bother. Hmm... *thinking* :)Thanks for the comments.

Link to comment
Share on other sites

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

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...