• (cs)

    I call plagiarism! I wrote a password generating function in PHP that was extremely similar to th----

    Er, nothing. I didn't. Just kidding. I'd never write such bad code. Ridiculous, ain't it? Haha...

  • (cs)

    The main problem was that the coder was trying to generate the invalid chars dynamically and as such needed to do all of that testing for valid chars, here's the corrected version:

      function GenPswd($nlen, $usealpha, $usenumeric){
      //  <All of that documentation crap>
    
      //  $disallow = "ILOQZiloqz";
          if ($usealpha){
             $allow = "ABCDEFGHJKMNPRSTUVWXYabcdefghjkmnprstuvwxy";
             if ($usenumeric)
                $allow .= "1234567890";
          } else
             $allow = "1234567890";
    
      // now randomly generate password to specified length
          $maxchr = strlen($allow);
          $pwd = "";
          for (;$nlen;$nlen--)
                  $pwd .= $allow[rand($maxchr)];
          return $pwd;
      }
    
  • Nonymous (unregistered) in reply to Scotty
    Scotty:
    Scotty:
    I think there is a problem here:
          if (!$usenumeric) {
              for ($n=0;$n<10;$n++) {
                  $disallow .= $n;
              }
          }
    

    It prevents me from ever randomly getting my favorite password characters like ^A, ^B, ^C, etc.

    To clarify, should it not have been:

    for ($n=$n0char;$n<=$n9char;$n++) { $disallow .= chr($n); }

    Or does PHP convert the number 0 into the character '0' in the given code? If not, then when digits are not supposed to be allowed, they would still be allowed.

    If it was straight append as "str" .= 0 then it'll convert it to '0', but chr(0) is going to produce a NUL.

  • (cs) in reply to bobday
    bobday:
    I can't believe the amount of people here saying this code "isn't that bad" or "does what it's meant to do." Are you all insane?

    The passwords generated have a 32-bit keyspace! A brute force attack will take no time at all to crack any password generated this way.

    For the love of God, if you looked at the code and didn't think it was deeply, deeply wrong and perverse, stay the hell away from any security-related programming.

    Don't mistake a WTF in the code for a WTF in the spec.

    You are right, a password with only characters and numbers is weak. But that is what the spec asked for (at least we can assume it is, as that is what the documentation claims) Maybe there is a reason for this? Perhaps this code only runs on a computer that has a keypad with only letters and numbers and a shift key? That isn't the point.

  • Nonymous (unregistered) in reply to brendan
    brendan:
    The main problem was that the coder was trying to generate the invalid chars dynamically and as such needed to do all of that testing for valid chars, here's the corrected version:
      function GenPswd($nlen, $usealpha, $usenumeric){
      //  <All of that documentation crap>
    
      //  $disallow = "ILOQZiloqz";
          if ($usealpha){
             $allow = "ABCDEFGHJKMNPRSTUVWXYabcdefghjkmnprstuvwxy";
             if ($usenumeric)
                $allow .= "1234567890";
          } else
             $allow = "1234567890";
    
      // now randomly generate password to specified length
          $maxchr = strlen($allow);
          $pwd = "";
          for (;$nlen;$nlen--)
                  $pwd .= $allow[rand($maxchr)];
          return $pwd;
      }
    

    At least the code in the WTF post worked. Your code is going to generate a whole bunch of "PHP Warning: rand() expects exactly 2 parameters, 1 given" errors and its also going to generate a "PHP Notice: Undefined offset" whenever rand (which is inclusive with the limit), hits highest value.

    Oh the beauty of starting arrays and strings with position 0; see now if they started at 1 errors like this wouldn't happen and you wouldn't need to constantly subtract 1 from the length to get the last char.

    Why again do we start lists at 0 in so many languages?

  • ML (unregistered) in reply to bobday
    bobday:
    The passwords generated have a 32-bit keyspace! A brute force attack will take no time at all to crack any password generated this way.

    For the love of God, if you looked at the code and didn't think it was deeply, deeply wrong and perverse, stay the hell away from any security-related programming.

    WTF are you talking about?

    I don't think you understand what "keyspace" means. The keyspace, FYI, indicates all the possible permutations of a key (the 'key' in this case is the password). Given the length of the 'key' is arbitrary in this code, the keyspace is also arbitrary.

    A 32-bit key, obviously, has a length of 32 binary digits, making the keysize 2^32. Given that this 'key' is actually character data with 52 possible values (uc+lc+digits-disallowed) in each "digit", our key would have a length of $nlen 52ary digits or a keyspace of 52^$nlen.

    Where you came up with "32-bit" is completely beyond me here.

    Given that you obviously have no clue what you are talking about, perhaps you shouldn't be telling others to stay away from security programming.

  • Joe P (unregistered)

    A few Perl quickies, both 59 chars that use a command line issued number:

    $p.=(0..9,'A'..'Z','a'..'z')[62rand]for 1..pop;print$p$/
    and
    map$p.=(0..9,'A'..'Z','a'..'z')[62rand],1..pop;print$p$/
    However I did write a clean version with command line options for numeric/alpha/both(default) with full error detection (incorrect options or length < 1) and fully documented to make it idiot proof. I'd post it here but I know most people hate long code posts (at least I do).

    I decided on a cool approach after I read one of the above comments. Hope you enjoy it, give it a chance, its 61 characters long:

    $=chr 123*rand,/[\da-z]/i?$a.=$:redo for 1..pop;print$a,$/
    I'm happy with these, Joe P

  • Joseph Newton (unregistered) in reply to Bob
    Bob:
    function generatePassword($length, $numeric) { $possibles="abcdefghijkmnopqrstuvwxyz"; // Edit to suit if($numeric) $possibles.="0123456789"; // Edit to suit for($i=0; $i<6; $i++) $password.=substr($possibles, rand()%length($posibles), 1); return $password; }

    ... or something...

    I'll go with something, even the subject code. As obscure as it was, it at least had indentation [Okay, so maybe you don't know about code tags for posting to Web boards] and space between tokens and operators, so I found it worth reading, however clumsy it may have been.

    The space-deficient, geeky crap above is a true WTF.

  • Anon (unregistered) in reply to Nonymous
    Nonymous:
    Why again do we start lists at 0 in so many languages?
    Because, at its core level, an array is simply a memory address. Each element on the array is (elementLength * index) away from the starting address. If they started at 1, every access would have to include a decrement (or you'd be wasting elementLength bytes with every array, or you'd have a pointer that pointed to address - elementLength which would seem to be error-prone).

    The real question is: who creates a random function that takes an inclusive limit? Almost all random functions are exclusive of their maximum value while inclusive of their minimum. The fact that PHP is different makes PHP the odd one out here, and suggests that PHP is confusing in this respect.

    Also, you don't need to subtract one from the length for most uses of the length. The most common use of the length is to check to see if an index is in range. If you start at 0, the check is "index >= 0 && index < length". If you start at 1, the check changes to "index > 0 && index <= length". Given that starting at 0 makes memory management SO much easier, it's really simple to see why 0 is used: it makes the most sense.

    It's not the first element in the list, it's the element 0 units away from the start.

  • Joseph Newton (unregistered) in reply to Unomi
    Unomi:
    Well... have you tried it?

    I did and it works. So what is bad about it? Always here to learn something about bad code.

    • Unomi -

    Well, Unomi, even the subject snippet does provide some context in the way its coded. You can easily tell that it is aimed at three ranges of characters by reading the code, without reliance on any information external to the code. Yours relies on "Magic Numbers" and does not give any context to why they are being invoked. That can be a major problem when the code is part of a much larger system.

    Provide context in your code and your variable and function names. Good programming is more than just plugging in the right numbers to get the job done. It is communication--to others who read your code and to yourself months or years hence.

  • Joseph Newton (unregistered) in reply to Checksum
    Checksum:
    My first post.. and im ready for the slang..
    ...
    		for ($n=65;$n<=90;$n++) {
    ...
    

    doesn't waste loops?

    Hi Checksum,

    I am going to assume, despite your choice of moniker, that you are a human and not a robot that has cracked the Captcha. Bear in mind thatyour code will not be read only by a compiler, but by other humans. there is no shortage of whitespace in our environment--it's very inexpensive, and it bears great fruit in readability.

    Like some other samples posted in comments, you go straight to magic numbers, without providing context. That actually makes your code less portable than the subject code, which uses ord and char as self-commenting cues to its purpose and strategy. Although it may contain some mistakes, it is actually much easier to debug.

  • Joseph Newton (unregistered) in reply to Misha
    Misha:
    Aside from the general yuckyness of the code itself, in my view this kind of randomly generated password actually weakens security. As has been pointed out, no one can remember a password like 1wbZtY9, so it gets written down, stored in a text file or changed to "rosebud". I generally use a couple of random words picked from /usr/dict/words plus a random numeral. This approach is more memorable and occaisionally quite funny. Not very funny, but still sort of funny.

    One will be a zit. Why nine?

    Seems like a perfectly memorable formulation to me.

    Imagination, my boy, imagination. It is what distinguishes humans from beasts.

  • Joseph Newton (unregistered) in reply to Tom Duff
    Tom Duff:
    I think the WTF is that a particular php script is likely to call GenPswd exactly once. If GenPswd is the only thing in the script that calls rand, and if rand's seed is initialized the same for every execution of the script, then it generates the same password every time. (I could be wrong, I don't know any PHP, but on *every* system I've ever used you have to do something special to get rand not to generate the same sequence for every run.)

    Not in PHP:

    results run 1: 4rkKtra1 vB8hjJ1B 1gvgkpxU GFAurtST IYmwhpeg IxvmvnJy 62252I5I 510I4031 79274081

    resuls run 2: cIA2rb85 pM9jIHmk RK5N0h4g ggPTphxX rMWjdUXT YVrDUwtS 86055739 61339112 72117070

    Running precisely the same code.

  • (cs) in reply to Nonymous
    Nonymous:
    At least the code in the WTF post worked. Your code is going to generate a whole bunch of "PHP Warning: rand() expects exactly 2 parameters, 1 given" errors and its also going to generate a "PHP Notice: Undefined offset" whenever rand (which is inclusive with the limit), hits highest value.

    Oh the beauty of starting arrays and strings with position 0; see now if they started at 1 errors like this wouldn't happen and you wouldn't need to constantly subtract 1 from the length to get the last char.

    You are right, that's what I get for not testing it first ( or least not read the documentation). the fix is:

    $pwd .= $allow[rand() % $maxchr];

    As for the subtraction of 1, most uses of random are with the % operator which means that it can never return grater then or equal to its divisor.

    Nonymous:
    Why again do we start lists at 0 in so many languages?

    Anon explains why.

  • (cs) in reply to Jojosh_the_Pi
    Jojosh_the_Pi:
    BlueCollarAstronaut:
    At best, it's inefficient, at worst, it could approach infinite iterations if you happen to run into a streak of bad luck with the randomizer.

    It would have to be extremely bad luck, an extremely long password, or generating a ton of passwords (most likely, this function is being called once in a while). The probability of getting a valid character, even with the most restrictions, is a bit under 1/6. In actual practice, a password will be generated in a negligible amount of time (to human perception). In 100 attempts, the odds of not generating a valid character is around 2.3 x 10^-8 (well, if the numbers were truly random--but you get the idea).

    Of course, this is not to say this function is any good!

    Well the code is non-deterministic. There is no way you can prove to me that this code will end. The only thing you can say is that this code will "most likely" end within a certain number of itterations. This behavior is something you should not have in a function...

    The suggested aproaches about building an array of acceptable characters and then choosing the n-th chracter from that range is deterministic, since it will terminate after picking n acceptable letters.

    To see how bad the performance on this can get, try to implement a shuffle algorithem that shuffels a deck of 110 cards that uses the "flawed" logic ;)

  • SplasPood (unregistered)

    This is by far the best password generation code I've ever seen... some strings changed to protect the guilty..

    $rnd = substr(str_replace(array(""",";"," ",",","
    ","/","=","-","_","(",")",".","?",">","<","","'","%","$","#","@","!","*","&","^ ","+","{","}","[","]",":","\n","\r",""),"",str_shuffle(cat /home/baddev/www/reseller/*.php`)),0,10);

  • (cs) in reply to rdrunner
    rdrunner:
    Jojosh_the_Pi:
    BlueCollarAstronaut:
    At best, it's inefficient, at worst, it could approach infinite iterations if you happen to run into a streak of bad luck with the randomizer.

    It would have to be extremely bad luck, an extremely long password, or generating a ton of passwords (most likely, this function is being called once in a while). The probability of getting a valid character, even with the most restrictions, is a bit under 1/6. In actual practice, a password will be generated in a negligible amount of time (to human perception). In 100 attempts, the odds of not generating a valid character is around 2.3 x 10^-8 (well, if the numbers were truly random--but you get the idea).

    Of course, this is not to say this function is any good!

    Well the code is non-deterministic. There is no way you can prove to me that this code will end. The only thing you can say is that this code will "most likely" end within a certain number of itterations. This behavior is something you should not have in a function...

    The suggested aproaches about building an array of acceptable characters and then choosing the n-th chracter from that range is deterministic, since it will terminate after picking n acceptable letters.

    To see how bad the performance on this can get, try to implement a shuffle algorithem that shuffels a deck of 110 cards that uses the "flawed" logic ;)

    Apples and oranges, chief. To randomly shuffle a deck of 110 cards into the correct order on any given attempt is extremely unlikely: 1/(110!), meaning (110! - 1)/(110!) odds of having to try again, whereas in this algorithm, the chances of picking a bad character (given both alphas and numbers) is something like 23/75. That ain't great, but it approaches zero far faster than the shuffle algorithm as to make the comparison immensely unfair. For example, consider the following deterministic algorithm: Create every possibly permutation of the 110 card deck. Then, starting at the first one, go through each one until you find the permutation in the correct order. Hey, that's a terrible algorithm! Deterministic algorithms must be worthless, too! Still, I agree that a white list is the better option in this case. I just hate bad analogies.

  • brong (unregistered) in reply to rbowes
    rbowes:
    trav:
    Everybody knows that the most commonly used passwords are love, sex, secret, and god.
    Damnit, you stole my post! :P

    That wasn't trav, it was you logging in as trav using one of the above passwords. Hax0r.

  • Arthur (unregistered) in reply to Unomi

    Unomi: Do you work for Microsoft? I find your code far more complicated than it needs to be.

    Take a look at Bob's code (post 125872), except for 2 minor errors it is pure poetry.

  • (cs) in reply to Arthur
    Arthur:
    Unomi: Do you work for Microsoft? I find your code far more complicated than it needs to be.

    Take a look at Bob's code (post 125872), except for 2 minor errors it is pure poetry.

    Although I do have to agree with you that Unomi's code is a WTF, but

    At least Unomi's code conformed more to the function specifications than Bob's code. A working, poorly implemented program is better than a non working program.

    Problems with Bob's code

    • Does not take same amount of params.
    • because of the above one can not generate only numeric passwords
    • Does not generate uppercase chars.
    • recalculates length of possible values each iteration
    • does not generate specified length passwords
    • producing extra overhead each iteration with substr

    Both of them didn't remove any of "ILOQZiloqz"

    To be fair:

    Problems with Unomi's code

    • Use of magic values
    • incorrect naming of variables
    • using variables before there initialized.
    • inefficient use of if statements,
    • could of used a case statement.
  • 57451 (swedish) (unregistered) in reply to ASDF
    ASDF:
    Coded by a Swede. Maxord and minord mean "max word" and "min word", Ord obviously meaning word.

    But then Dimitiy doesn't sound Swedish at all.

    Or, ord is abbrev:ed "ordinal"?

  • Me (unregistered)

    Stupid code, the quickest and easiest code is to make a string of all valid characters. If the length is zero then doh!!, abort. Then use the random number to generate an index into that string and append characers to the password until you have generated the right number of characters.

  • jfw (unregistered) in reply to Jonathan
    Jonathan:
    bobday:
    I can't believe the amount of people here saying this code "isn't that bad" or "does what it's meant to do." Are you all insane?

    The passwords generated have a 32-bit keyspace! A brute force attack will take no time at all to crack any password generated this way.

    First of all, how do you get 32-bit keyspace?

    There are 62 individual characters (assuming alphanumeric), 26 lower case, 26 uppercase, and 10 numbers.

    The character space of the generated passwords has nothing to do with it. He's correct, except that it's a bit worse than he suggests. Unless it's not.

    The problem is primarily the srand() function, and secondarily the rand() function. The PHP documentation does not specify the algorithm to be used by the PHP rand() function, but does say that the libc rand() function is usually used. ANSI C does not specify the internals of the libc rand() function, either, but traditionally the libc rand() function is a particular well-known 32-bit linear congruential generator, which is seeded by calling srand(), which accepts one (1) 32-bit integer. So: the traditional random number generator starts with at most 32 bits worth of state, and therefore has only 4 billion starting points, being completely predictable from the starting point onward. Therefore, a password generator utilizing rand() can generate at most 4 billion unique passwords. A password generator which does what this one does, calling rand() and throwing away values it doesn't like, generates far fewer unique passwords, because if the initial seed is a value which will be thrown away, rand() will be called repeatedly until an acceptable value crops up, effectively making several initial values of rand() map to the same generated password.

    PHP also offers a different random number generator through the mt_rand() interface, but mt_srand() also only takes a single 32-bit integer as a seed. Unless the default initialization the PHP system offers uses a different interface and jams in a larger seed, there are only 4 billion sequences that calls to mt_rand() will return. (Because mt_rand() has more than 32 bits of internal state and a fabulously long cycle time, it is possible that those 4 billion unique sequences do not generally overlap, which is not the case with the standard rand() function.)

    Except for the possibility that some PHP installer might substitute a worthwhile rand() function (while stubbing out srand()), every possible password this function might generate can probably be enumerated in a matter of hours and written to a somewhat large text file. The only saving grace is that those generated passwords are roughly equiprobable (not quite true due to the collision problem mentioned above), and brute-force testing them over the web would take a long time (since the response time is going to be milliseconds to hundreds of milliseconds, not a couple of microseconds).

    John von Neumann:
    Anyone who attempts to generate random numbers by deterministic means is, of course, living in a state of sin.
  • ma.u (unregistered)

    I think use php code AS password is the best Bye

  • DOA (unregistered)

    At least it has decent comments, which is more than I can say about most code out there

    captcha: noone gives a rat's ass

  • brendan (unregistered) in reply to jfw
    jfw:
    The problem is primarily the srand() function, and secondarily the rand() function. The PHP documentation does not specify the algorithm to be used by the PHP rand() function, but does say that the libc rand() function is usually used. ANSI C does not specify the internals of the libc rand() function, either, but traditionally the libc rand() function is a particular well-known 32-bit linear congruential generator, which is seeded by calling srand(), which accepts one (1) 32-bit integer. So: the traditional random number generator starts with at most 32 bits worth of state, and therefore has only 4 billion starting points, being completely predictable from the starting point onward. Therefore, a password generator utilizing rand() can generate at most 4 billion unique passwords. A password generator which does what this one does, calling rand() and throwing away values it doesn't like, generates far fewer unique passwords, because if the initial seed is a value which will be thrown away, rand() will be called repeatedly until an acceptable value crops up, effectively making several initial values of rand() map to the same generated password.

    After reading the php source code (ah the power of open source). it seems to me that depending on what your system supports, it uses the best one (the following is based off the FreeBSD man pages).

    the random() libc function has a period of >2^69 (256-bytes of state information)

    the lrand48() libc function has a max period of 2^48.

    and the rand() libc function has a max period of 2^31.

    jfw:

    PHP also offers a different random number generator through the mt_rand() interface, but mt_srand() also only takes a single 32-bit integer as a seed. Unless the default initialization the PHP system offers uses a different interface and jams in a larger seed, there are only 4 billion sequences that calls to mt_rand() will return. (Because mt_rand() has more than 32 bits of internal state and a fabulously long cycle time, it is possible that those 4 billion unique sequences do not generally overlap, which is not the case with the standard rand() function.)

    the mt_rand() function has a period of 2^19937-1 according to it's documentation, note I'm not a expert at this topic.

  • This is nothing... really... (unregistered) in reply to Nonymous
    Why again do we start lists at 0 in so many languages?

    It's fundamental computer science. As fundamental as 1+1=2... as fundamental as the Peno Postulates.

    There is some disagreement: http://lambda-the-ultimate.org/node/1950

    But, in general the index is the array offset in memory. If an integer consumes 'm' memory elements and you have an array of integers in memory as such:

     x = [a,b,c,d,e,f,g,h,i,j]
    

    where each letter holds an arbitrary integer. Now then, to address the integer a position p you would take the position p multiply it by the consumption of 'm' and add that to the position of x in memory.

    So to get the cell 'c' you would: cPointer = addressOf(x) + (2 * m); to get pointer to 'a' you would: aPointer = addressOf(x) + (0 * m);

    And if your indexes started with 1 you would have to subtract 1 from the index at all times to perform this arithmetic. So by using indexes starting at zero I can see the offset of the element from the head of the array. It was a great epiphany for me to see that clearly. Indexes are not the same as first, second, third.

    It also becomes important in using arrays to model 3D systems since the origin point is at 0,0,0 and not at 1,1,1. Many summation series are written to refer to i=0 to some number. Look at: http://en.wikipedia.org/wiki/Taylor_series

    For non-arithmetic uses of arrays many languages provide container classes. If you plan on using elements in an array without caring too much about their precise indexes simply don't use the simple array construct, us a container class such as a list, set, or hashMap and get an iterator.

    If this is too much math for you just remember it's called a computer for a reason.

  • martin (unregistered) in reply to SplasPood
    SplasPood:
    This is by far the *best* password generation code I've ever seen... some strings changed to protect the guilty..

    $rnd = substr(str_replace(array(""",";"," ",",","
    ","/","=","-","_","(",")",".","?",">","<","","'","%","$","#","@","!","*","&","^ ","+","{","}","[","]",":","\n","\r",""),"",str_shuffle(cat /home/baddev/www/reseller/*.php`)),0,10);

    you mispelled bestest

    very nice code tho if reseller directory indeed exists and is full of php files, if you'd rotate them after generation as well ... would be random, wouldn't it ? :D

  • (cs) in reply to Jonathan
    Jonathan:
    First of all, how do you get 32-bit keyspace?
    Random seed.

    And that's just the first attack I could think of. Based on the left-out letters and the fact that PHP's RAND_MAX is 2^15-1 on Windows, I'm sure there are more creative attacks that can be implemented.

  • (cs) in reply to ML
    ML:
    Where you came up with "32-bit" is completely beyond me here.
    That is exactly why I'm asking you to stay away from security programming.
  • (cs) in reply to trav

    "Don't forget 'god', system administrators love to use 'god', it's that whole male ego thing!"

  • S (unregistered) in reply to Jojosh_the_Pi
    Jojosh_the_Pi:
    The problem's with the check !strpos($disallow, chr($n)), which was supposed to disallow any of the illegal characters. strpos returns false (that is, 0) if the search string is not found, but it can also return 0 if the search string is at position 0. So, if the character "I" is chosen randomly, since it's the first char in the disallow string, will pass the strpos test.

    Programmer should have used the === comparison to check for boolean false. Besides that, the function seems to work as expected. Not the grandest WTF ever.

    This is one of the major f**k-ups in PHP. Why not return -1 when it isn't found? This would make the function a lot better. It's like having a function like "object TestSomething(string s)" in Java or C# and the programmer has to check what type the returned object is. Not nice. But then again, PHP is filled with crap like this.

  • (cs)

    This whole nonsense reminds me of the password generator they are using at my university. It simply takes a random 40-bits number and sprintf("%X")s it. I guess they were all happy because it contains numbers AND letters, so it must be good. Too bad that it actually has a fixed short lenght, and contains only 16 possible characters. Yay security.

  • Nick Presta (unregistered)

    This is what I would use to generate a password similar to this WTF...

    function genPass($length, $upperLower = true, $symbols = true) {
      $password = hash("sha512", uniqid(time()));
      # Make sure the password is long enough.
      while (strlen($password) < $length) {
        $password .= hash("sha512", uniqid(time()));
      }
      if ($upperLower == true) {
        # This will convert every other letter to uppercase/lowercase.
        for ($i = 0; $i < strlen($password); $i++) {
          $password{$i} = ($i % 2 ? strtoupper($password{$i}) : strtolower($password{$i}));
        }
      }
      if ($symbols == true) {
        # Set special modifiers to replace with symbols.
        $search = array("a", "b", "c", "d", "e");
        $replace = array("@", ">", "<", "\\", "#");
        # This will convert specific characters to symbols.
        for ($f = 0; $f < strlen($password); $f++) {
          $password{$f} = ($f % 2 ? str_ireplace($search, $replace, $password{$f}) : str_replace($search, $replace, $password{$f}));
        }
      }
      return substr($password, 0, $length);
    }
    

    I think it works pretty well.

  • GrouchyAdmin (unregistered)

    This is something I did on my second day of learning PHP:

    function genPrefix ($num=5) { $letters = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', ); $code = ""; for ($i = 0; $i < $num; $i++) { $code .= $letters[mt_rand(0, count($letters))]; } return $code; }

    I pray that it's gone from everywhere. I have no idea what the hell I was thinking. Sure, abusing the ASCII numerics would work, but what if I ported it to EBCDI...yeah....

  • GrouchyAdmin (unregistered) in reply to Nick Presta
    Nick Presta:
    $password{$f} = ($f % 2 ? str_ireplace($search, $replace, $password{$f}) : str_replace($search, $replace, $password{$f}));

    I think it works pretty well.

    That's damn awful, and you know it. Jesus. I mean, PHP is not an optimized language, truly, but COME ON! Even my retarded table lookup was faster.

    ..not that it wasn't retarded. ;)

  • jim258kelly (unregistered) in reply to wilkeson

    Welcome to the world of DOD Classified networks.

  • Arfer (unregistered) in reply to Tom Duff
    Tom Duff:
    "Note: As of PHP 4.2.0, there is no need to seed the random number generator with srand() or mt_srand() as this is now done automatically."

    Mmm. A built-in source of non-reproducability -- one of my favorites. That's gonna make debugging fun.

    Presumably you still can use a seed (for reproducability {is that a word}), but if you don't use a seed, the generatot will use a semi-random seed (eg timestamp + pid)

  • Sebastian Ramadan (unregistered) in reply to GeneWitch
    i have a java program that tries to make random words, then match them against a dictionary that has been loaded into a hash table.

    You're TRWTF. Use a trie.

  • Sebastian Ramadan (unregistered) in reply to Ann Coulter

    In that case, aren't you suggesting that TRWTF is using passwords for the average blog or forum?

  • Sebastian Ramadan (unregistered) in reply to Joseph Newton
    it does provide pretty random passwords per spec

    You're confused about the word "random".

  • Sebastian Ramadan (unregistered) in reply to jfw
    jfw:
    Jonathan:
    bobday:
    I can't believe the amount of people here saying this code "isn't that bad" or "does what it's meant to do." Are you all insane?

    The passwords generated have a 32-bit keyspace! A brute force attack will take no time at all to crack any password generated this way.

    First of all, how do you get 32-bit keyspace?

    There are 62 individual characters (assuming alphanumeric), 26 lower case, 26 uppercase, and 10 numbers.

    The character space of the generated passwords has nothing to do with it. He's correct, except that it's a bit worse than he suggests. Unless it's not.

    The problem is primarily the srand() function, and secondarily the rand() function. The PHP documentation does not specify the algorithm to be used by the PHP rand() function, but does say that the libc rand() function is usually used. ANSI C does not specify the internals of the libc rand() function, either, but traditionally the libc rand() function is a particular well-known 32-bit linear congruential generator, which is seeded by calling srand(), which accepts one (1) 32-bit integer. So: the traditional random number generator starts with at most 32 bits worth of state, and therefore has only 4 billion starting points, being completely predictable from the starting point onward. Therefore, a password generator utilizing rand() can generate at most 4 billion unique passwords. A password generator which does what this one does, calling rand() and throwing away values it doesn't like, generates far fewer unique passwords, because if the initial seed is a value which will be thrown away, rand() will be called repeatedly until an acceptable value crops up, effectively making several initial values of rand() map to the same generated password.

    PHP also offers a different random number generator through the mt_rand() interface, but mt_srand() also only takes a single 32-bit integer as a seed. Unless the default initialization the PHP system offers uses a different interface and jams in a larger seed, there are only 4 billion sequences that calls to mt_rand() will return. (Because mt_rand() has more than 32 bits of internal state and a fabulously long cycle time, it is possible that those 4 billion unique sequences do not generally overlap, which is not the case with the standard rand() function.)

    Except for the possibility that some PHP installer might substitute a worthwhile rand() function (while stubbing out srand()), every possible password this function might generate can probably be enumerated in a matter of hours and written to a somewhat large text file. The only saving grace is that those generated passwords are roughly equiprobable (not quite true due to the collision problem mentioned above), and brute-force testing them over the web would take a long time (since the response time is going to be milliseconds to hundreds of milliseconds, not a couple of microseconds).

    John von Neumann:
    Anyone who attempts to generate random numbers by deterministic means is, of course, living in a state of sin.

    Precisely. The passwords generated by this algorithm may as well be a randomised integer between PHP_INT_MIN and PHP_INT_MAX.

    As an example, suppose I wanted to bruteforce a password generated by this algorithm. I could start with a seed of INT_MIN, use the same GenPswd function to generate and test corresponding passwords, iterate the seed, and repeat until I reach a correct password or a seed equal to PHP_INT_MAX.

    The example doesn't just stop there. Once I find a correct password by guessing the seed, the odds are that PHP will predictably mutate the seed correctly for me. I can go forward in O(1) constant time and determine what the next password generated will likely be.

Leave a comment on “Generating Secure P455w0rd5”

Log In or post as a guest

Replying to comment #:

« Return to Article