Generate a token for email verification in CodeIgniter 3 - php

I'm building a login/reg system in CI3 and I have a doubt.
Instead of use:
$key=md5(uniqid());
for sending key for email activation...can I use another method? I don't know, using database (mysql)? hash with SHA1 maybe?
I don't want the most secure way, just a solution that is not fake as uniqid() is. 'Cause I know that id generated by uniqid() is not really random, so there is no reason to hash to md5 is simply...stupid.
Thank you in advance.

Actually email verification/password generation should be
easy to understand
easy to get back
It means if you send md5 what happen is user get an word length of 32. Its very bad sign.
MD5 example
8b1a9953c4611296a827abf8c47804d7
what I Suggest you is
In codeigniter there is an helper call String. Use that.
There is 5 different choices to pick you
alpha
alnum
basic
numeric
nozero
How to use this?
Load helper in controller
$this->load->helper('string');
Then just add this
random_string([$type [, $len]]) ;
Example :
random_string('alnum', 8);
How these diff with each other ??
Assume : length is 8 in these scenario.
alpha
This will just print String with UPPER Case
Example AKTHDOGK
alnum
This will print String with UPPER and LOWER Case
Example JdKsPeeU
basic
This will print random number using mt_rand() in php.
Example 12756079
numeric
This will print Numeric string.
Example 01234567 (Not used. So not sure)
nozero
This will print and number. But there is no zero
Example 12345678 (Not used. So not sure)
FYI: I never used numeric and nozero. So i have no idea about the example. But all other function are i used.

Related

Trouble creating auth string using PHP HMAC SHA1 and Base64

