Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Easy Encryption and Decryption with PHP

Tags:

php

encryption

My PHP Application uses URLs like these:

http://domain.com/userid/120
http://domain.com/userid/121

The keys and the end of the URL are basically the primary key of the MySQL database table.

I don't want this increasing number to be public and I also don't want that someone will be able to crawl the user profiles just by interating the Id.

So I want to encrypt this Id for display in a way I can easily decrypt it again. The string shouldn't get much longer.

What's the best encryption method for this?

like image 588
norwald2 Avatar asked Dec 13 '10 14:12

norwald2


4 Answers

Simple Obscuring: Base64 encode them using base64_encode.
Now, your http://domain.com/userid/121 becomes: http://domain.com/userid/MTIx
Want more, do it again, add some letters around it.

Tough Obscuring: Use any encryption method using MCrypt library.

like image 87
shamittomar Avatar answered Nov 11 '22 14:11

shamittomar


A better approach (from a usability and SEO perspective) would be to use a unique phrase rather than an obscured ID. In this instance the user's user name would seem an ideal solution, and would also be un-guessable.

That said, if you don't want to use this approach you could just use a hash (perhaps md5) of the user's user name which you'd store in the database along with their other details. As such, you can just do a direct lookup on that field. (i.e.: Having encrypt and decrypt part of the URL is probably overkill.)

like image 37
John Parker Avatar answered Nov 11 '22 15:11

John Parker


You have a variety of choices here:

  • Generate and store an identifier in the database. It's good because you can then have readable keys that are guaranteed to be unique. It's bad because it causes a database schema change, and you have to actually query that table every time you want to generate a link.

  • Run an actual key-based encryption, for instance based on PHP's MCrypt. You have access to powerful cryptographic algorithms, but most secure algorithms tend to output strings that are much longer than what you expect. XOR does what you want, but it does not prevent accessing sequential values (and the key is pretty simple to determine, given the a priori knowledge about the numbers).

  • Run a hash-based verification: instead of using 121 as your identifier, use 121-a34df6 where a34df6 are the first six characters of the md5 (or other HMAC) of 121 and a secret key. Instead of decoding, you extract the 121 and recompute the six characters, to see if they match what the user sent. This does not hide the 121 (it's still right there before the hyphen) but without knowing the secret key, the visitor will not be able to generate the six characters to actually view the document numbered 121.

  • Use XOR with shuffling: shuffle the bits in the 30-bit identifier, then apply the XOR. This makes the XOR harder to identify because the shuffle pattern is also hidden.

  • Use XOR with on-demand keys: use fb37cde4-37b3 as your key, where the first part is the XOR of 121 and md5('37b3'.SECRET) (or another way of generating an XOR key based on 37b3 and a secret).

Don't use base64, it's easy to reverse engineer: if MTIx is 121, then MTIy is 122 ...

Ultimately, you will have to accept that your solution will not be secure: not only is it possible for users to leak valid urls (through their browser history, HTTP referer, or posting them on Twitter), but your requirement that the identifier fits in a small number of characters means a brute-force attack is possible (and becomes easier as you start having more documents).

like image 4
Victor Nicollet Avatar answered Nov 11 '22 13:11

Victor Nicollet


Simplest but powerful encryption method: XOR with a secret Key. http://en.wikipedia.org/wiki/XOR_cipher No practical performance degradation.

Base64 representation is not an encryption! It's another way to say the same.

Hope this helps.

like image 1
hmassad Avatar answered Nov 11 '22 13:11

hmassad