I need to create a simple hashing method for passing some data in a URL. It doesn't need to be very secure, it just shouldn't be obvious to most people.
The hash needs to contains the numerical id of the sender and the id of the recipient and I should be able to decode the data after reading the appended hash.
Any ideas? I'd like the hash to be a short as possible, simply because this url is meant to be shared via IM, email, etc..
Hash is one way only. If you want to decrypt it, you have to encrypt it. Try mcrypt with one of these.
For non secure stuff you can try base64_encode, You can also base_convert each numeric id from 10 to 36 digits or so. Multiplying the numbers with a secret constant could also help.
$obscurity = base_convert($recipientId * 42, 10, 36) . ':' . base_convert($senderId * 42, 10, 36)
Try base64 encoding/decoding. put together with the apache option "Multiviews" or apache mod_rewrite, would make your urls look like:
http://mysite.com/messages/[encoded string here]
base64 definitely should do the trick if you want to decode it again.
Note that this is not a 'hash', a hash generally means one-way encryption.
$senderId = 1234;
$recipientId = 5678;
$myString = $senderId . ":" . $recipientId;
echo base64_encode($myString);
You could use encryption, as mentioned by #OIS.
Or you could use a hash and store the hash values in a database keyed to sender id and recipient id. PHP has md5() and sha1() built in.
Related
I am trying to send over an encrypted URL and then decode it at the other end. Now the call I make is passed over but my decryption returns null.
Here's some of my code.
$this->_app_url . '?key=' . $this->_api_key . '&request=' .base64_encode(mcrypt_encrypt(MCRYPT_RIJNDAEL_256, $this->_api_key, json_encode($url), MCRYPT_MODE_ECB));
The url is just a standard url, the key is a 32bit string so you can imagine it as anything. The $url variable is an array of stuff to be sent over. So that when I decrypt I have that array outright.
So at the other end I am trying to decode:
$key = $_REQUEST["key"];
$encrypted = $_REQUEST["request"];
$decrypted = json_decode(rtrim(mcrypt_decrypt(MCRYPT_RIJNDAEL_256, $key, base64_decode($encrypted), MCRYPT_MODE_ECB)));
This simply returns NULL, I can echo out the key and request and I get what i'm expecting but I just can't decrypt it.
This question has been asked a lot, with different word choice (which makes it difficult to say, "Just search for it!"). This fact prompted a blog post titled, The Comprehensive Guide to URL Parameter Encryption in PHP .
What People Want To Do Here
What People Should Do Instead
Explanation
Typically, people want short random-looking URLs. This doesn't allow you much room to encrypt then authenticate the database record ID you wish to obfuscate. Doing so would require a minimum URL length of 32 bytes (for HMAC-SHA256), which is 44 characters when encoded in base64.
A simpler strategy is to generate a random string (see random_compat for a PHP5 implementation of random_bytes() and random_int() for generating these strings) and reference that column instead.
If you must encrypt data (very much NOT recommended), don't use a homegrown design (and don't use mcrypt either!). Use a trustworthy library instead.
As in php we use $_GET to pass variables in the url , i want to pass variables which include the id of the user which i want to be anonymous, so can something be done which can encrypt the variable before passing it and the the variable once taken on the page can be decrypted to get the original variable value.
for eg:
Before passing variable $id=10;
Passed in the url as $id=dasfgjg;
when taken from the url and decrypted $id=10;
How can this be achieved?
You can use an RC4 cipher if you intend to encrypt/decrypt only on the server-side
http://www.phpkode.com/source/s/rc4-cipher-0-1/rc4-cipher-0-1/RC4.php
$my_secret_key = '3klmsd94mms.saeo44o!!3le';
if( isset($_GET['p']) ) {
$id = RC4::decrypt($my_secret_key, $_GET['p']);
// ....
}
else {
echo 'Go to the page';
}
Just generate random strings (make sure it's unique) for each record in the database and save it there, too. Then use this as an identifier. Note that, of course, this has nothing to do with encryption.
A quick and dirty way to achieve this (for each request)
on the client, create a string like 'xx:10:yy' where xx and yy are strings consisting pf random characetrs
on the client, create a salted hash of the users salted/hashed password
use this hash as a key and the string from the first bullet as cleartext for encryption with e.g. crypt.js
in the request send the encrypted string and the salt
on the server use the transmited salt and the users salted/hashed password to recover the key
on the server use mcrypt or friends to decrypt the string
on the server use standard PHP text processing functions to recover the payload from the decrypted string
In a CMS app I occasionally need to open an iframe of another domain. At the moment I am setting the URL for that iframe to something very obscure. Like http://domain.com/iframe/jhghjg34787386/. This works but theoretically that iframe source url will get saved in the user's history and could be accessed from the outside world.
So, I am wondering about using a time-based approach to an ever-changing hash or string that is processed on the request side and is checked on the iframe source side. However I would like it to be time based.
I could do this to get my hash:
<?php
$seed = '123456789'; // a password that both the parent and source have
$string = md5(time().$seed);
?>
But then the two servers have to be exactly synced. Any way to make the time constraint more fuzzy?
I am also open to other approaches. Is there any way to validate that the parent window for an iframe is of a certain domain?
You could add a key to your hash and send the timestamp with the query, e.g.:
$key = "YOUR_SECRET_KEY";
$time = time();
$hash = hash_hmac('sha256', $time, $key);
$url = "https://example.com/iframe?hash=$hash&time=$time";
On the other side you should first check if the timestamp is in the limits (e.g. not older than five minutes) and than rehash with the key and the submitted timestamp. If you get the same hash the request is valid.
Notes:
don't use MD5: the algorithm is completely broken and doesn't provide any security anymore (although it's supposed to still be ok when used with an HMAC…)
you should use hash_equals for comparing hashes to prevent timing attacks
we use an HMAC to guarantee data integrity and authentication. See https://crypto.stackexchange.com/questions/1070/why-is-hkx-not-a-secure-mac-construction for why we mustn't just concatenate time & key
You shouldn't use plain MD5 that; MD5 is not designed for ensuring message authenticity. Instead you can just give the timestamp publicly, alongside with other information (message), base64 encoded, so that it does not contain the ':' character. Then you can calculate the HMAC code of the message for example with
$hmac = hash_hmac("md5", $message, $secret)
$signed_message = $message . ":" . $hmac
On the other end you can then check this signature, by first splitting with ":", getting $message and $hmac, then you can check authenticity with
$hmac == hash_hmac("md5", $message, $secret)
If codes match, then check if the timestamp in the $message is still within the limits.
Be careful of using MD5 for hashing - it is cryptographically broken. There are any number of online sites to help create collisions. Rather use something like SHA256 and always include a long salting string.
If the user does not have to interact with the site in the iframe you could consider scraping the site code and inserting it directly into your code. There are a number of libraries available for this.
What about using something like
$hash = hash ( "sha256" , date("h") . 'myverylongsaltstring' );
So long as the servers have their timezones correct and are synchronized to within an hour this approach will work like your time() hash.
Additionally you could use something like TinyUrl to obfuscate the link a little further. Something along the lines of http://www.technabled.com/2008/12/create-your-own-tinyurl-with-php-and.html
If it is time based, then the amount of possible keys that a person would have to guess would be tiny.
Since I would know approximately when a URl might be generated, and I know how you are hashing it, then I can just create hundreds of thousands of links and test them out.
You should use UUID or something equivalent. The probability of a collission would be essentially impossible.
I am trying to create my own torrent tracker but dont know how to generate info_hash that is used xbtt to track torrents.
Is this possible with php?
I am using this function to bencode and decode http://paste.lisp.org/display/17178
Is this the correct hash?
$nn = file_get_contents('my.torrent');
$file = bdecode($nn);
$hash = sha1( bencode($file[info]) );
Thank You.
According to the bittorrent specification the info_hash is an urlencoded 20-byte SHA1 hash of the value of the info key from the Metainfo file.
You can calculate the sha1 hash of a string in php using the sha1 function and url encode ot with the urlencode function.
UPDATE:
Your method is not correct. You need to bdecode the torrent file, which you have already done. But you need to calculate the info_hash based on the value of the info key from the Metainfo (torrent) file.
When you have done that, you still need to urlencode the result, which it seems is also missing from your current implementation.
I was attempting to
encrypt de cookie data with md5, but I can not validate the hash back.
It has got to do, with the fact that cookie_data is a serialized array, because normal stringvalues work ok.
It's actually from a codeigniter class, but it does not work??
Does anyone know what the problem might be?
$hash = substr($session, strlen($session)-32);
$session= substr($session, 0, strlen($session)-32);
if ($hash !== md5($session.$this->encrypt_key))
{........
and the cookie value is encrypted like this
$cookie_data = $cookie_data.md5($cookie_data.$this->encrypt_key);
EDIT
I found that the answer is to use urlencode en urldecode in the proces of creating and validate
md5 hashes, because setcookie does urlencode automaticly, and thereby possibly changing the hash.
thanks, Richard
You have a typo:
md5($sessie.$this->encrypt_key))
should be
md5($session.$this->encrypt_key))
If you develop with notices turned on you'll catch this kind of thing much more easily.
You're not encrypting your data, you're signing it.
md5 is a oneway function. It is not a reversible one, so you can't decrypt the data.
The only thing you can do is encrypt the original data (if you saved it elsewhere) and check the result of this second computation.
If the value retrieved and the new value calculated are the same, the hash you received is valid (As you are doing in your code).
EDIT
You know, with just three lines of code I will guess some possible causes:
$session doesn't contains at the beginning of your code the same value of cookie_data.
you are using multibyte strings and strlen is not mb aware (use the idioms substr($session,0,-32) to get the payload part of the string.
maybe substr doesn't cope with multibyte strings too, use explicitally mb_substr (or whatever it is called).
To me the first case is the more probable. For what I can see.
I was attempting to encrypt de cookie
data with md5, but I can not decrypt
it back for validation.
md5 isnt an encryption method. it creates a one-way hash that cant be turned back into the original data.
If you want to encrypt data try mcrypt