So I am working with this API and using Laravel, and I am trying to build an auth string. This is the documentation I was given, but I am having a little trouble as this is something relatively new to me.
Here are the auth instructions:
The authentication parameter is a string and it can calculated by the
caller or the caller can choose to save this value as a parameter
together with connection ID and API key.
The authentication is a base64 string of a HMAC SHA1 hash. This is
computed by using the binary of API Key in in
########################## format in all lower case and UTF8 encoding as the key and computer HMAC SHA1 hash on the binary of
Connection ID in ################################ format in all lower
case and UTF8 encoding.
The result binary hash is then base64 encoded and the text result is
what should be passed as the authentication parameter. In C# the code
to calculate the authentication may look like:
HMACSHA1 hmac = new HMACSHA1(
UTF8Encoding.UTF8.GetBytes(apiKey.ToString("N").ToLower())
);
string authentication = Convert.ToBase64String(
hmac.ComputeHash(
UTF8Encoding.UTF8.GetBytes(connectionId.ToString("N").ToLower())
)
);
As an example the following credentials:
Connection ID: 5fecbc200f0e4a7cbf41040e11047e56
API Key: 2de51c4fd0f04b9fabeb95225e87da70
Should result in a computed authentication value of
m5/Vc1RzhUETQvEtx/JdIglQpTg=
So what i have been trying is:
$a = strtolower('5fecbc200f0e4a7cbf41040e11047e56');
$b = strtolower('2de51c4fd0f04b9fabeb95225e87da70');
$z = hash_hmac("sha1", utf8_encode(decbin($b)), utf8_encode(decbin($a)), true);
dd(base64_encode($z));
Which outputs QjG3kzUs7U1UukNd++3t24pBWNk=
I have tried a few more variations, but I am just lost on this one. First time really decoding or encoding anything. Would greatly appreciate any tips, ideas, or snippets that can help me figure this out. Already spent a few hours on this and it's bugging me..
First: Get rid of utf8_encode() and just generally don't use it. It assumes that the input string is ISO-88591-1 and if it is anything else it will silently corrupt the data. This function has an incredibly misleading name, and I would go as far as to suggest that no one should ever use it or the corresponding utf8_decode() which will break your data in the same manner, but reversed.
If you need to convert string encodings in PHP use something that explicitly defines the input and output encodings, eg: mb_convert_encoding(). [you still don't need it for this]
Second: Whatever you think decbin() does, you're incorrect. It converts an integer into a literal, capital-S String composed of 0 and 1 characters.
Third: PHP strings have no inherent encoding and are roughly equivalent to byte arrays if you twisted my arm for a description. The bytes you put into them are the bytes you get out of them.
Fourth: I'm not exactly a C# expert [or intermediate, or even beginner] but that example code is horrendous. What even is the significance of the N in connectionId.ToString("N")? I can't find any documentation about this.
Start simple, use meaningful variable names, build up, and read the docs.
$connectionID = strtolower('5fecbc200f0e4a7cbf41040e11047e56');
$apiKey = strtolower('2de51c4fd0f04b9fabeb95225e87da70');
$hash = hash_hmac("sha1", $connectionID, $apiKey, true);
var_dump(base64_encode($hash));
Output:
string(28) "m5/Vc1RzhUETQvEtx/JdIglQpTg="

Simple uppercase encryption algorithm

I am using a system to sell tickets for a game.
Current id numbers for tickets are consecutive. EG: 651,652,653. If someone would buy a new ticket, his ticket id would be 654.
I am looking for a solution to inform the user about his ticket unique id by sending him a string instead of the ticket number, so that he can have a reference, but he would not know how many tickets were purchased before.
By encrypting ticket number 651 I want to generate a string having 6-7 characters maximum, all uppercase, and this algorithm should be two way and reversed only using a secret key.
EG: using a key like 881hu and encrypting number 651 I should obtain something like UTR8N1A0 .
I want uppercase letters for readability, and the length of the new string should not be too long, because then it would be hard to remember.
Do I have any options of such algorithm? I am using PHP as server language for all this.
I agree with #RaggaMuffin-420 comment, that way you can have 6-7 uppercase characters maximum. As for something like mcrypt there's no easy way to make it in 6-7 chars...
of course if you don't want to do something silly like:
$secret = 123456789;
$tickedID = 654;
$code = strtoupper( dechex($secret + $tickedID) );
echo 'Code is: ' . $code . '<br>';
$decode = hexdec($code) - $secret;
echo 'Decoded: ' . $decode;
Output:
Code is: 75BCFA3
Decoded: 654
Disclaimer: I would go with adding unique code in database referencing to the actual ticked id.
One option - you can calculate a hash(consecutive_number + salt) and then encode the hash.
Update: If you need to quickly extract the original consecutive_number, hide it inside the encoded hash string. You can read it, and you can verify it by re-calculating the hash (as the salt is secret, one won't be able to easily calculate the hash to construct a valid key).
There's a lot of bad advice floating around the Internet (and bad designs like "hashids"), but ultimately what you want is:
Don't do this:
Do this instead:
Images (and detailed arguments) from: The Comprehensive Guide to URL Parameter Encryption in PHP

How can I generate strong unique API keys with PHP?

I need to generate a strong unique API key.
Can anyone suggest the best solution for this? I don't want to use rand() function to generate random characters. Is there an alternative solution?
As of PHP 7.0, you can use the random_bytes($length) method to generate a cryptographically-secure random string. This string is going to be in binary, so you'll want to encode it somehow. A straightforward way of doing this is with bin2hex($binaryString). This will give you a string $length * 2 bytes long, with $length * 8 bits of entropy to it.
You'll want $length to be high enough such that your key is effectively unguessable and that the chance of there being another key being generated with the same value is practically nil.
Putting this all together, you get this:
$key = bin2hex(random_bytes(32)); // 64 characters long
When you verify the API key, use only the first 32 characters to select the record from the database and then use hash_equals() to compare the API key as given by the user against what value you have stored. This helps protect against timing attacks. ParagonIE has an excellent write-up on this.
For an example of the checking logic:
$token = $request->bearerToken();
// Retrieve however works best for your situation,
// but it's critical that only the first 32 characters are used here.
$users = app('db')->table('users')->where('api_key', 'LIKE', substr($token, 0, 32) . '%')->get();
// $users should only have one record in it,
// but there is an extremely low chance that
// another record will share a prefix with it.
foreach ($users as $user) {
// Performs a constant-time comparison of strings,
// so you don't leak information about the token.
if (hash_equals($user->api_token, $token)) {
return $user;
}
}
return null;
Bonus: Slightly More Advanced Use With Base64 Encoding
Using Base64 encoding is preferable to hexadecimal for space reasons, but is slightly more complicated because each character encodes 6 bits (instead of 4 for hexadecimal), which can leave the encoded value with padding at the end.
To keep this answer from dragging on, I'll just put some suggestions for handling Base64 without their supporting arguments. Pick a $length greater than 32 that is divisible by both 3 and 2. I like 42, so we'll use that for $length. Base64 encodings are of length 4 * ceil($length / 3), so our $key will be 56 characters long. You can use the first 28 characters for selection from your storage, leaving another 28 characters on the end that are protected from leaking by timing attacks with hash_equals.
Bonus 2: Secure Key Storage
Ideally, you should be treating the key much like a password. This means that instead of using hash_equals to compare the full string, you should hash the remainder of the key like a password, store that separately than the first half of your key (which is in plain-text), use the first half for selection from your database and verify the latter half with password_verify.
using mcrypt:
<?php
$bytes = mcrypt_create_iv(4, MCRYPT_DEV_URANDOM);
$unpack = unpack("Nint", $bytes);
$id = $unpack['int'] & 0x7FFFFFFF;
PHP has uniqid function http://php.net/manual/en/function.uniqid.php with optional prefix and you can even add additional entropy to further avoid collision. But if you absolutely possitevily need something unique you should not use anything with randomness in it.
This is the best solution i found.
http://www.php.net/manual/en/function.uniqid.php#94959

PHP short encrypt

I'm using this code:
$url = "http://www.webtoolkit.info/javascript-base64.html";
print base64_encode($url);
But the result is very long: "aHR0cDovL3d3dy53ZWJ0b29sa2l0LmluZm8vamF2YXNjcmlwdC1iYXNlNjQuaHRtbA=="
There is a way to transform long string to short encryption and to be able to transform?
for example:
new_encrypt("http://www.webtoolkit.info/javascript-base64.html")
Result: "431ASDFafk2"
encoding is not encrypting. If you're depending on this for security then you're in for a very nasty shock in the future.
Base 64 encoding is intended for converting data that's 8 bits wide into a format that can be sent over a communications channel that uses 6 or 7 bits without loss of data. As 6 bits is less than 8 bits the encoded string is obviously going to be longer than the original.
This q/a might have what you're looking for:
An efficient compression algorithm for short text strings
It actually links here:
http://github.com/antirez/smaz/tree/master
I did not test it, just found the links.
First off, base64 is an encoding standard and it is not meant to encrypt data, so don't use that. The reason your data is so much longer is that for every 6 bits in the input string, base64 will output 8 bits.
There is no form of encryption that will directly output a shortened string. The result will be just as long in the best case.
A solution to that problem would be to gzip your string and then encrypt it, but with your URL the added data for the zip format will still end up making your output longer than the input.
There are a many different algorithms for encrypting/decryption. You can take a look at the following documentation: http://www.php.net/manual/en/function.mcrypt-list-algorithms.php (this uses mcrypt with different algorithms).
...BUT, you can't force something to be really small (depends on the size you want). The encrypted string needs to have all the information available to be able to decrypt it. Anyways, a base64-string is not that long (compared with really secure salted hashes for example).
I don't see the problem.
Well... you could try using md5() or uniqid().
The first one generate the md5 hash of your string.
md5("http://www.webtoolkit.info/javascript-base64.html");
http://php.net/manual/en/function.md5.php
The second one generates a 13 unique id and then you can create a relation between your string and that id.
http://php.net/manual/en/function.uniqid.php
P.S. I'm not sure of what you want to achieve but these solutions will probably satisfy you.
You can be creative and just do some 'stuff' to encrypt the url so that it is not easy quess able but encode / decode able..
like reverse strings...
or have a random 3 letters, your string encoded with base64 or just replace letters for numbers or numbers for letters and then 3 more random letters.. once you know the recipe, you can do and undo it.
$keychars = "abcdefghijklmnopqrstuvwxyz0123456789";
$length = 2;
$randkey = "";
$randkey2 = "";
for ($i=0;$i<$length;$i++) $randkey .= substr($keychars, rand(1, strlen($keychars) ), 1);

obfuscate or encrypt some plain text data in PHP

I need to obfuscate or encrypt some plain text data in my php 5.2 application.
I'd prefer a solution that would have input string and output string retain the same length.
This does not need to extremely strong, as there are numerous other layers of security in place. Strong would be good, but this will just keep programmers/dba/support people/etc from accidentally reading the text from within the database.
key considerations
EDIT ADD I'd prefer a solution that would have input string and output string retain the same length.
only string text will be obfuscated/encrypted for storage in a database
the php application will need to obfuscate/encrypt the data before the database save and will need to un-obfuscate/dencrypt following the database read
this is a modification to an existing application
only some columns will need to be obfuscated/encrypted
only some rows will need to be obfuscated/encrypted, based on a Type field
there are only a few load/save points to handle
max column size is already determined for some fields, but not for others, but I'd prefer a solution to work within the existing size of the restricted fields
EDIT, ADD the key will be probably be a composite of some Primary key info +uneditable fields
here is a sample database table and data:
int char(1) varchar(24) int date
MyPrimaryKey RowType UserText UserNo DateChange
------------ ------- ------------------------ -------- ----------------
1 N nothing special here 43 6/20/2009 12:11am
2 N same thing, wow! 78 6/23/2009 1:03pm
3 S fBJKg}.jkjWfF78dlg#45kjg 43 6/25/2009 6:45am
4 N same old, same old text 21 6/25/2009 8:11am
The application would load and display rows 1,2, and 4 normally. However it would conditionally (based on row type) handle the text in row 3 using this obfuscate/encrypt and un-obfuscate/decrypt logic.
Can anyone provide obfuscate/encrypt and un-obfuscate/decrypt functions code, links, and or pointer that would help here?
thanks!
EDIT
I like the simple base64 encoding idea, but is there a method that can keep the data within a fixed size. All methods listed so far have the output value larger than the input value. This will be a problem for some columns, where the user can enter in 50 characters and it is stored in a varchar(50) column.
for simple obfuscation use strtr() - Translate certain characters:
string strtr ( string $str , string $from , string $to )
to encode in php:
$readable='This is a special test string ABC123 ([+,-!#$%&*])';
$unreadable=strtr($readable,' !"#$%&\'()*+,-./0123456789:;<=>?#ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ'
,'¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ !"#$%&\'()*+,-./0123456789:;<=>?#ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ '
);
print $unreadable; //outputs: "ÕéêôAêôAâAôñæäêâíAõæôõAôõóêïèAÂÃIJ³´A©Ü¬­®¢¤¥¦§«Þª"
to decode in php:
$unreadable='ÕéêôAêôAâAôñæäêâíAõæôõAôõóêïèAÂÃIJ³´A©Ü¬­®¢¤¥¦§«Þª';
$readable=strtr($unreadable,'¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ !"#$%&\'()*+,-./0123456789:;<=>?#ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ '
,' !"#$%&\'()*+,-./0123456789:;<=>?#ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ ¡¢£¤¥¦§¨©ª«¬­®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖ×ØÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ'
);
print $readable; //outputs: "This is a special test string ABC123 ([+,-!#$%&*])"
you can easily replicate this logic in the DB if necessary (without looping): Using a Table of Numbers, by Erland Sommarskog
How about base64 encoding? We use to use that to make SMS messages in our SMS Gateway DB unreadable by the developers.
Try these PHP functions convert_uuencode and convert_uudecode:
function encrypt_decrypt ($data, $encrypt) {
if ($encrypt == true) {
$output = base64_encode (convert_uuencode ($data));
} else {
$output = convert_uudecode (base64_decode ($data));
}
return $output;
}
$enc_txt = encrypt_decrypt ("HELLO DATA", true);
echo $enc_txt."\n"; // KjIkNSwzJFxAMSQlNDAwYGAKYAo=
echo encrypt_decrypt ($enc_txt, false); // HELLO DATA
There are a few options.
If you want very strong, you could look into mcrypt.
But if it's only so working developers cant read the text without some work to actually do it. Then you could just BASE64 encode it or uuencode it
If you have mcrypt installed (all my current PHP environments have), you could use mcrypt_encrypt and mcrypt_decrypt like this:
function encrypt ($text) {
global $key;
return mcrypt_encrypt (MCRYPT_RIJNDAEL_256, $key, $text, MCRYPT_MODE_ECB, "abcdefghijklmnopqrstuvwxyz012345");
}
function decrypt ($secret) {
global $key;
return rtrim (mcrypt_decrypt (MCRYPT_RIJNDAEL_256, $key, $secret, MCRYPT_MODE_ECB, "abcdefghijklmnopqrstuvwxyz012345"), "\0");
}
which uses a global $key and AES (very strong).
Drawbacks are performance (in comparison to simpler ones like Base64) and that you somehow have to fix a key.
Cheers,
if you're using mysql around version 5, then you don't even need much php for it, you can do it inside your query with the mysql string functions encrypt(text, password) and decrypt(text, password)
http://dev.mysql.com/doc/refman/5.1/en/encryption-functions.html
DECODE(crypt_str,pass_str)
Decrypts the encrypted string crypt_str using pass_str as the password. crypt_str should be a string returned from ENCODE().
ENCODE(str,pass_str)
Encrypt str using pass_str as the password. To decrypt the result, use DECODE().
The result is a binary string of the same length as str.
The strength of the encryption is based on how good the random generator is. It should suffice for short strings.
update: another possibility would be rot13 ^^
Try using the mcrypt library. It's not included with standard PHP, but it's easily downloadable and very commonly used. Here's a quick tutorial on what you can do with it.
It's best to make sure the key you use for the encryption is stored in a secure place, but if you aren't really concerned about security, you'd probably be OK just hardcoding the key into your code somewhere.

Categories