Unique Key Generation Logic - php

I am planning to build, for lack of a better term, a multi user Customer Relationship Manager (CRM) and I want to create a unique identifier that is easy to transmit in email, via text, and verbally to other team members.
For Example:
I upload my list of 100 customers and John Smith and his phone number are included in that list. Upon upload, I want to generate a hidden fingerprint / unique identifier for John Smith in the database, and then propagate a 12 digit number that can be shared publicly.
In my mind like this - john smith + ph: 5557898095 = fingerprint: 7e013d7962800374e6e67dd502f2d7c0 displays to end user id number: 103457843983
My question is - what method or process should I use to take the name and phone number, generate a hidden key, and then translate to a displayable key that is linked to the hidden one?
I hope this clear. I mainly want to use the right logic process.

You could use crc32('fingerprint') for the end user id number:
<?php
echo printf("%u", crc32('7e013d7962800374e6e67dd502f2d7c0')); //226407465310
?>

I don't understand what your problem really is, but I'll try.
It seems like you mean something like this:
A SQL table which saves the public and private ID (and maybe other things).
You can generate a key like this:
$chars = '0123456789abcedfghijklmnopqrstuvwxyz';
function generateKey($length, $charsLength = 10) {
global $chars;
$key = '';
for($i=0;$i<$length;++$i) {
$key .= $chars[rand(0, $charsLength - 1)];
}
return $key;
}
$keyPublic = generateKey(10); // Public key with length 10
// Now check if the key already exist
while(mysql_num_rows(mysql_select('SELECT publicKey FROM keys WHERE publicKey = \''.$keyPublic.'\')) === 1) {
$keyPublic = generateKey(10);
}
$keyPrivate = generateKey(10, 36); // Private key with length 10
// Now check if the key already exist
while(mysql_num_rows(mysql_select('SELECT privateKey FROM keys WHERE privateKey = \''.$keyPrivate.'\')) === 1) {
$keyPrivate = generateKey(10, 36);
}
In this example there are two keys generated and it is checked if the keys already exist. (in the example in the table "keys").

Assuming your real ID is the auto_incremented field in your customer table, then just have a second table that maps your public ID to the real ID.
Assuming you're using some sort of hashing algorithm to generate your public ID, it'd be a simple process to do a lookup on that table when you create a new user to detect a clash with an existing user, then regenerate a new ID until there's no clash (e.g. include system time as part of your hash input, then just keep regenerating until you find a unique ID)

Related

PHP - Generating random integers within specified range from a key

I have a set of questions with unique IDs in a MySQL database.
Users also have a unique ID and are to answer these questions and their answers are saved in the database.
Now, I want users to get 5 non-repeating uniquely and randomly picked questions from the pool of available ones (let's say 50) based on users ID. So when a user with id 10 starts answering his questions, but stops and wants to return later to the same page, he will get the same questions as before. A user with id 11 will get a different random set of questions, but it will always be the same for him and different from all other users.
I found that random.org can generate exactly what I need with their sequence generator that generates a random sequence of numbers based on provided ID:
https://www.random.org/sequences/?min=1&max=50&col=1&format=plain&rnd=id.10
But I would like the generation to be done locally instead of relying random.org API.
So, I need to generate 'X' unique random integers, within specified range 'Y' that are generated based on supplied integer 'Z'. I should be able to call a function with 'Z' as parameter and receive back the same 'X' integers every time.
I need to know how to replicate this generation with PHP code or at least a push or hint in a direction of a PHP function, pseudo-code or code snippet that will allow me to do it myself.
Thank you in advance!
Why reinvent the wheel
mt_srand(44);
for ($i=0; $i < 10; $i++) echo mt_rand(). "\n";
echo "\n\n";
mt_srand(44);
for ($i=0; $i < 10; $i++) echo mt_rand(). "\n";
result
362278652
928876241
1914830862
68235862
1599103261
790008503
1366233414
1758526812
771614145
1520717825
362278652
928876241
1914830862
68235862
1599103261
790008503
1366233414
1758526812
771614145
1520717825
Generate your random numbers at the beginning and save it in a session. That way the random numbers for that user is always known and you can know what id of question you should go back to by looking it up in the session.
Cheers
you can get random $w array values. try this code as example and change with your logic.
$w = array('0'=>11,'1'=>22,'2'=>44,'3'=>55,'4'=>66,'5'=>88);
$str = '';
for($i=0;$i<5;$i++) {
$str.= $w[rand(0,5)];
}
As this article suggests, you could use a non-repeating pseudo random number generator. Only problem would be to generate a primnumber that is atleast 2x as big as the upper-bound for IDs and satisfies the condition p = 3 in the ring Z4. Though there should be big-enough primnumbers matching the conditions on the net for free use.
Due to my lack of experience with PHP i can only provide pseudocode though.
int[] generateUniqueRands(int id , int ct)
int[] res
const int prim//the primnumber described above
for int i in [0 , ct[
res[i] = ((id + i) * (id + i)) % prim
return res
Note that this algorithm basically works like a window:
id = x set = [a , b , c , d]
id = x + 1 set = [b , c , d , e]
...
If you wish to avoid this kind of behavior just generate a unique random-number from the id first (can be achieved in the same way the set of random numbers is generated).
When the user with ID 10 opens the page for the first time, use rand() to generate random numbers then store them into a cell in the users table in database. So the user with id 10 has the rand() numbers stored.
For example the users table has id, rand_questions.
Check if the rand_questions is empty then update with the new random numbers generated, else you get the numbers from the database.

PHP function for auto increment with changed value

I have a requirement where I need to insert user_id in following format
13310_userid_1
13310_userid_2
13310_userid_3
where
13310 = $_GET['userid'] //user id from session
userid = constant //constant text defined
1/2/3 = autoincrement value
Here the variation is when user_id is changed, the auto increment value will be inserted from beginning which would look like
13311_userid_1
13311_userid_2
13311_userid_2
and not
13311_userid_4
13311_userid_5
13311_userid_6
How can I check if the user_id is changed and insert auto increment value from 1 ?
Thanks
I'm not sure it's that you need, but you can use an array to store increment of each cont :
$const = 'userid';
$user_id = '13310';
$array_increment[$user_id] =1;
foreach(array('Franck','Robert','You','Me') as $index=>$test){
if($index==2)$user_id = '13311';
if(!isset($array_increment[$user_id])){
$array_increment[$user_id]=1;
}
$increment = $array_increment[$user_id];
echo $user_id.'_'.$const.'_'.$increment.'<br />';
$array_increment[$user_id]++;
}
Will show :
13310_userid_1
13310_userid_2
13311_userid_1
13311_userid_2
you could store the incremental value of each userid in a temporary session:
For each request check if $_GET['userid'] already exists in a session if not create it with value zero.
Increment by one and use this value to create your string for inserting into DB
//set up session if it is not already set
if(!isset($_SESSION['users'][$_GET['userid'])){
$_SESSION['users'][$_GET['userid']=0;
}
$_SESSION['users'][$_GET['userid']=$_SESSION['users'][$_GET['userid']+1;
$user=$_GET['userid'].'_userid_'.$_SESSION['users'][$_GET['userid'];
//insert $user into your DB or permanent storage.
$db->insert($user);
(this should be a comment but its a bit verbose)
Your only makes sense if a database figures in here somewhere - but you never explicitly stated that this is the case nor which database it is.
Relational database design (and to quite a large extent, non-relational database design) is subject to the rules of normalization. These are methods for describing the structure of your data and prevent you doing stupid things. This breaks the first rule.
Assuming you were designing the system properly, then you would keep the three attributes as seperate fields. But that does not answer the question of whether the id is nominal, cardinal or ordinal (and in the case of ordinal numbers whether there is a requirement for them to be consecutive).

Insert multiple email(Unique Key) rows in your database

I want to populate a table that has the next structure:
USERS_TABLE
ID_USR (Primary_Key, AUTO_INCREMENT)
USERNAME (Not Null)
EMAIL (Not Null, Unique Key)
Password(Not Null)
Nacionality (Not Null)
Work (Null)
And I want to do it with a php script. It's not a problem for me to create the script but I have some doubts with the email's field. I don't want real names or emails, just data and the posibility to introduce over 10-100 rows.
So with the ID_USR I don't have problems because it's an auto increment value, no problems with the not null's or null's fields.
Now think about the email, as you see it is a unique key so I thought about putting two random numerical values​​, one before and one after # and then the extension.
Example:
<?php
for ($i = 0; $i < 10; $i++)
{
$a = rand();
$b = rand(); // array("gmail", "facebook", "hotmail", "outlook", "yahoo".....);
$extension = array(".com", ".es", ".net", ".org"); // ....
$c = rand(0,3);
$email = $a."#".$b."".$extension[$c];
echo "$email";
}
?>
It returns to me:
2095518299#699790428.com
254450939#1623171070.org
1142680888#2074501004.org
1940419404#1779299580.es
726585010#1262850036.net
578544275#145818927.net
2067281904#1894405902.org
275443932#1915863743.es
734209458#1269004984.com
1035465063#1828742272.net
As you can see this can work but my question is if there is a smarter/efficient way.
I think this may be constructive so I hope your answers. See you.
Aha, the test data problem!
If I were you I'd use a domain name you control for the domain part of the email addresses. That is,
726585010#emailtest.yoyodyne.com
578544275#emailtest.yoyodyne.com
2067281904#emailtest.yoyodyne.com
(if you happen to work for Yoyodyne.) This will prevent randomly generated email addresses from escaping into the wild if you should make an error and try to send to everybody.
Then, use a longer random number for the number so you don't get many accidental collisions. You will probably will get some.
Finally, after you populate the table, before you use it, go back and change the email column so it incorporates the id number.
UPDATE USERS_TABLE SET EMAIL = CONCAT(ID_USR,'#emailtest.yoyodyne.com')
That way your tests will be readily traceable back to particular user rows.

While loop for mysql database with php?

I am developing a mysql database.
I "need" a unique id for each user but it must not auto increment! It is vital it is not auto increment.
So I was thinking of inserting a random number something like mt_rand(5000, 1000000) into my mysql table when a user signs up for my web site to be. This is where I am stuck?!
The id is a unique key on my mysql table specific to each user, as I can not 100% guarantee that inserting mt_rand(5000, 1000000) for the user id will not incoherently clash with another user's id.
Is there a way in which I can use mt_rand(5000, 1000000) and scan the mysql database, and if it returns true that it is unique, then insert it as the user's new ID, upon returning false (somebody already has that id) generate a new id until it becomes unique and then insert it into the mysql database.
I know this is possible I have seen it many times, I have tried with while loops and all sorts, so this place is my last resort.
Thanks
You're better off using this: http://dev.mysql.com/doc/refman/5.0/en/miscellaneous-functions.html#function_uuid
Or using this: http://dev.mysql.com/doc/refman/5.0/en/insert-on-duplicate.html
But if you actually want to do what you are saying, you can just do something like:
$x;
do {
$x = random_number();
"SELECT count(*) FROM table WHERE id = $x"
} while (count != 0);
// $x is now a value that's not in the db
You could use a guid. That's what I've seen done when you can't use an auto number.
http://php.net/manual/en/function.com-create-guid.php
Doesn't this function do what you want (without verification): http://www.php.net/manual/en/function.uniqid.php?
I think you need to approach the problem from a different direction, specifically why a sequence of incrementing numbers is not desired.
If it needs to be an 'opaque' identifier, you can do something like start with a simple incrementing number and then add something around it to make it look like it's not, such as three random numbers on the end. You could go further than that and put some generated letters in front (either random or based on some other algorithm, such as the day of the month they first registered, or which server they hit), then do a simple checksuming algorithm to make another letter for the end. Now someone can't easily guess an ID and you have a way of rejecting one sort of ID before it hits the database. You will need to store the additional data around the ID somewhere, too.
If it needs to be a number that is random and unique, then you need to check the database with the generated ID before you tell the new user. This is where you will run into problems of scale as too small a number space and you will get too many collisions before the check lucks upon an unallocated one. If that is likely, then you will need to divide your ID generation into two parts: the first part is going to be used to find all IDs with that prefix, then you can generate a new one that doesn't exist in the set you got from the DB.
Random string generation... letters, numbers, there are 218 340 105 584 896 combinations for 8 chars.
function randr($j = 8){
$string = "";
for($i=0;$i < $j;$i++){
srand((double)microtime()*1234567);
$x = mt_rand(0,2);
switch($x){
case 0:$string.= chr(mt_rand(97,122));break;
case 1:$string.= chr(mt_rand(65,90));break;
case 2:$string.= chr(mt_rand(48,57));break;
}
}
return $string;
}
Loop...
do{
$id = randr();
$sql = mysql_query("SELECT COUNT(0) FROM table WHERE id = '$id'");
$sql = mysql_fetch_array($sql);
$count = $sql[0];
}while($count != 0);
For starters I always prefer to do all the randomization in php.
function gencode(){
$tempid=mt_rand(5000, 1000000);
$check=mysql_fetch_assoc(mysql_query("SELECT FROM users WHERE id =$tempid",$link));
if($check)gencode();
$reg=mysql_query("INSERT INTO users id VALUES ('$tempid')",$link);
//of course u can check for if $reg then insert successfull

Generating Strong Unique User ID's w/PHP & MySQL

Ahoy Stack Overflow! This be mai first post...
I'm attempting to identify users with a salted unique public key.
Algorithm - Should I use uniqid(), sha256, sha512, something else? All hashes will be salted. NIST recommended SHA256, but I prefer to hear what others might suggest.
Generation - Does hash(SALT + AUTO_INCREMENT_PK + CREATED_TIMESTAMP) suffice? More entropy?
I'd use email, as it is unique for each user, however the user can modify their email address. I was also considering storing signup_email so that hashes would not have to be re-calculated.
MySQL Storage - Currently, our ID's are INT(255) auto_increment primary key's. As stated earlier, potentially hundreds of millions of keys. Depending on the crypto algo, I should have a fixed-size ID. Can I keep INT(255) or should I use CHAR(n)?
---------------------- Thanks for reading :) -------------------------------
One thing: If you don't trust the users with their IDs, sending them over GET or POST will not work; those are all visible to motivated users.
I would use SHA256 using a salt.counter.time string, and use the output to generate GUIDs for the actual id. This would minimize the possibility for collisions.
You will have to use CHAR for MySQL to store GUIDs.
See the comments at http://us2.php.net/manual/en/function.uniqid.php for more in-depth info. AFAIK GUID is not part of the PHP core so you have to fake it a bit.
If you are using user id as the way to allow a user to do anything with your service, if one user "guesses" the user id of another one, he'll be able to do whatever he wants with that one's account ?
You do not have any kind of other password or anything to go along that ?
Well, in that case, you need something quite unique, don't you ;-)
(Hoping I understood the question well -- but that might not be the case -- sorry, if it isn't)
What do you think of using Globally Unique Identifier (like, for instance, 61350955-9755-4AF3-8C19-6DBC42CA69E2) for your users ?
For an example of how they look like, take a look at http://createguid.com/
As a sidenote, that GUID is quite long ; which means lots of bytes in your DB, if you have millions users... So, it probably shouldn't be used as any kind of primary/foreign key.
What about using the smallest possible integer (that fits the number of users you'll have) as primary/foreign key, as that one will be duplicated in many places of the application ; and only have the "long user id" stored only once, in your user table ?
I wrote this class that gives you an unique id of 24 chars, compatible with the id field of MongoDB (and using the same logic to construct it). Might be useful in the future.
<?php
/**
* Generator for Mongo-like ObjectIds in pure PHP
* Author: Mauricio Piacentini
*
* Inspired by https://github.com/justaprogrammer/ObjectId.js
*
*/
class ObjectIdFactory
{
private $_datetime = null;
private $_machine = null;
private $_pid = null;
private $_increment = null;
public function __construct()
{
$this->_machine = str_pad(dechex(rand(0, 16777215)), 6, "0", STR_PAD_LEFT);
$this->_pid = str_pad(dechex(rand(0, 32767)), 4, "0", STR_PAD_LEFT);
$this->_increment = rand(0, 16777215);
//We need a DateTime object to get timestamps, cache it
$this->_datetime = new DateTime();
}
public function getNewId($forcedincrement = null)
{
if (is_null($forcedincrement)) {
$this->_increment++;
if ($this->_increment > 0xffffff) {
$this->_increment = 0;
}
} else {
$this->_increment = $forcedincrement;
}
$timestamp = $this->_datetime->getTimestamp();
$timestamp_final = str_pad(dechex($timestamp), 8, "0", STR_PAD_LEFT);
$increment_final = str_pad(dechex($this->_increment), 6, "0", STR_PAD_LEFT);
return $timestamp_final . $this->_machine . $this->_pid . $increment_final;
}
}
https://github.com/piacentini/ObjectId.php
Have you looked into using a UUID?
A quick google search yields some good resources/links.
Personally I use md5(uniqid(mt_rand(), true)) which will create 32 character identifier (a 128 bit hex number) that is extremely difficult to predict.

Categories