How to save user-created content as a URL (hash) parameter? - php

I want to enable "Save" feature in my web app. I will send data to a PHP post receiver, and save the data in a MySQL row, so normally I can load it with its id like this:
site.com/content/123
But I want (just for the fancy looks) to use a "hash" (not sure if it's the right term) for this, like :
site.com/content/A2w7SqZ
just like jsFiddle does. How can I convert the id (integer) to a hash?
Example :
http://jsfiddle.net/sfu24/
The only way I can think of is MD5. But it generates a very long string. I think 6 characters are more than enough.
So how can I make a hash system like jsfiddle?
Thanks for any help !
P.S. I'm sure this question has been asked million times. But I couldn't find it. If you know an already-existing answer, please post the link and I will delete the question.

to generate random chars
function generate_random($length = 10) {
$characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$randomString = '';
for($i = 0; $i < $length; $i ++) {
$randomString .= $characters [rand ( 0, strlen ( $characters ) - 1 )];
}
return $randomString;
}

Take a look as base_convert()
or the hashids
which will help you generate short hashes from numbers (like YouTube and Bitly).

function generateHash($int) {
$rand_letters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
$newstr = '';
for ($i = 0; $i < strlen($int); $i++) {
$newstr .= $rand_letters[rand(0, strlen($rand_letters)-1)];
}
return $newstr;
}
function myHash($int) {
$newstr = generateHash($int);
$result = $db->query("SELECT COUNT(*) FROM hashes WHERE hash = '$newstr';");
if ($result->num_rows > 0) {
myHash($int);
}
return $newstr;
}
echo myHash(973451);
You generate string on the base of the length of your passed integer. That's what generateHash() does. And myHash() uses this string, if it's already present, runs itself again, until generate not-present string, so returns it.
The hashes are random, so they are not straight reversable (they still can be), but "12345" will not result in one and the same string everytime.

Related

Generate save activation key as product key

I am trying to create a function which creates a random String. This String should consist of letters (only caps) and numbers. It will be used to activate a product. So the user has to type it into a text field.
So far I found the following function:
function random_str($length, $keyspace = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'){
$pieces = [];
$max = mb_strlen($keyspace, '8bit') - 1;
for ($i = 0; $i < $length; ++$i) {
$pieces []= $keyspace[random_int(0, $max)];
}
return implode('', $pieces);
}
I do not have that much experience with random functions. So is there anything to improve or would you suggest a different function?
To generate a cryptographically secure random string (which I would recommend for an activation key), I would rather use openssl_random_pseudo_bytes
You can find the doc here and some useful informations in that thread (for example, how to get a random string with 0-9A-Z characters rather than just 0-9A-F).
As of PHP7.0 you could also use random_bytes, which is also cryptographically secure.
readable - base64_encode(random_bytes($lenght ) ); shorter
readable longer - bin2hex(random_bytes($lenght ) );
To make with wanted length use substr
Use rand function instead of 'random_int'
function random_str($length, $keyspace =
'0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'){
$pieces = [];
$max = mb_strlen($keyspace, '8bit') - 1;
for ($i = 0; $i < $length; ++$i) {
$pieces []= $keyspace[rand(0, $max)];
}
return implode('', $pieces);
}
echo random_str('50');
// Output //
P7V55MYPQJGRNQ8W0VW7TRKBDK2B7NXWUT20F0P6J5Y7W63X20

Generate a random string of alpha numerical characters to a .txt file

I would like to create a random string of 25 alpha-numerical characters that when ran via a cron, would print the results to a key.txt file.
What would be the best way to do it? Thank you.
There are tons of tutorials out there, one possible solution (for a learning purpose, that is) would be:
$chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
// alternatively: implode('', array_merge(range(0,9),range('a', 'z'), range('A', 'Z')));
$length = 25;
$string = '';
for ($i = 0; $i < $length; $i++)
$string .= $chars[rand(0, strlen($chars) - 1)];
// save it to a file
file_put_contents("key.txt", $string);
This is easy function to resolve your problem.
Pass your length variable to define length of out put.
function random_string( $length = 25 ) {
$chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
$password = substr( str_shuffle( $chars ), 0, $length );
return $password;
}
PS. it's not guarantee uniqueness of each output.
I can give you answers as long as the bible on how to generate random strings but you'll be reading them and saying to yourself: "Well, this sucks.". So I'll keep it short and to the point.
// Generate random string
$randomString = uniqid();
This way it will not have to be 25 characters long as the generated string is always unique and would be a perfect key or filename.
For more information check the PHP Manual on uniqid().

Turning an integer into random string and back again

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.

Random Code Overkill?

I have some code I am using
function genCode ($entropy=1) {
$truCde = "";
$indx = 0;
$leng = 30*$entropy;
while ($indx < $leng) {
$code = "";
$length = 100*$entropy;
$index = 0;
while ($index < $length) {
$code .= rand();
$index++;
}
$index = 0;
while ($index < $length) {
$code = sha1($code);
$index++;
}
$truCde .= $code;
$indx++;
}
$finalCode = sha1(rand()) . hash("sha256",$truCde . md5($entropy*rand()));
$finalCode .= sha1(md5(strlen($finalCode)*$entropy));
return hash (
"sha256",
sha1($finalCode) . sha1(md5($finalCode)) . sha1(sha1($finalCode))
);
}
to generate a random code for e-mail verification. Is there code that takes less time to generate random codes. It takes about 1-2 seconds to run this code, but I am looking to shave .7 seconds off this because the rest of the script will take longer.
That's massive overkill. Calling rand() repeatedly isn't going to make the code "more random", nor will using random combinations of SHA and MD5 hashes. None of that complexity improves the verification codes.
An improvement that would make a difference would be to use mt_rand() in preference to rand(). The Mersenne Twister pseudo RNG is much stronger than most default rand() implementations. The PHP documentation hints that rand() may max out at 215 meaning you can only generate 32,768 unique verification codes.
Other than that, a single hash call will do.
sha1(mt_rand())
(You don't even really need to call a hash function as the unpredictability of your codes will come from the random number generator, not the hash function. But hash functions have the nice side effect of creating long hex strings which "look" better.)
If you just want to generate random strings to test that someone has access to an email address, or something like that, I would throw out that code and use something a lot more straightforward. Something like the following would likely do.
function genCode () {
$chars = 'abcdefghijklmnopqrstuvwxyz0123456789';
$returnValue = '';
for ($i = 0; $i < 20; $i++) {
$returnValue .= $chars[mt_rand(0, 35)];
}
return $returnValue;
}
You can hash the return value if you want, but I don't know what the point would be other than to obfuscate the scheme used to come up with the random strings.

PHP code for generating decent-looking coupon codes (mix of letters and numbers)

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

Categories