generate a 5 char long string 0-9 a-z - php

I need a function in php that can generate a 5 char long string with numbers and a-z
What should I look into?

Other's have already provided you with correct answers, but here's a one-liner, just for the sake of it:
$code = substr(str_shuffle('0123456789abcdefghijklmnopqrstuvwxyz'), 0, 5);
str_shuffle randomizes the above string, then substr takes the first 5 letters of that shuffled string. Simple.
As noted in comments for this answer, this function only generates strings that have only unique characters. If one would like to have the strings where even "aaaaa" is possible, here's a little function that allows just that:
function generate($len) {
return substr(str_shuffle(str_repeat('0123456789abcdefghijklmnopqrstuvwxyz', $len)), 0, $len);
}
echo generate(5);
str_repeat repeats the 0-9a-z string $len times, so every letter has an almost equal possibility for every position. (Read the comments on why only "almost")

For kicks, here's an alternate approach:
//create a random base 36 string
$str = base_convert(rand(), 10, 36);
substr and concatenate as necessary to satisfy length requirements.
This will not give unique characters (e.g., 'aa11a' would be a possible output) -- which may or may not be what the OP wants. Also, the fact that you may need to run the function multiple times to get a string of the requested length means performance may not be spectacular, but if you're only calling this function once or twice, it won't matter.
Here's a more complete implementation:
function randstr($len) {
$currLen = 0;
$value = '';
while($currLen < $len) {
$new = base_convert(rand(), 10, 36);
$value .= $new;
$currLen += strlen($new);
}
//$value may be longer than the requested $len
return substr($value, 0, $len);
}
It's also worth noting that this string will be of less-than-perfect randomness -- the first char of each string output by base_convert will have a bias toward the lower end of the spectrum (as rand() will not completely fill a whole char's worth of bits every time). Ideally, you want a number of bits out of rand that will exactly fill some number of base-36 chars.
Using a source of entropy that gives you more bits than you need for the string in the first place (like /dev/urandom) would resolve this issue. But for most applications, the loss of entropy won't matter enough to justify the overhead of reading /dev/urandom.
Alternately, you could simply throw away the first char of each base_convert() call.

Here’s some example generator:
$length = 5;
$charset = '0123456789abcdefghijklmnopqrstuvwxyz';
$str = '';
while ($length--) {
$str .= $charset[rand() % count($charset)];
}

Do you mean a random string?
If so, simply create a string containing the 36 characters, generate 5 random numbers and create the string based on the character positions (pseudo-code):
string src = "0123456789abcdefghijklmnopqrstuvwxyz"
string dst = ""
for i = 1 to 5:
dst = dst + src[random(len(src))]
If you want 5 unique characters, you do the same thing but with one slight difference.
Generate the first random number in the range 0 through 35, the second in the range 0 through 34 and so on.
Then, as you add the character from the source string to your own string, replace the used character in the source string with the last character in the source string. This will prevent the same character from being selected twice:
string src = "0123456789abcdefghijklmnopqrstuvwxyz"
int srclen = len(src)
string dst = ""
for i = 1 to 5:
idx = randon(len(src))
dst = dst + src[idx]
src[idx] = src[srclen-1]
srclen = srclen - 1
Aside: #Tatu has provided a simple solution using str_shuffle which is a more elegant way of doing that last method (unique characters) but I'm not convinced it's the most efficient way since it's likely to involve a lot of swaps to get a decent shuffle. The method here seems to me to be more likely to be faster.
Keep that in mind if performance is important, but also keep in mind that I haven't tested how good it is - it may be fast enough - it may even blow my solution out of the water :-) As with all performance-related things, measure, don't guess.

http://php.net/manual/en/function.chr.php, in case you dislike hardcoding the alphabet.

Yet another approach, for funsies. Could be shortened - here it's a bit verbose, for readability.
function rand_string($length=5) {
$values = str_split("abcdefghijklmnopqrstuvwxyz0123456789"));
shuffle($values);
$values = array_flip($values);
$string = implode(array_rand($lenght));
return $string;
}

Related

how to create a row of digits based on a string in php [duplicate]

