SitePoint Sponsor

User Tag List

Results 1 to 10 of 10
  1. #1
    SitePoint Enthusiast
    Join Date
    Jul 2001
    Location
    cheshire
    Posts
    83
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    password generator- unique?

    I have a script that is supposed to generate unique passwords. Trouble is its producing passwords that already exist in the 'personaldetails' table. i don't think I'm the lucky type that wins the lottery everyday so it its not by chance - there is an error somewhere. (the userid is primary key and is autoincrement, I know thats not a standard way of doing it but that isn't causing this error)
    The script is:

    if ("SUBMIT"==$generate){
    $String = "This is the text which will be encrypted so that we may create random and secure passwords!";
    $Length = 8; // Change this value to indicate how long your passwords should be. 32 character limit.
    $String = md5($String);
    $StringLength = strlen($String);
    srand ((double) microtime() * 1000000);
    $Begin = rand(0,($StringLength-$Length-1)); // Pick an arbitrary starting point.
    $password = substr($String, $Begin, $Length);
    print ("Your recommended password isP><BIG>$password</BIG>\n");

    // Add the password to the database.

    $sql = "INSERT INTO personaldetails SET " .
    "firstname='$firstname', " .
    "surname='$surname'," .
    "password='$password'," .
    "teacherstatus='$teacherstatus'";
    if (mysql_query($sql)) {
    echo("<P>Your password has been added to the database.</P>");
    } else {
    echo("<P>Error adding password to database: " .
    mysql_error() . "</P>");
    }
    $Query5="SELECT userid FROM personaldetails WHERE password='$password'";
    $result5=mysql_query($Query5) or die ("Can not execute query:" . mysql_error());
    print("Your userid is " . mysql_result($result5,0) . ". This has also been added to the database. ");
    }

    I don't understand why its not generating unique passwords. As, a consequence I'm bringing back the userid for the password that was already in the table, I end up with 2 people sharing the same password and and the generator reports they have the same userid ( when I look in the table the newest row has been added and has a userid which is different to the userid of the other person in the table who has the first copy of the password. My query to bring back the userid is bringing back the userid of the first row it comes to that has the 'unique' password entry, unfortunately the password is not unique and so I get the wrong persons userid? - can you spot what is wrong with the generator?
    Last edited by p0c79; Sep 9, 2001 at 02:39.

  2. #2
    SitePoint Wizard johnn's Avatar
    Join Date
    Mar 2001
    Location
    Southern California, USA
    Posts
    1,181
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hello,
    rand() is not that good. Try mt_srand() and mt_rand()
    You can read the manual to see how they are use together.

    John

  3. #3
    ********* Callithumpian silver trophy freakysid's Avatar
    Join Date
    Jun 2000
    Location
    Sydney, Australia
    Posts
    3,798
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I can't see any problem with the algorithm you are using. My guess is that you are seeding the random number generator more than once in the one script. Is there another place where it may be seeded (an include file?). If this is so - then that's a no-no. Otherwise, ... ?

    BTW the manual says that mt_srand() and mt_rand() are superior to srand() and rand(). Here is the algorithm I use (I copied it from somewhere else - a zend.com tutorial perhaps - can't remember):
    PHP Code:
          mt_srand( (double)microtime() * 1000000 );
          
    $chars "abcdefghijklmnopqrstuvwxyz1234567890";
          
    $length 8;
          
    $code "";
          while ( 
    strlen($code) < $length ) {
             
    $code .= substr($charsmt_rand()%(strlen($chars)), 1);
          } 

  4. #4
    SitePoint Enthusiast
    Join Date
    Jul 2001
    Location
    cheshire
    Posts
    83
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    seeding more than once!

    I suspect you are correct about the seeding more than once. I have enclosed the full script below. I think it may get seeded again when a user clicks the other link on the page which displays the form for indicating which class you want to see the results for. As this form returns you to the same page with the same 'generate a password' link, and "SUBMIT"==$generate is true.

    I think I will revise the script so the generate a password link does not remain on the page when a visitor returns to the page. My thinking is a bit woolly here - I'm trying to get my head round this but I'm not fully there yet. Can you see more clearly from the script how the reseading occurs.
    Many thanks.
    PHP Code:
    <?php
    function averageOfAverages($totalAvg$returnedRows){
    if (
    $returnedRows){
    $AverageOfAverages=$totalAvg $returnedRows;
    return 
    $AverageOfAverages;
    }
    else{
        
    $AverageOfAverages=0;
        return 
    $AverageOfAverages;
         }
    }
    ?>
    <html>
    <head>
    <title>The teacher page</title>
    </head>
    <body>
    PHP Code:
    <?php
    $Host 
    "*************";// Set the variables for the database access:
    $User "*****";
    $Password "*****";       
    $DBName "*******";     
    $TableName "testscores";

    $link = @mysql_connect("$Host""$User""$Password");
    if (!
    $link)
     {
     print(
    "<P>Unable to connect to the " .       
     
    "database server at this time.</P>\n");      //note how 2 strings have been concatonated
     
    exit();
    }
    else
    {
    print(
    "You're now connected to the Mysql server at the host ISP.<P>\n");
    }

    if (! @
    mysql_select_db("$DBName") )
     {
     print(
    "<P>Unable to locate the $DBName database at this time.</P>\n");
     exit();
     }
     else
    {
    print(
    "The database $DBName has been located.</P>\n");
    }

    $UserName=urldecode($UserName);
    print(
    "Greetings " $UserName "<br>\n");
    /*
     If the teacher wants to see the scores for a class, display the form that allows the teacher to choose which class but don't display it if the form has been submitted
    */
     
    if( (isset($displayscore)) AND ("SUBMIT"!==$displayscore)){

    print (
    "<FORM ACTION=\"$PHP_SELF\" METHOD=POST>\n");
    print(
    "<center><Table border=\"0\"  width=\"60%\"></center>\n");
    print(
    "<CAPTION ALIGN=\"TOP\"><b><font size=\"+2\">Data Collection Page 2</font></b></CAPTION>");

    print(
    "<INPUT TYPE=HIDDEN NAME=\"UserName\" VALUE=\"$UserName\">\n");


    //Allow the teacher to select the class that he/her wants to see the results for.
    print ("<tr><td> Select the class:</td>\n ");
    print (
    "<td><SELECT NAME=\"class\"><OPTION>Choose One</OPTION>\n");
    print (
    "<OPTION VALUE=\"11M1\">11M1</OPTION>\n");
    print (
    "<OPTION VALUE=\"11M2\">11M2</OPTION>\n");
    print (
    "<OPTION VALUE=\"11M3\">11M3</OPTION>\n");
    print (
    "<OPTION VALUE=\"11M4\">11M4</OPTION>\n");
    print (
    "<OPTION VALUE=\"11M5\">11M5</OPTION>\n");
    print (
    "<OPTION VALUE=\"11M6\">11M6</OPTION>\n");
    print (
    "<OPTION VALUE=\"11M7\">11M7</OPTION>\n");
    print (
    "</SELECT></td></tr>\n");

    print (
    "<tr><td><INPUT TYPE=SUBMIT NAME=displayscore VALUE=\"SUBMIT\"></td>\n");
    print(
    "<td><br></td></tr>");
    print(
    "</table></center>\n");
    print (
    "</FORM><br>\n");

    }
    //close the if isset
    //If the display form has been submitted run a query to select the relevant data


     
    if ("SUBMIT" == $displayscore) {
     
    // Request the pupils names and scores for class=$class from the personaldetails and //testscores table
     
    $Query "SELECT firstname, surname, testname, testscore FROM personaldetails p, testscores t  WHERE class='$class' AND p.userid=t.id ORDER BY surname, testname";
     
    $result mysql_query($Query); 
     if (!
    $result) {
     echo(
    "<P>Error performing query: " .
     
    mysql_error() . "</P>");
     exit();
     }
    }

    //Request the max score, min score and average score from testscores table
     
    if ("SUBMIT" == $displayscore) {
    $query2="SELECT testname, MAX(testscore) AS maxScore, MIN(testscore) AS minScore, AVG(testscore) AS averageScore FROM $TableName WHERE class='$class' GROUP BY testname";
    $result2=mysql_query($query2) or die ("Can not execute query:" mysql_error());
    $num_rows=mysql_num_rows($result2);
    }


     
    // Display the pupils name, test name and test score if the form has  been submitted
    if ("SUBMIT"==$displayscore){
    print (
    "<P> Here are the scores for class $class: </P>\n");
    // Create a table.
    print ("<TABLE BORDER=1 WIDTH=\"75%\" CELLSPACING=2 CELLPADDING=2 ALIGN=CENTER>\n");
    print (
    "<TR ALIGN=CENTER VALIGN=TOP>\n");
    print (
    "<TD ALIGN=CENTER VALIGN=TOP><b><font size=\"+1\">First Name</font></b></TD>\n");
    print (
    "<TD ALIGN=CENTER VALIGN=TOP><b><font size=\"+1\">Surname</font></b></TD>\n");
    print (
    "<TD ALIGN=CENTER VALIGN=TOP><b><font size=\"+1\">Test Name</font></b></TD>\n");
    print (
    "<TD ALIGN=CENTER VALIGN=TOP><b><font size=\"+1\">Test Score</font></b></TD>\n");
    print (
    "</TR>\n");
    /*Initialise the total variable to zero*/
    $total 0;
    //Fetch the results from the database.
     
    while ( $row mysql_fetch_array($result) ) {
    print (
    "<TR ALIGN=CENTER VALIGN=TOP>\n");
    print (
    "<TD ALIGN=CENTER VALIGN=TOP>" $row[firstname] . "</TD>\n");
    print (
    "<TD ALIGN=CENTER VALIGN=TOP>" $row[surname] . "</TD>\n");
    print (
    "<TD ALIGN=CENTER VALIGN=TOP>" $row[testname] . "</TD>\n");
    print (
    "<TD ALIGN=CENTER VALIGN=TOP>" $row[testscore] . "</TD>\n");
    print (
    "</TR>\n");
     
    $thistestscore $row['testscore'];     
     
    $total += $thistestscore;
     }
    print (
    "</TABLE><br>\n");

    }
     
    // Display the class max, min and avg for each test if the form has been submitted
    if ("SUBMIT"==$displayscore){
    print (
    "<P> Here are the max, min and avg scores for class $class  </P>\n");
    // Create a table.
    print ("<TABLE BORDER=1 WIDTH=\"75%\" CELLSPACING=2 CELLPADDING=2 ALIGN=CENTER>\n");
    print (
    "<TR ALIGN=CENTER VALIGN=TOP>\n");
    print (
    "<TD ALIGN=CENTER VALIGN=TOP><b><font size=\"+1\">Test Name</font></b></TD>\n");
    print (
    "<TD ALIGN=CENTER VALIGN=TOP><b><font size=\"+1\">Max Score</font></b></TD>\n");
    print (
    "<TD ALIGN=CENTER VALIGN=TOP><b><font size=\"+1\">Min Score</font></b></TD>\n");
    print (
    "<TD ALIGN=CENTER VALIGN=TOP><b><font size=\"+1\">Avg Score</font></b></TD>\n");
    print (
    "</TR>\n");
    /*Initialise the totalAverage variable to zero*/
    $totalAverage 0;
    //Fetch the results from the database.
     
    while ( $row2 mysql_fetch_array($result2) ) {
    print (
    "<TR ALIGN=CENTER VALIGN=TOP>\n");
    print (
    "<TD ALIGN=CENTER VALIGN=TOP>" $row2[testname] . "</TD>\n");
    print (
    "<TD ALIGN=CENTER VALIGN=TOP>" $row2[maxScore] . "</TD>\n");
    print (
    "<TD ALIGN=CENTER VALIGN=TOP>" $row2[minScore] . "</TD>\n");
    printf ("<TD ALIGN=CENTER VALIGN=TOP>%01.1f"$row2[averageScore]); print ("</TD>\n");
    print (
    "</TR>\n");
    $thisAverageScore $row2['averageScore'];     
     
    $totalAverage += $thisAverageScore;
     }
    print (
    "</TABLE><br>\n");
    $overallAverage=averageOfAverages($totalAverage$num_rows);
    print(
    "The combined average for the tests completed so far by $class is $overallAverage out of 25.0<br>\n");
    }
    // When clicked, this link will load this page
     // with the score submission form displayed.

    $UserName=urlencode($UserName);
    $logondetails=urlencode($logondetails);
     echo(
    "<P><A HREF='$PHP_SELF?displayscore=1&UserName=$UserName&userid=$userid&class=$class'>" .
     
    "Display the test scores for a class!</A></P>");



    if (
    "SUBMIT"==$generate){
    $String "This is the text which will be encrypted so that we may create random and secure passwords!";
    $Length 8// Change this value to indicate how long your passwords should be. 32 character limit.
    $String md5($String);
    $StringLength strlen($String);
    srand ((double) microtime() * 1000000);
    $Begin rand(0,($StringLength-$Length-1)); // Pick an arbitrary starting point.
    $password substr($String$Begin$Length);
    print (
    "Your recommended password is:<P><BIG>$password</BIG>\n");

    // Add the password to the database.

     
    $sql "INSERT INTO personaldetails SET " .  
     
    "firstname='$firstname', " .
     
    "surname='$surname'," .
     
    "password='$password'," 
     
    "teacherstatus='$teacherstatus'";
     if (
    mysql_query($sql)) {
     echo(
    "<P>Your password has been added to the database.</P>");
     } else {
     echo(
    "<P>Error adding password to database: " .
     
    mysql_error() . "</P>");
     }
    $Query5="SELECT userid FROM personaldetails WHERE password='$password'";
    $result5=mysql_query($Query5) or die ("Can not execute query:" mysql_error());
    print(
    "Your userid is " mysql_result($result5,0) . ". This has also been added to the database. ");
     }





     if (isset(
    $displayPasswordForm)){
    print (
    "<FORM ACTION=\"$PHP_SELF\" METHOD=POST>\n");
    print(
    "<center><Table border=\"0\"  width=\"60%\"></center>\n");
    print(
    "<CAPTION ALIGN=\"TOP\"><b><font size=\"+2\">Password Generator Form</font></b></CAPTION>");
    print(
    "<tr><td>Enter the pupils first name:</td>");
    print(
    "<td><INPUT TYPE=TEXT NAME=\"firstname\"></td></tr>\n");
    print(
    "<tr><td>Enter the pupils surname:</td>");
    print(
    "<td><INPUT TYPE=TEXT NAME=\"surname\"></td></tr>\n");
    print(
    "<tr><td>Choose Teacher Status:</td>");
    print(
    "<td>Y:<INPUT TYPE=RADIO NAME=\"teacherstatus\" VALUE=\"Y\"></td></tr>\n");
    print(
    "<tr><td><br></td>");
    print(
    "<td>N:<INPUT TYPE=RADIO NAME=\"teacherstatus\" VALUE=\"N\"></td></tr>\n");
    print (
    "<tr><td><INPUT TYPE=SUBMIT NAME=\"generate\" VALUE=\"SUBMIT\"></td>\n");
    print(
    "<td><br></td></tr>");
    print(
    "</table></center>\n");
    print (
    "</FORM><br>\n");
    }


     echo(
    "<P><A HREF='$PHP_SELF?displayPasswordForm=1'>" "Generate A Password!</A></P>");
     

    mysql_close($link);
    ?>
    <A href="feedback.php"><IMG
    height=31 alt="left arrow" hspace=10 src="2arrow4.gif" width=90 border=0></A>
    </body>
    </html>

  5. #5
    ********* Callithumpian silver trophy freakysid's Avatar
    Join Date
    Jun 2000
    Location
    Sydney, Australia
    Posts
    3,798
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Well I can only see one call to srand() in the script - so srand() can only be called once or never each time the script is run depending on the value of $generate. So that should not be a problem.

    So I suggest you try using the alternative functions mt_rand and mt_srand, and try out some other algorithms.

    As an interesting note - according to Zend, in future php.ini will have a setting that by default will set rand() to actually use mt for random number generation.
    http://www.zend.com/zend/week/week51.php#Heading2 It looks like the rand functions are being rewritten ofr PHP 5

  6. #6
    SitePoint Enthusiast
    Join Date
    Jul 2001
    Location
    cheshire
    Posts
    83
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Ok - I'll try the code you use!

    Hi
    I am going to give up on my generator. I have just tried to enter the password for a whole class, I was getting on nicely untill about the 10th pupil and then it started giving me passwords that were already taken.
    If I can't get your version to work I'll let you know.
    Thanks

    BTW - I think I understand the code. This bit:
    mt_rand()%(strlen($chars))

    works out the starting point for the substring - is that correct. The % symbol is for a modular division, so the answer is whats remaining after the division? And the while loop keeps this process adding a character at a time to '$code' until it has 8 characters?

  7. #7
    SitePoint Enthusiast
    Join Date
    Jul 2001
    Location
    cheshire
    Posts
    83
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Fatal error

    I have pasted your code ( one minor alteration of $code to $password) as:

    if ("SUBMIT"==$generate){
    mt_srand( (double)microtime() * 1000000 );
    $chars = "abcdefghijklmnopqrstuvwxyz1234567890";
    $length = 8;
    $password = "";
    while ( strlen($code) < $length ) {
    $password .= substr($chars, mt_rand()%(strlen($chars)), 1);
    }
    print ("Your recommended password isP><BIG>$password</BIG>\n");

    I don't get a parse error but after a delay this pops up

    Fatal error: Maximum execution time of 30 seconds exceeded in /home/p0c79/www/teacher2.php

    What have I done wrong?

  8. #8
    Mlle. Ledoyen silver trophy seanf's Avatar
    Join Date
    Jan 2001
    Location
    UK
    Posts
    7,168
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    The script is taking too long to run so PHP has killed it. There are ways to extend the execution time using set_time_limit() but you should not need to do this for something like this

    Sean
    Harry Potter

    -- You lived inside my world so softly
    -- Protected only by the kindness of your nature

  9. #9
    ********* Callithumpian silver trophy freakysid's Avatar
    Join Date
    Jun 2000
    Location
    Sydney, Australia
    Posts
    3,798
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Infinite loop!

    this:
    while ( strlen($code) < $length ) {

    should be:
    while ( strlen($password) < $length ) {

  10. #10
    SitePoint Enthusiast
    Join Date
    Jul 2001
    Location
    cheshire
    Posts
    83
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Thanks

    Thanks
    Sometimes small changes make big differences - off to try out my new generator.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •