what I'm wanting is to convert an integer into a string. For example, 123456789 may become 8GFsah93r ... you know like Youtube, Pastebin and what not. I then want to convert it back.
I'm working with large integers, for example: 131569877435989900
Take a look at this link: http://codepad.viper-7.com/wHKOMi
This is my attempt using a function I found on the web, obviously... it's not correctly converting back to integer. I'm needing something that does this realiably.
Thanks
Ok, one of the ideas is to use a character array as a representation of a numeric system. Then you can convert from base 10 to base x and vica-versa. The value will be shorter and less readable (altought, you should encrypt it with a two-way crypter if it must be secure).
A solution:
final class UrlShortener {
private static $charfeed = Array(
'a','A','b','B','c','C','d','D','e','E','f','F','g','G','h','H','i','I','j','J','k','K','l','L','m',
'M','n','N','o','O','p','P','q','Q','r','R','s','S','t','T','u','U','v','V','w','W','x','X','y','Y',
'z','Z','0','1','2','3','4','5','6','7','8','9');
public static function intToShort($number) {
$need = count(self::$charfeed);
$s = '';
do {
$s .= self::$charfeed[$number%$need];
$number = floor($number/$need);
} while($number > 0);
return $s;
}
public static function shortToInt($string) {
$num = 0;
$need = count(self::$charfeed);
$length = strlen($string);
for($x = 0; $x < $length; $x++) {
$key = array_search($string[$x], self::$charfeed);
$value = $key * pow($need, $x);
$num += $value;
}
return $num;
}
}
Then you can use:
UrlShortener::intToShort(2);
UrlShortener::shortToInt("b");
EDIT
with large numbers, it does not work. You should use this version (with bcmath http://www.php.net/manual/en/book.bc.php ) with very large numbers:
final class UrlShortener {
private static $charfeed = Array(
'a','A','b','B','c','C','d','D','e','E','f','F','g','G','h','H','i','I','j','J','k','K','l','L','m',
'M','n','N','o','O','p','P','q','Q','r','R','s','S','t','T','u','U','v','V','w','W','x','X','y','Y',
'z','Z','0','1','2','3','4','5','6','7','8','9');
public static function intToShort($number) {
$need = count(self::$charfeed);
$s = '';
do {
$s .= self::$charfeed[bcmod($number, $need)];
$number = floor($number/$need);
} while($number > 0);
return $s;
}
public static function shortToInt($string) {
$num = 0;
$need = count(self::$charfeed);
$length = strlen($string);
for($x = 0; $x < $length; $x++) {
$key = array_search($string[$x], self::$charfeed);
$value = $key * bcpow($need, $x);
$num += $value;
}
return $num;
}
}
$original = 131569877435989900;
$short = UrlShortener::intToShort($original);
echo $short;
echo '<br/>';
$result = UrlShortener::shortToInt($short);
echo $result;
echo '<br/>';
echo bccomp($original, $result);
If something missing from here, please let me know, because it's only a snippet from my library (I don't wanna insert the whole thing here)
negra
check base64 encoding: http://php.net/manual/en/function.base64-encode.php http://php.net/manual/en/function.base64-decode.php
If you want a shorter string first encode it into an 8bit string then encode. You can do this with % 256 and / 256.
Or you could manually do what base64 does, get the first 6bits and encode it to a char.
Why not use something like this? Do you need it heavily encrypted?
$num = 131569877435989900;
echo $str = base64_encode($num);
echo base64_decode($str);
I think what you want is to encode the ids using Base32. The resulting string contains only the 26 letters of the alphabet and the digits 2-7, making it very human readable.
The simplest would be to use something like base_convert -- unfortunately, it won't work for such large integers correctly.
However, you can use the same idea by copying base_convert_arbitrary from my answer here and doing:
$id = '131569877435989900';
$encoded = base_convert_arbitrary($id, 10, 36);
$decoded = base_convert_arbitrary($encoded, 36, 10);
print_r($encoded);
print_r($decoded);
See it in action.
The nice thing about this approach is that you can tweak the first line inside the function, which reads:
$digits = '0123456789abcdefghijklmnopqrstuvwxyz'; // 36 "digits"
Add any other "digits" you find acceptable (e.g. capital letters or other symbols you don't mind having in your URL). You can then replace the base 36 in the above example with a larger one (you can go as high as there are defined digits), and it will work just like you want it to.
See it here working with 62 digits.
I am suprised No one is mentioning base64_encode() and it partner base64_decode().
If you were not considering length this is perfect
$before = base64_encode(131569877435989900);
$after = 'MS4zMTU2OTg3NzQzNTk5RSsxNw==';
$on_reverse = base64_decode('MS4zMTU2OTg3NzQzNTk5RSsxNw==');
$on_reverse == 131569877435989900;
I always go for the simplest solutions, as long as they don't compromise my security.
The easiest way to get random string is to use hash functions like md5() or sha1() For example:
<?php
$bigInt = '131569877435989900';
$hash = md5($bigInt);
$hashed=substr($hash,0,-20);
echo $hashed;
?>
These hash functions are irreversible-you can't get the original value(these functions are also used to crypt data). If you want you can save the original big integer in an array or a database. But decripting the hash would be impossible.
Related
I need to be able to turn a string into its binary parts. Say I have the string:
"R!Testing"
I want a function to return the respective binary:
"010100100010000101010100011001010111001101110100011010010110111001100111"
and also have another function to also turn that binary in the string "R!Testing" for example. Currently I am using the following.
function messageToBinary($message) {
$value = unpack('H*', $message);
return base_convert($value[1], 16, 2);
}
// Turn string of bits into its text equivalent
function binaryToMessage($binary) {
return pack('H*', base_convert($binary, 2, 16));
}
This of course has several issues I believe. Some characters fail (I think because 16 is the max?) to convert properly and also base_convert sometimes fails with large strings due to overflow issues.
What is a better approach?
Do it in a loop instead of trying to treat the whole thing as one big number. ord() returns the character code of a character, and sprintf() can be used to convert that to a fixed-length binary number.
function messageToBinary($message) {
$len = strlen($message);
$result = '';
for ($i = 0; $i < $len; $i++) {
$result .= sprintf("%08b", ord($message[$i]));
}
return $result;
}
To go the other way, extract 8-bit segments of the string, convert them from binary to decimal, then use chr() to convert that to a character.
function binaryToMessage($binary) {
$len = strlen($binary);
$result = '';
for ($i = 0; $i < $len; $i += 8) {
$n = substr($binary, $i, 8);
$result .= chr(bindec($n));
}
return $result;
}
Note that this only works for 8-bit characters. For Unicode, you'll need to get more complex.
I am looking for the shortest way to generate random/unique strings and for that I was using the following two:
$cClass = sha1(time());
or
$cClass = md5(time());
However, I need the string to begin with a letter, I was looking at base64 encoding but that adds == at the end and then I would need to get rid of that.
What would be the best way to achieve this with one line of code?
Update:
PRNDL came up with a good suggestions which I ended up using it but a bit modified
echo substr(str_shuffle(abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ),0, 1) . substr(str_shuffle(aBcEeFgHiJkLmNoPqRstUvWxYz0123456789),0, 31)
Would yield 32 characters mimicking the md5 hash but it would always product the first char an alphabet letter, like so;
However, Uours really improved upon and his answer;
substr(str_shuffle("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), 0, 1).substr(md5(time()),1);
is shorter and sweeter
The other suggestion by Anonymous2011 was very awesome but the first character for some reason would always either M, N, Y, Z so didn't fit my purposes but would have been the chosen answer, by the way does anyone know why it would always yield those particular letters?
Here is the preview of my modified version
echo rtrim(base64_encode(md5(microtime())),"=");
Rather than shuffling the alphabet string , it is quicker to get a single random char .
Get a single random char from the string and then append the md5( time( ) ) to it . Before appending md5( time( ) ) remove one char from it so as to keep the resulting string length to 32 chars :
substr("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ", mt_rand(0, 51), 1).substr(md5(time()), 1);
Lowercase version :
substr("abcdefghijklmnopqrstuvwxyz", mt_rand(0, 25), 1).substr(md5(time()), 1);
Or even shorter and a tiny bit faster lowercase version :
chr(mt_rand(97, 122)).substr(md5(time()), 1);
/* or */
chr(mt_rand(ord('a'), ord('z'))).substr(md5(time()), 1);
A note to anyone trying to generate many random strings within a second: Since time( ) returns time in seconds , md5( time( ) ) will be same throughout a given second-of-time due to which if many random strings were generated within a second-of-time, those probably could end up having some duplicates .
I have tested using below code . This tests lower case version :
$num_of_tests = 100000;
$correct = $incorrect = 0;
for( $i = 0; $i < $num_of_tests; $i++ )
{
$rand_str = substr( "abcdefghijklmnopqrstuvwxyz" ,mt_rand( 0 ,25 ) ,1 ) .substr( md5( time( ) ) ,1 );
$first_char_of_rand_str = substr( $rand_str ,0 ,1 );
if( ord( $first_char_of_rand_str ) < ord( 'a' ) or ord( $first_char_of_rand_str ) > ord( 'z' ) )
{
$incorrect++;
echo $rand_str ,'<br>';
}
else
{
$correct++;
}
}
echo 'Correct: ' ,$correct ,' . Incorrect: ' ,$incorrect ,' . Total: ' ,( $correct + $incorrect );
I had found something like this:
$length = 10;
$randomString = substr(str_shuffle(md5(time())),0,$length);
echo $randomString;
If you need it to start with a letter, you could do this. It's messy... but it's one line.
$randomString = substr(str_shuffle("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), 0, 1) . substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), 0, 10);
echo $randomString;
I decided this question needs a better answer. Like code golf! This also uses a better random byte generator.
preg_replace("/[\/=+]/", "", base64_encode(openssl_random_pseudo_bytes(8)));
Increase the number of bytes for a longer password, obviously.
Creates a 200 char long hexdec string:
$string = bin2hex(openssl_random_pseudo_bytes(100));
maaarghk's answer is better though.
base_convert(microtime(true), 10, 36);
You can try this:
function KeyGenerator($uid) {
$tmp = '';
for($z=0;$z<5;$z++) {
$tmp .= chr(rand(97,122)) . rand(0,100);
}
$tmp .= $uid;
return $tmp;
}
I have generated this code for you. Simple, short and (resonably) elegant.
This uses the base64 as you mentioned, if length is not important to you - However it removes the "==" using str_replace.
<?php
echo str_ireplace("==", "", base64_encode(time()));
?>
I use this function
usage:
echo randomString(20, TRUE, TRUE, FALSE);
/**
* Generate Random String
* #param Int Length of string(50)
* #param Bool Upper Case(True,False)
* #param Bool Numbers(True,False)
* #param Bool Special Chars(True,False)
* #return String Random String
*/
function randomString($length, $uc, $n, $sc) {
$rstr='';
$source = 'abcdefghijklmnopqrstuvwxyz';
if ($uc)
$source .= 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
if ($n)
$source .= '1234567890';
if ($sc)
$source .= '|##~$%()=^*+[]{}-_';
if ($length > 0) {
$rstr = "";
$length1= $length-1;
$input=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')
$rand = array_rand($input, 1)
$source = str_split($source, 1);
for ($i = 1; $i <= $length1; $i++) {
$num = mt_rand(1, count($source));
$rstr1 .= $source[$num - 1];
$rstr = "{$rand}{$rstr1}";
}
}
return $rstr;
}
I'm using this one to generate dozens of unique strings in a single go, without repeating them, based on other good examples above:
$string = chr(mt_rand(97, 122))
. substr(md5(str_shuffle(time() . rand(0, 999999))), 1);
This way, I was able to generate 1.000.000 unique strings in ~5 seconds. It's not THAT fast, I know, but as I just need a handful of them, I'm ok with it. By the way, generating 10 strings took less than 0.0001 ms.
JavaScript Solution:
function randomString(pIntLenght) {
var strChars = “0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz”;
var strRandomstring = ”;
for (var intCounterForLoop=0; intCounterForLoop < pIntLenght; intCounterForLoop++) {
var rnum = Math.floor(Math.random() * strChars.length);
strRandomstring += strChars.substring(rnum,rnum+1);
}
return strRandomstring;
}
alert(randomString(20));
Reference URL : Generate random string using JavaScript
PHP Solution:
function getRandomString($pIntLength = 30) {
$strAlphaNumericString = ’0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ’;
$strReturnString = ”;
for ($intCounter = 0; $intCounter < $pIntLength; $intCounter++) {
$strReturnString .= $strAlphaNumericString[rand(0, strlen($strAlphaNumericString) - 1)];
}
return $strReturnString;
}
echo getRandomString(20);
Reference URL : Generate random String using PHP
This function returns random lowercase string:
function randomstring($len=10){
$randstr='';
for($iii=1; $iii<=$len; $iii++){$randstr.=chr(rand(97,122));};
return($randstr);
};
I find that base64 encoding is useful for creating random strings, and use this line:
base64_encode(openssl_random_pseudo_bytes(9));
It gives me a random string of 12 positions, with the additional benefit that the randomness is "cryptographically strong".
to generate strings consists of random characters, you can use this function
public function generate_random_name_for_file($length=50){
$key = '';
$keys = array_merge(range(0, 9), range('a', 'z'));
for ($i = 0; $i < $length; $i++) {
$key .= $keys[array_rand($keys)];
}
return $key;
}
It really depends on your requirements.
I needed strings to be unique between test runs, but not many other restrictions.
I also needed my string to start with a character, and this was good enough for my purpose.
$mystring = "/a" . microtime(true);
Example output:
a1511953584.0997
How to match the OPs original request in an awful way (expanded for readability):
// [0-9] ASCII DEC 48-57
// [A-Z] ASCII DEC 65-90
// [a-z] ASCII DEC 97-122
// Generate: [A-Za-z][0-9A-Za-z]
$r = implode("", array_merge(array_map(function($a)
{
$a = [rand(65, 90), rand(97, 122)];
return chr($a[array_rand($a)]);
}, array_fill(0, 1, '.')),
array_map(function($a)
{
$a = [rand(48, 57), rand(65, 90), rand(97, 122)];
return chr($a[array_rand($a)]);
}, array_fill(0, 7, '.'))));
One the last array_fill() would would change the '7' to your length - 1.
For one that does all alpha-nurmeric (And still slow):
// [0-9A-Za-z]
$x = implode("", array_map(function($a)
{
$a = [rand(48, 57), rand(65, 90), rand(97, 122)];
return chr($a[array_rand($a)]);
}, array_fill(0, 8, '.')));
The following one-liner meets the requirements in your question: notably, it begins with a letter.
substr("abcdefghijklmnop",random_int(0, 16),1) . bin2hex(random_bytes(15))
If you didn't care whether the string begins with a letter, you could just use:
bin2hex(random_bytes(16))
Note that here we use random_bytes and random_int, which were introduced in PHP 7 and use cryptographic random generators, something that is important if you want unique strings to be hard to guess. Many other solutions, including those involving time(), microtime(), uniqid(), rand(), mt_rand(), str_shuffle(), array_rand(), and shuffle(), are much more predictable and are unsuitable if the random string will serve as a password, a bearer credential, a nonce, a session identifier, a "verification code" or "confirmation code", or another secret value.
I also list other things to keep in mind when generating unique identifiers, especially random ones.
True one liner random string options:
implode('', array_rand(array_flip(str_split(str_shuffle('abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ'))), 21));
md5(microtime() . implode('', array_rand(array_flip(str_split(str_shuffle('abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ'))), 21)));
sha1(microtime() . implode('', array_rand(array_flip(str_split(str_shuffle('abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ'))), 21)));
I have written a generator of strings, but I don't know how to create a random hex string with length, for instance 100 digits, for inserting into a database. All these strings have to be same length.
How can I generate random hex strings?
As of PHP 5.3 with OpenSSL extension:
function getRandomHex($num_bytes=4) {
return bin2hex(openssl_random_pseudo_bytes($num_bytes));
}
For your example of 100 digits:
$str = getRandomHex(50);
While this answers OP's question, if what you are looking for is random, then #danorton answer may be a better fit.
Like this:
$val = '';
for( $i=0; $i<100; $i++ ) {
$val .= chr(rand(65, 90));
}
65 is A while 90 is Z. if you do not like "magic numbers" this form may be more readable:
$val = '';
for( $i=0; $i<100; $i++ ) {
$val .= chr(rand(ord('A'), ord('Z')));
}
I'd make ord() result a variable and move it out of the loop though for performance reasons:
$A = ord('A');
$Z = ord('Z');
$val = '';
for( $i=0; $i<100; $i++ ) {
$val .= chr(rand($A, $Z));
}
Or you could glue output of sha1()s (three of them) and cut down to 100 chars. Or use md5() instead (but I'd stick to sha1()).
EDIT sha1() outputs 40 chars long string, md5() 32 chars long. So if you do not want to glue char by char (as in loop I gave above) try this function
function getId($val_length) {
$result = '';
$module_length = 40; // we use sha1, so module is 40 chars
$steps = round(($val_length/$module_length) + 0.5);
for( $i=0; $i<$steps; $i++ ) {
$result .= sha1(uniqid() . md5(rand());
}
return substr($result, 0, $val_length);
}
where function argument is length of string to be returned. Call it getId(100);
$randHexStr = implode( array_map( function() { return dechex( mt_rand( 0, 15 ) ); }, array_fill( 0, $strlen, null ) ) );
where $strlen is length of random hex string.
From php7 on you should use the function random_bytes:
function getRandomHex($num_bytes=4) {
return bin2hex(random_bytes($num_bytes));
}
liner technique to do so, but its bit complicated and hard-coded in-terms of length of string.
$rand4 = substr(sha1(rand(0,getrandmax())),rand(0,24),16);
in which you need to change the last varibale of function (which i set to 16) if you want to change the length of output string and one more thing there is one rand(0,24) in which number 24 will change according to third variable, it should not be more then 40-thirdvariable...
I like to a have single general function that can handle similar situations. By that I mean a function which receives both the requried length of the generated string and the possible characters that can occure in it.
That way a single function can create: 40-digit decimal number, 16-digit uppercase hex number, 100 letter lowercase string, etc...
Here is my implementation:
/**
* Generate a random string.
*
* #param int $length Length of the generated string.
* #param string $chars The string containing all of the available characters.
*
* #return string The generated string.
*/
function getRandomString($length = 10, $chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789') {
$str = '';
$size = strlen($chars);
for ($i = 0; $i < $length; $i++) {
$str .= $chars[mt_rand(0, $size - 1)];
}
return $str;
}
IMPORTANT: Do not use this function to generate random string for any security purpose. For a secure string generator check out the answer from #danorton.
For an ecommerce site I want to generate a random coupon code that looks better than a randomly generated value. It should be a readable coupon code, all in uppercase with no special characters, only letters (A-Z) and numbers (0-9).
Since people might be reading this out / printing it elsewhere, we need to make this a simple-to-communicate value as well, perhaps 8-10 characters long.
Something like perhaps,
AHS3DJ6BW
B83JS1HSK
(I typed that, so it's not really that random)
$chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
$res = "";
for ($i = 0; $i < 10; $i++) {
$res .= $chars[mt_rand(0, strlen($chars)-1)];
}
You can optimize this by preallocating the $res string and caching the result of strlen($chars)-1. This is left as an exercise to the reader, since probably you won't be generating thousands of coupons per second.
Try this:
substr(base_convert(sha1(uniqid(mt_rand())), 16, 36), 0, 10)
Why don't keep it simple?
<?php
echo strtoupper(uniqid());
?>
Always returns 13 character long uppercased random code.
You can use the coupon code generator PHP class file to generate N number of coupons and its customizable, with various options of adding own mask with own prefix and suffix. Simple PHP coupon code generator
Example:
coupon::generate(8); // J5BST6NQ
http://webarto.com/35/php-random-string-generator
Here you go.
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 strtoupper($string); //to uppercase
}
If there are no security requirements for these, then you don't really need randomly generated codes. I would just use incremental IDs, such as those generated by whatever RDBMS you use. Optionally, if you have different types of coupons, you could prefix the codes with something, e.g.:
CX00019 QZ0001C
CX0001A QZ0001D
CX0001B QZ0001E
Alternately, you could even use dictionary words in the coupon, as such coupon codes are easier to remember and faster for users to type. Companies like Dreamhost use these for their promo codes, e.g.:
Promo60
NoSetupFee
YELLOWGORILLA82
Some of these are obviously human-created (which you might want to have the option of), but they can also be generated using a dictionary list. But even if they are randomly-generated nonsense phrases, the fact that the characters follow a logical pattern still makes it much more user-friendly than something like R7QZ8A92F1. So I would strongly advise against using the latter type of coupon codes just on the basis that they "look cool". Your customers will thank you.
$size = 12;
$string = strtoupper(substr(md5(time().rand(10000,99999)), 0, $size));
function generateCouponCode($length = 8) {
$chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
$ret = '';
for($i = 0; $i < $length; ++$i) {
$random = str_shuffle($chars);
$ret .= $random[0];
}
return $ret;
}
you can find a lot of function in php rand manual
http://php.net/manual/en/function.rand.php
i like this one
<?php
//To Pull 8 Unique Random Values Out Of AlphaNumeric
//removed number 0, capital o, number 1 and small L
//Total: keys = 32, elements = 33
$characters = array(
"A","B","C","D","E","F","G","H","J","K","L","M",
"N","P","Q","R","S","T","U","V","W","X","Y","Z",
"1","2","3","4","5","6","7","8","9");
//make an "empty container" or array for our keys
$keys = array();
//first count of $keys is empty so "1", remaining count is 1-7 = total 8 times
while(count($keys) < 8) {
//"0" because we use this to FIND ARRAY KEYS which has a 0 value
//"-1" because were only concerned of number of keys which is 32 not 33
//count($characters) = 33
$x = mt_rand(0, count($characters)-1);
if(!in_array($x, $keys)) {
$keys[] = $x;
}
}
foreach($keys as $key){
$random_chars .= $characters[$key];
}
echo $random_chars;
?>
$length = 9;
$code = (strtoupper(substr(md5(time()), 0, $length)));
Just Write
$voucher_no = date('ymd') . rand(1000, 9999);
while(SapItem::where('voucher_no', $voucher_no)->exists()){
$voucher_no = date('ymd') . rand(1000, 9999);
}
Output: 2204171447
I know that the rand function in PHP generates random integers, but what is the best way to generate a random string such as:
Original string, 9 chars
$string = 'abcdefghi';
Example random string limiting to 6 chars
$string = 'ibfeca';
UPDATE: I have found tons of these types of functions, basically I'm trying to understand the logic behind each step.
UPDATE: The function should generate any amount of chars as required.
Please comment the parts if you reply.
If you want to allow repetitive occurences of characters, you can use this function:
function randString($length, $charset='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789')
{
$str = '';
$count = strlen($charset);
while ($length--) {
$str .= $charset[mt_rand(0, $count-1)];
}
return $str;
}
The basic algorithm is to generate <length> times a random number between 0 and <number of characters> − 1 we use as index to pick a character from our set and concatenate those characters. The 0 and <number of characters> − 1 bounds represent the bounds of the $charset string as the first character is addressed with $charset[0] and the last with $charset[count($charset) - 1].
Well, you didn't clarify all the questions I asked in my comment, but I'll assume that you want a function that can take a string of "possible" characters and a length of string to return. Commented thoroughly as requested, using more variables than I would normally, for clarity:
function get_random_string($valid_chars, $length)
{
// start with an empty random string
$random_string = "";
// count the number of chars in the valid chars string so we know how many choices we have
$num_valid_chars = strlen($valid_chars);
// repeat the steps until we've created a string of the right length
for ($i = 0; $i < $length; $i++)
{
// pick a random number from 1 up to the number of valid chars
$random_pick = mt_rand(1, $num_valid_chars);
// take the random character out of the string of valid chars
// subtract 1 from $random_pick because strings are indexed starting at 0, and we started picking at 1
$random_char = $valid_chars[$random_pick-1];
// add the randomly-chosen char onto the end of our string so far
$random_string .= $random_char;
}
// return our finished random string
return $random_string;
}
To call this function with your example data, you'd call it something like:
$original_string = 'abcdefghi';
$random_string = get_random_string($original_string, 6);
Note that this function doesn't check for uniqueness in the valid chars passed to it. For example, if you called it with a valid chars string of 'AAAB', it would be three times more likely to choose an A for each letter as a B. That could be considered a bug or a feature, depending on your needs.
My favorite:
echo substr(md5(rand()), 0, 7);
So, let me start off by saying USE A LIBRARY. Many exist:
RandomCompat
RandomLib
SecurityMultiTool
The core of the problem is almost every answer in this page is susceptible to attack. mt_rand(), rand(), lcg_value() and uniqid() are all vulnerable to attack.
A good system will use /dev/urandom from the filesystem, or mcrypt_create_iv() (with MCRYPT_DEV_URANDOM) or openssl_pseudo_random_bytes(). Which all of the above do. PHP 7 will come with two new functions random_bytes($len) and random_int($min, $max) that are also safe.
Be aware that most of those functions (except random_int()) return "raw strings" meaning they can contain any ASCII character from 0 - 255. If you want a printable string, I'd suggest running the result through base64_encode().
function generate_random_string($name_length = 8) {
$alpha_numeric = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
return substr(str_shuffle(str_repeat($alpha_numeric, $name_length)), 0, $name_length);
}
Updated the code as per mzhang's great suggestion in the comments below.
A better and updated version of #taskamiski's excellent answer:
Better version, using mt_rand() instead of rand():
echo md5(mt_rand()); // 32 char string = 128bit
Even better, for longer strings, using the hash() function that allows to select hashing algorithmns:
echo hash('sha256', mt_rand()); // 64 char string
echo hash('sha512', mt_rand()); // 128 char string
If you want to cut the result down to let's say 50 chars, do it like this:
echo substr(hash('sha256', mt_rand()), 0, 50); // 50 char string
Joining characters at the end should be more efficient that repeated string concatenation.
Edit #1: Added option to avoid character repetition.
Edit #2: Throws exception to avoid getting into infinite loop if $norepeat is selected and $len is greater than the charset to pick from.
Edit #3: Uses array keys to store picked random characters when $norepeat is selected, as associative array key lookup is faster than linearly searching the array.
function rand_str($len, $norepeat = true)
{
$chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
$max = strlen($chars) - 1;
if ($norepeat && len > $max + 1) {
throw new Exception("Non repetitive random string can't be longer than charset");
}
$rand_chars = array();
while ($len) {
$picked = $chars[mt_rand(0, $max)];
if ($norepeat) {
if (!array_key_exists($picked, $rand_chars)) {
$rand_chars[$picked] = true;
$len--;
}
}
else {
$rand_chars[] = $picked;
$len--;
}
}
return implode('', $norepeat ? array_keys($rand_chars) : $rand_chars);
}
this will generate random string
function generateRandomString($length=10) {
$original_string = array_merge(range(0,9), range('a','z'), range('A', 'Z'));
$original_string = implode("", $original_string);
return substr(str_shuffle($original_string), 0, $length);
}
echo generateRandomString(6);
I think I will add my contribution here as well.
function random_string($length) {
$bytes_1 = openssl_random_pseudo_bytes($length);
$hex_1 = bin2hex($bytes_1);
$random_numbers = substr(sha1(rand()), 0, $length);
$bytes_2 = openssl_random_pseudo_bytes($length);
$hex_2 = bin2hex($bytes_2);
$combined_chars = $hex_1 . $random_numbers . $hex_2;
$chars_crypted = hash('sha512', $combined_chars);
return $chars_crypted;
}
Thanks
Most aspects of this have already been discussed, but i'd recommend a slight update:
If you are using this for retail usage, I would avoid the domain
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789
and instead use:
ABCDEFGHJKMNPQRSTUVWXY3456789
Granted, you end up with far fewer characters, but it saves a great deal of hassle, as customers cannot mistake 0 for O, or 1 for l or 2 for Z. Also, you can do an UPPER on the input and customers can then enter upper or lower case letters -- that is also sometimes confusing since they can look similar.
What do you need a random string for?
Is this going to be used for anything remotely analogous to a password?
If your random string requires any security properties at all, you should use PHP 7's random_int() function instead of all the insecure mt_rand() answers in this thread.
/**
* Generate a random string
*
* #link https://paragonie.com/b/JvICXzh_jhLyt4y3
*
* #param int $length - How long should our random string be?
* #param string $charset - A string of all possible characters to choose from
* #return string
*/
function random_str($length = 32, $charset = 'abcdefghijklmnopqrstuvwxyz')
{
// Type checks:
if (!is_numeric($length)) {
throw new InvalidArgumentException(
'random_str - Argument 1 - expected an integer'
);
}
if (!is_string($charset)) {
throw new InvalidArgumentException(
'random_str - Argument 2 - expected a string'
);
}
if ($length < 1) {
// Just return an empty string. Any value < 1 is meaningless.
return '';
}
// This is the maximum index for all of the characters in the string $charset
$charset_max = strlen($charset) - 1;
if ($charset_max < 1) {
// Avoid letting users do: random_str($int, 'a'); -> 'aaaaa...'
throw new LogicException(
'random_str - Argument 2 - expected a string at least 2 characters long'
);
}
// Now that we have good data, this is the meat of our function:
$random_str = '';
for ($i = 0; $i < $length; ++$i) {
$r = random_int(0, $charset_max);
$random_str .= $charset[$r];
}
return $random_str;
}
If you aren't on PHP 7 yet (which is probably the case, as it hasn't been released as of this writing), then you'll want paragonie/random_compat, which is a userland implementation of random_bytes() and random_int() for PHP 5 projects.
For security contexts, always use random_int(), not rand(), mt_rand(), etc. See ircmaxell's answer as well.
built on top of https://stackoverflow.com/a/853898/533426
but with php 7 cryptographically secure random function and lower AND upper case alphabet
function random($length = 8){
$valid_chars ="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
// start with an empty random string
$random_string = "";
// count the number of chars in the valid chars string so we know how many choices we have
$num_valid_chars = strlen($valid_chars);
// repeat the steps until we've created a string of the right length
for ($i = 0; $i < $length; $i++)
{
// pick a random number from 1 up to the number of valid chars
$random_pick = random_int(1, $num_valid_chars);
// take the random character out of the string of valid chars
// subtract 1 from $random_pick because strings are indexed starting at 0, and we started picking at 1
$random_char = $valid_chars[$random_pick-1];
// add the randomly-chosen char onto the end of our string so far
$random_string .= $random_char;
}
// return our finished random string
return $random_string;
}
//example output XjdXHakZ, yBG8hpZG, L6jg4FpK
// #author http://codeascraft.etsy.com/2012/07/19/better-random-numbers-in-php-using-devurandom/
function devurandom_rand($min = 0, $max = 0x7FFFFFFF)
{
$diff = $max - $min;
if ($diff < 0 || $diff > 0x7FFFFFFF) {
throw new RuntimeException('Bad range');
}
$bytes = mcrypt_create_iv(4, MCRYPT_DEV_URANDOM);
if ($bytes === false || strlen($bytes) != 4) {
throw new RuntimeException('Unable to get 4 bytes');
}
$ary = unpack('Nint', $bytes);
$val = $ary['int'] & 0x7FFFFFFF; // 32-bit safe
$fp = (float) $val / 2147483647.0; // convert to [0,1]
return round($fp * $diff) + $min;
}
function build_token($length = 60, $characters_map = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789') {
$map_length = mb_strlen($characters_map)-1;
$token = '';
while ($length--) {
$token .= mb_substr($characters_map, devurandom_rand(0,$map_length),1);
}
return $token;
}
This will work only in UNIX environment where PHP is compiled with mcrypt.
Do you want to create your password by a random permutation of the original letters? Should it just contain unique characters?
Use rand to choose random letters by index.
This is an old question but I want try to post my solution... I always use this my function to generate a custom random alphanumeric string...
<?php
function random_alphanumeric($length) {
$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ12345689';
$my_string = '';
for ($i = 0; $i < $length; $i++) {
$pos = mt_rand(0, strlen($chars) -1);
$my_string .= substr($chars, $pos, 1);
}
return $my_string;
}
$test = random_alphanumeric(50); // 50 characters
echo $test;
?>
test: UFOruSSTCPIqxTRIIMTRkqjOGidcVlhYaS9gtwttxglheVugFM
if you need two or more unique strings you can use this trick...
$string_1 = random_alphanumeric(50);
$string_2 = random_alphanumeric(50);
while ($string_1 == $string_2) {
$string_1 = random_alphanumeric(50);
$string_2 = random_alphanumeric(50);
if ($string_1 != $string_2) {
break;
}
}
echo $string_1;
echo "<br>\n";
echo $string_2;
$string_1: tMYicqLCHEvENwYbMUUVGTfkROxKIekEB2YXx5FHyVByp3mlJO
$string_2: XdMNJYpMlFRKFDlF6GhVn6jsBVNQ1BCCevj8yK2niFOgpDI2MU
I hope this help.
echo substr(bin2hex(random_bytes(14)), 0, $length);
this code gets a random bytes, that are converted from binary to hexadecimal, and then takes a substring of this hexadecimal string, as long you puts in $length variable
Try this
Simple enough!
function RandomFromCharset($charset,$length)
{
$characters = $charset; // your existing charset / defined string
$charactersLength = strlen($characters);
$random_from_charset = '';
for ($i = 0; $i < $length; $i++)
{
$random_from_charset.= $characters[rand(0, $charactersLength - 1)];
}
return random_from_charset;
}
Call the function as follows
RandomFromCharset($charset,$length);
where $length will be length of random string you want (this can be predefined also in the function as RandomFromCharset(charset,$length=10) ) to generate and $charset will be your existing string to which you want to restrict the characters.
One approach is to generate an md5 from a random number and extract the number of characters you want:
<?php
$random = substr(md5(mt_rand()), 0, 7);
echo $random;
?>
mt_rand will generate a random number, md5 will create a 32 character string (containing both letters and numbers) and, in this example, we're extracting the first 7 characters of text.
you could make an array of characters then use rand() to pick a letter from the array and added it to a string.
$letters = array( [0] => 'a' [1] => 'b' [2] => 'c' [3] => 'd' ... [25] = 'z');
$lengthOfString = 10;
$str = '';
while( $lengthOfString-- )
{
$str .= $letters[rand(0,25)];
}
echo $str;
*note that this does allow repeat characters
This builds on Gumbo's solution by adding functionality to list a set of characters to be skipped in the base character set. The random string selects characters from $base_charset which do not also appear in $skip_charset.
/* Make a random string of length using characters from $charset, excluding $skip_chars.
* #param length (integer) length of return value
* #param skip_chars (string) characters to be excluded from $charset
* #param charset (string) characters of posibilities for characters in return val
* #return (string) random string of length $length */
function rand_string(
$length,
$skip_charset = '',
$base_charset='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'){
$skip_len = strlen($skip_charset);
for ($i = 0; $i<$skip_len; $i++){
$base_charset = str_replace($skip_charset[$i], '', $base_charset);
}
cvar_dump($base_charset, '$base_charset after replace');
$str = '';
$count = strlen($base_charset);
while ($length--) {
$str .= $base_charset[mt_rand(0, $count - 1)];
}
return $str;
}
Here are some usage examples. The first two examples use the default value for $base_charset. The last example explicitly defines $base_charset.
echo rand_string(15, 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz');
// 470620078953298
echo rand_string(8, 'abcdefghijklmnopqrstuvwxyz0123456789');
// UKLIHOTFSUZMFPU
echo rand_string(15, 'def', 'abcdef');
// cbcbbccbabccaba
well, I was looking for a solution, and I kindda used #Chad Birch's solution merged with #Gumbo's one. This is what I came up with:
function get_random_string($length, $valid_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz123456790!·$%&/()=?¿¡',.-;:+*`+´ç")
{
$random_string = "";
$num_valid_chars = strlen($valid_chars);
for ($i = 0; $i < $length; $i++, $random_string .= $valid_chars[mt_rand(1, $num_valid_chars)-1]);
return $random_string;
}
I think comments are pretty much unnecesary since the answers I used to build up this one are already thoroughly commented. Cheers!
If you're not concerned about time, memory, or cpu efficiency, and if your system can handle it, why not give this algorithm a try?!
function randStr($len, $charset = 'abcdABCD0123') {
$out = '';
$str = array();
for ($i = 0; $i < PHP_INT_MAX; $i++) {
$str[$i] = $charset;
shuffle($str);
$charset .= implode($charset, $str);
$charset = str_shuffle($charset);
}
$str = array_flip($str);
$str = array_keys($str);
for ($i = 0; $i < PHP_INT_MAX; $i++) {
shuffle($str);
}
$str = implode('', $str);
for ($i = 0; $i < strlen($str); $i++) {
$index = mt_rand(1, strlen($str));
$out .= $str[$index - 1];
}
for ($i = 0; $i < PHP_INT_MAX; $i++) {
$out = str_shuffle($out);
}
return substr($out, 0, $len);
}
Maybe this will read better if it uses recursion, but I'm not sure if PHP uses tail recursion or not...