In php is there a way to give a unique hash from a string, but that the hash was made up from numbers only?
example:
return md5(234); // returns 098f6bcd4621d373cade4e832627b4f6
but I need
return numhash(234); // returns 00978902923102372190
(20 numbers only)
the problem here is that I want the hashing to be short.
edit:
OK let me explain the back story here.
I have a site that has a ID for every registered person, also I need a ID for the person to use and exchange (hence it can't be too long), so far the ID numbering has been 00001, 00002, 00003 etc...
this makes some people look more important
this reveals application info that I don't want to reveal.
To fix point 1 and 2 I need to "hide" the number while keeping it unique.
Edit + SOLUTION:
Numeric hash function based on the code by https://stackoverflow.com/a/23679870/175071
/**
* Return a number only hash
* https://stackoverflow.com/a/23679870/175071
* #param $str
* #param null $len
* #return number
*/
public function numHash($str, $len=null)
{
$binhash = md5($str, true);
$numhash = unpack('N2', $binhash);
$hash = $numhash[1] . $numhash[2];
if($len && is_int($len)) {
$hash = substr($hash, 0, $len);
}
return $hash;
}
// Usage
numHash(234, 20); // always returns 6814430791721596451
An MD5 or SHA1 hash in PHP returns a hexadecimal number, so all you need to do is convert bases. PHP has a function that can do this for you:
$bignum = hexdec( md5("test") );
or
$bignum = hexdec( sha1("test") );
PHP Manual for hexdec
Since you want a limited size number, you could then use modular division to put it in a range you want.
$smallnum = $bignum % [put your upper bound here]
EDIT
As noted by Artefacto in the comments, using this approach will result in a number beyond the maximum size of an Integer in PHP, and the result after modular division will always be 0. However, taking a substring of the hash that contains the first 16 characters doesn't have this problem. Revised version for calculating the initial large number:
$bignum = hexdec( substr(sha1("test"), 0, 15) );
You can try crc32(). See the documentation at: http://php.net/manual/en/function.crc32.php
$checksum = crc32("The quick brown fox jumped over the lazy dog.");
printf("%u\n", $checksum); // prints 2191738434
With that said, crc should only be used to validate the integrity of data.
There are some good answers but for me the approaches seem silly.
They first force php to create a Hex number, then convert this back (hexdec) in a BigInteger and then cut it down to a number of letters... this is much work!
Instead why not
Read the hash as binary:
$binhash = md5('[input value]', true);
then using
$numhash = unpack('N2', $binhash); //- or 'V2' for little endian
to cast this as two INTs ($numhash is an array of two elements). Now you can reduce the number of bits in the number simply using an AND operation. e.g:
$result = $numhash[1] & 0x000FFFFF; //- to get numbers between 0 and 1048575
But be warned of collisions! Reducing the number means increasing the probability of two different [input value] with the same output.
I think that the much better way would be the use of "ID-Crypting" with a Bijectiv function. So no collisions could happen! For the simplest kind just use an Affine_cipher
Example with max input value range from 0 to 25:
function numcrypt($a)
{
return ($a * 15) % 26;
}
function unnumcrypt($a)
{
return ($a * 7) % 26;
}
Output:
numcrypt(1) : 15
numcrypt(2) : 4
numcrypt(3) : 19
unnumcrypt(15) : 1
unnumcrypt(4) : 2
unnumcrypt(19) : 3
e.g.
$id = unnumcrypt($_GET('userid'));
... do something with the ID ...
echo ' go ';
of course this is not secure, but if no one knows the method used for your encryption then there are no security reasons then this way is faster and collision safe.
The problem of cut off the hash are the collisions, to avoid it try:
return hexdec(crc32("Hello World"));
The crc32():
Generates the cyclic redundancy checksum polynomial of 32-bit lengths
of the str. This is usually used to validate the integrity of data
being transmitted.
That give us an integer of 32 bit, negative in 32 bits installation, or positive in the 64 bits. This integer could be store like an ID in a database. This don´t have collision problems, because it fits into 32bits variable, once you convert it to decimal with the hexdec() function.
First of all, md5 is basically compromised, so you shouldn't be using it for anything but non-critical hashing.
PHP5 has the hash() function, see http://www.php.net/manual/en/function.hash.php.
Setting the last parameter to true will give you a string of binary data. Alternatively, you could split the resulting hexadecimal hash into pieces of 2 characters and convert them to integers individually, but I'd expect that to be much slower.
Try hashid.
It hash a number into format you can define. The formats include how many character, and what character included.
Example:
$hashids->encode(1);
Will return "28630" depends on your format,
Just use my manual hash method below:
Divide the number (e.g. 6 digit) by prime values, 3,5,7.
And get the first 6 values that are in the decimal places as the ID to be used. Do a check on uniqueness before actual creation of the ID, if a collision exists, increase the last digit by +1 until a non collision.
E.g. 123456 gives you 771428
123457 gives you 780952
123458 gives you 790476.

How to decrease runtime for generating permutations of a string?

I have written a function that takes in a MD5 hashvalue and finds its input/original value by permuting all possible combinations of a string. As per BIT_CHEETAH's answer on a SO question:
... you cannot decrypt MD5 without attempting something like brute force hacking which is extremely resource intensive, not practical, and unethical.
(Source: encrypt and decrypt md5)
I'm well aware of this, however, I am using this scenario to implement a string permutation function. I would also like to stick to the recursive methodology as opposed to others. The best summary of doing this is probably summarised by Mark Byers post:
- Try each of the letters in turn as the first letter and then find all
the permutations of the remaining letters using a recursive call.
- The base case is when the input is an empty string the only permutation is the empty string.
(Generating all permutations of a given string)
Anyway, so I implemented this and got the following:
function matchMD5($possibleChars, $md5, $concat, $length) {
for($i = 0; $i < strlen($possibleChars); $i++) {
$ch = $possibleChars[$i];
$concatSubstr = $concat.$ch;
if(strlen($concatSubstr) != $length) {
matchMD5($possibleChars, $md5, $concatSubstr, $length);
}
else if(strlen($concatSubstr) == $length) {
$tryHash = hash('md5', $concatSubstr);
if ($tryHash == $md5) {
echo "Match! $concatSubstr ";
return $concatSubstr;
}
}
}
}
Works 100%, however when I pass in a four character array, my server runs 10.7 seconds to generate a match where the match lies approximately 1/10th of the way of all possible permutations. My valid characters in which the functions permutes, called, $possibleChars, contains all alphanumeric characters plus a few selected punctionations:
0123456789.,;:abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ
Question: Can the above code be written to run faster somehow?
When doing brute-force, you have to run through all the possibilities, there is not way of cutting a corner there. So you are left with profiling your code to find out what the application spends the most time doing and then trying to optimize that.

How to generate unique secure random string in PHP?

I want to add random string as token for form submission which is generated unique forever. I have spent to much time with Google but I am confused which combination to use?
I found so many ways to do this when I googled:
1) Combination of character and number.
2) Combination of character, number and special character.
3) Combination of character, number, special character and date time.
Which combination may i use?
How many character of random string may I generate.?
Any other method which is secure then please let me know.?
Here are some considerations:
Alphabet
The number of characters can be considered the alphabet for the encoding. It doesn't affect the string strength by itself but a larger alphabet (numbers, non-alpha-number characters, etc.) does allow for shorter strings of similar strength (aka keyspace) so it's useful if you are looking for shorter strings.
Input Values
To guarantee your string to be unique, you need to add something which is guaranteed to be unique.
Random value is a good seed value if you have a good random number generator
Time is a good seed value to add but it may not be unique in a high traffic environment
User ID is a good seed value if you assume a user isn't going to create sessions at the exact same time
Unique ID is something the system guarantees is unique. This is often something that the server will guarantee / verify is unique, either in a single server deployment or distributed deployment. A simple way to do this is to add a machine ID and machine unique ID. A more complicated way to do this is to assign key ranges to machines and have each machine manage their key range.
Systems that I've worked with that require absolute uniqueness have added a server unique id which guarantees a item is unique. This means the same item on different servers would be seen as different, which was what was wanted here.
Approach
Pick one more input values that matches your requirement for uniqueness. If you need absolute uniqueness forever, you need something that you control that you are sure is unique, e.g. a machine associated number (that won't conflict with others in a distributed system). If you don't need absolute uniqueness, you can use a random number with other value such as time. If you need randomness, add a random number.
Use an alphabet / encoding that matches your use case. For machine ids, encodings like hexadecimal and base 64 are popular. For machine-readable ids, for case-insensitive encodings, I prefer base32 (Crockford) or base36 and for case-sensitive encodings, I prefer base58 or base62. This is because these base32, 36, 58 and 62 produce shorter strings and (vs. base64) are safe across multiple uses (e.g. URLs, XML, file names, etc.) and don't require transformation between different use cases.
You can definitely get a lot fancier depending on your needs, but I'll just throw this out there since it's what I use frequently for stuff like what you are describing:
md5(rand());
It's quick, simple and easy to remember. And since it's hexadecimal it plays nicely with others.
Refer to this SO Protected Question. This might be what you are looking.
I think its better to redirect you to a previously asked question which has more substantive answers.You will find a lot of options.
Try the code, for function getUniqueToken() which returns you unique string of length 10 (default).
/*
This function will return unique token string...
*/
function getUniqueToken($tokenLength = 10){
$token = "";
//Combination of character, number and special character...
$combinationString = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789*#&$^";
for($i=0;$i<$tokenLength;$i++){
$token .= $combinationString[uniqueSecureHelper(0,strlen($combinationString))];
}
return $token;
}
/*
This helper function will return unique and secure string...
*/
function uniqueSecureHelper($minVal, $maxVal) {
$range = $maxVal - $minVal;
if ($range < 0) return $minVal; // not so random...
$log = log($range, 2);
$bytes = (int) ($log / 8) + 1; // length in bytes
$bits = (int) $log + 1; // length in bits
$filter = (int) (1 << $bits) - 1; // set all lower bits to 1
do {
$rnd = hexdec(bin2hex(openssl_random_pseudo_bytes($bytes)));
$rnd = $rnd & $filter; // discard irrelevant bits
} while ($rnd >= $range);
return $minVal + $rnd;
}
Use this code (two function), you can increase string length by passing int parameter like getUniqueToken(15).
I use your 2nd idea (Combination of character, number and special character), which you refine after googling. I hope my example will help you.
You should go for 3 option. Because it has date and time so it become every time unique.
And for method have you tried
str_shuffle($string)
Every time it generates random string from $string.
End then use substr
($string , start , end)
to cut it down.
End if you want date and time then concatenate the result string with it.
An easily understandable and effective code to generate random strings in PHP. I do not consider predictability concerns important in this connection.
<?php
$d = str_shuffle('0123456789');
$C = str_shuffle('ABCDEFGHIJKLMNOPQRSTUVWXYZ');
$m = str_shuffle('abcdefghijklmnopqrstuvwxyz');
$s = str_shuffle('#!$&()*+-_~');
$l=9; //min 4
$r=substr(str_shuffle($d.$C.$m.$s),0,$l);echo $r.'<br>';
$safe=substr($d,0,1).substr($C,0,1).substr($m,0,1).mb_substr($s,0,1);
$r=str_shuffle($safe.substr($r,0,$l-4));//always at least one digit, special, small and capital
// this also allows for 0,1 or 2 of each available characters in string
echo $r;
exit;
?>
For unique string use uniqid().
And to make it secure, use hashing algorithms
for example :
echo md5(uniqid())

PHP int to longer string for use with qrcode

I'm trying to build a app that would identify a user by scanning a qrcode. For this, I want to use the primary key as the identifier. Since the character length of the integer is short, it wouldn't give a good look as a qrcode.
So my question is: Is it possible to convert the int to string which is longer than 10-12 chars (fixed length if possible),mix of chars and numbers which can be reversed to the original integer.
What you can do is to make SHA256 of your user's ID and convert it to QR code.
Then when user reads QR code and send you sha value you try to match it with SHA of user's IDs in the database.
So here is the way to have SHA hash from user id:
$hash = hash('sha256', $userId); // The result is long enough string for QA
The when you need to find a user based on SHA do the following:
select * from users where SHA2(id, 256) = 'SHA_PROVIDED_BY_USER';
You can in order to speed up the look up process store SHA in the DB as well then query will be much faster.
Another option is to prepend the number with some letters. It will give you random string, nice QRs and you can extract numeric ID with simple regexp.
Using function from PHP random string generator (don't forget to remove numbers from $characters) the code could be:
//encoding
$size = 12;
$str = generateRandomString($size-strlen($userId)).$userId;
//decoding
preg_match('/(\d+)$/', $str, $matching);
$userId = $matching[1];
you can convert your integer to any base with base_convert function.
here is the documentation.
http://php.net/manual/en/function.base-convert.php
The notion that a number, in PHP, has a "maximum size" is a little off (not wrong, just off =P)
From the manual:
If PHP encounters a number beyond the bounds of the integer type, it will be interpreted as a float instead.
So, you could use really large numbers for your QR Codes if you want. Shouldn't be an issue. However, what would be better is to think of "what exactly do you need"?
If you need a numeric value, but want it in hex, you can use base_convert() to go back and forth between the numbers:
$val = 1234;
$hex = base_convert($val, 10, 16);
However, if strings are more for you, you could use base64_encode() to encode it:
$val = 'awesome string value';
$encoded = base64_encode($val);
UPDATE
Based on comments, it sounds like you also want to pad the string if it's too short. You can use str_pad() to accomplish this:
$val = str_pad("1", 10, "0", STR_PAD_LEFT);
echo $val;
// displays: 0000000001
$orig = intval($val);
echo $orig;
// displays: 1
Coderpad Example of str_pad()

Create short unique IDs (chars and numbers) that 'looks' pretty... like YouTube IDs (PHP)

I want be able to generate an unique string id from an integer.
So for example '1' is converted to 'o7wu' and vice-versa. (use the number to search the DB and the string for display)
I found this great function: http://kevin.vanzonneveld.net/techblog/article/create_short_ids_with_php_like_youtube_or_tinyurl/, but the generated ids are really ugly for small numbers, for example
'1' is 'aacd' and '2' is 'aadd'. I also found http://blog.kevburnsjr.com/php-unique-hash, the generated ids look great, but they are 'one way' only, i think.
I dont really need any kind of encryption, I just need it to be short, pretty.
For those having truble with my deffinition of a pretty ID: I define pretty as real random mix of chars and ints. NOT: aabb33, abc123, aa22cc. YES: dfh7, ao8f, z6t4 .. and so one...
Random number generators can be hacked to give less random numbers. Actually, you can make them use the same numbers every time. If you set the seed to the same number, you will get the same sequence. Here's an example that creates a "random" string by passing a single number.
<?php
$n = 1;
// Any number to be added to the random seed
// Different numbers give different sequences
$offset = 45;
srand($n + $offset);
$code = '';
for($i=0; $i<4; $i++) {
// Numbers and letters
$char = rand(48, 57+26);
// Lower case letters
if ($char > 57) $char += 39;
$code .= chr($char);
}
echo "The code is $code\n";
With this offset, 1 gives 'ghep', 2 gives 'tw70', 3 gives 'ob0c'. To increase the number of characters, change the $i<4 to a 5, or 13. To change the included characters, use a different range of ASCII codes.
I've tried the first link too and had little success with the code provided. I did some research and I think that YouTube IDs are basically just randomly generated strings (given that there are nearly 74 quintillion possible combinations, the chances of two IDs ever being alike is very slim). Below is a little PHP script that I use to create 11-character YouTube-style random IDs.
$length = 11;
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_-';
$random_id = "";
for ($i = 0; $length > $i; $i++) {
$random_id .= $characters[mt_rand(0, strlen($characters) -1)];
}
The script above basically creates a list of 64 characters identical to those used by YouTube, randomly selects eleven of those characters and then concatenates them all within a for loop. I then store the random IDs generated in a column for random IDs which are searched for via the URL. It does not include encryption, but it is the closest thing I could come up with. You can change the length of the string by changing the $length variable and the characters used by changing the characters that make up the $characters variable.
Little hint, if you are using a MySQL database, change the random ID column's collation to latin1_bin, that way you can include case sensitivity.

Categories