PHP Developers Network

A community of PHP developers offering assistance, advice, discussion, and friendship.
 
Loading
It is currently Fri May 29, 2020 8:41 am

All times are UTC - 5 hours




Post new topic Reply to topic  [ 6 posts ] 
Author Message
PostPosted: Fri Jan 27, 2012 11:40 am 
Offline
Forum Contributor
User avatar

Joined: Sat Oct 01, 2011 9:29 pm
Posts: 156
Location: Colorado, USA
My college asked me to lead a team and design and develop a website for a project they're putting out. It's a long story.
Anyway, this site will be viewed and used by colleges throughout the US. It will be a place for students and teachers to
share files and collaborate on said project.

I thought I might need to include some security with this. Just a thought.
I needed a way to encrypt data for storage and then decrypt it for readability.

I looked at PHPs mcrypt, but I had a problem with it: It wasn't core. I had absolutely no idea what my or any other college was going to do with or where they were going to put it this once it was done, so I need the whole thing to be as flexible and ready-to-go as possible.
So I looked at base_64 - too easy to just rewash through the decode.

I finally found, on another forum, a set of functions that pretty much solved my problem. encrypt($string, $key) and decrypt($string, $key)
Well, I wanted one solid key for this, so I simply hard-coded it into another require()d page (this other page checks to see if the server's name is on a whitelist and connects to the DB if it is)

Still wasn't good enough. I'm going to potentially be dealing with everyone in the US (and I guarantee a whole bunch of security experts are going to run through my code before it goes live). I needed a salt, but I didn't want to have to type in a salt every single time I wanted to run the function. In essence, I wanted an encrypt($string) and a decrypt($string) which I pretty much achieved by having a "master" password. The point of this encryption is the encrypted data is stored in the database so in case the DB is compromised, all the attacker will get is a bunch of who knows what.

I edited and re-edited and finally came up with this:
Syntax: [ Download ] [ Hide ]
function encrypt($string, $key){
        $result = "";
        for($i=0; $i<strlen($string); $i++){
                $char = substr($string, $i, 1);
                $keychar = substr($key, ($i % strlen($key))-1, 1);
                $char = chr(ord($char)+ord($keychar));
                $result.=$char;
        }
        $salt_string = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxys0123456789~!@#$^&*()_+`-={}|:<>?[]\;',./";
        $length = rand(1, 15);
        $salt = "";
        for($i=0; $i<=$length; $i++){
                $salt .= substr($salt_string, rand(0, strlen($salt_string)), 1);
        }
        $salt_length = strlen($salt);
        $end_length = strlen(strval($salt_length));
        return base64_encode($result.$salt.$salt_length.$end_length);
}
function decrypt($string, $key){
        $result = "";
        $string = base64_decode($string);
        $end_length = intval(substr($string, -1, 1));
        $string = substr($string, 0, -1);
        $salt_length = intval(substr($string, $end_length*-1, $end_length));
        $string = substr($string, 0, $end_length*-1+$salt_length*-1);
        for($i=0; $i<strlen($string); $i++){
                $char = substr($string, $i, 1);
                $keychar = substr($key, ($i % strlen($key))-1, 1);
                $char = chr(ord($char)-ord($keychar));
                $result.=$char;
        }
        return $result;
}


For obvious reasons this isn't the whole code, but you can get the gist of it.
So my question is this: Is this secure enough for a database? I will use this on top of an md5() for passwords


Top
 Profile  
 
PostPosted: Tue Jan 31, 2012 5:32 am 
Offline
DevNet Resident
User avatar

Joined: Sun Sep 03, 2006 5:19 am
Posts: 1579
Location: Sofia, Bulgaria
This is a really really stupid code. It was written by someone who hasn't even read a basic book on cryptography.
No offense, but you yourself should not take security decisions like that either. Especially you should *not* eschew proven cryptographic primitives and replacing them with homebrew code.
About your concerns about support for mcrypt - wouldn't you control the installation environment? Having mcrypt installed should be pretty standard for any hosting.
Another concern you *should* have is that there are lots of interesting ways you can screw your encryption security even with mcrypt :)
What data will you encrypt and why? For how long? How would you manage the keys? How and when would it be decrypted?


Top
 Profile  
 
PostPosted: Wed Feb 01, 2012 1:27 pm 
Offline
Forum Contributor
User avatar

Joined: Sat Oct 01, 2011 9:29 pm
Posts: 156
Location: Colorado, USA
I understand that having a salt with a way around it in the string is a semi-bad idea. However, I would like to make a few points.

First, this is not the entire encryption. I also use another encryption method on top of it, as well as a few modifications to this one as well as another salt.
The only reason i'm using a "homebrew" method is - of course - because it will be more difficult for the attacker to get (or in this case, create) a solution.
the method above is by no means a replacement. It's simply an add-in.

Another note: I discovered my mistake with the salt. The string is now salted before it is encrypted.

Next, why would I add a way around the salt in the encrypted string? Because, to me, a salt does two things:
1) it makes the entire thing harder to decrypt, and
2) it gives the string a more "random" appearance, to help deter attackers.
So, being honest with myself, if they really want to get around the salt, storing it separately will not help. I might as well make it easier on myself.

To answer your question: I honestly have no idea how much control i'm going to have. They promise me that i'm going to be running the entire thing, but... Well, let's just say i've been promised that before by people like this. Eventually they're going to take over in one way or another; I might as well make sure they can't screw too much up. The only reason i'm doing this is because if it succeeds, I will end up with one hell of a boost on my resume.

And last: I will encrypt almost everything going into the database. Passwords will be md5()d under the encryption (ie. encrypt(md5($password), $key))
I say "almost" because there's a few things that really don't need to be encrypted (ie. Online status, date and time of last action, etc.)
The data will be stored indefinitely. Or at least until someone decides to delete the database. There is only one key. The key used is... I don't even know how long. I think around 25 characters, all of which are semi-random. The data will only be decrypted when it needs to be used. So far only in two cases: When logging in, and when viewing data in the database (for administrative purposes, mostly)


Top
 Profile  
 
PostPosted: Wed Feb 01, 2012 1:41 pm 
Offline
Forum Contributor
User avatar

Joined: Sat Oct 01, 2011 9:29 pm
Posts: 156
Location: Colorado, USA
I do appreciate your thoughts, though :D

I showed the whole PHP code to my security professor and he approved it, so I think it should be good enough. However, I still haven't really stored anything in the actual database and would be glad for some improvements


Top
 Profile  
 
PostPosted: Thu Feb 02, 2012 5:39 am 
Offline
DevNet Resident
User avatar

Joined: Sun Sep 03, 2006 5:19 am
Posts: 1579
Location: Sofia, Bulgaria
You seem to be mixing up one-way hashing and encryption. Salting is something you do for plaintexts that are to be hashed. When using block ciphers there is a similar concept, Initialization Vectors. What you do with that "encryption" (and I use the term losely ;) ) will not benefit from it. Encrypt more than a couple of k plaintext or more than a couple of m non-random binaries and your 25 character password will fail.

If I see such code on your resume, you'll have to have a hell of a reason why you did it this way. "Because the homebrew algorithm is unknown to the attacker" is a classic cryptography pitfall. The idea not to do that has .
I don't know what is the speciality of your "security professor", but if I, a layman, can see the glaring hole, it puts serious doubt to his knowledge (or of course he might just have said "yeah, it's fine" without giving it a read at all - gotta love the academia ;) )

If you wanted advice, it's "don't do it man!" :) But of course everyone is entitled to make his own mistakes, it's your funeral :)


Top
 Profile  
 
PostPosted: Thu Feb 02, 2012 11:11 am 
Offline
Forum Contributor
User avatar

Joined: Sat Oct 01, 2011 9:29 pm
Posts: 156
Location: Colorado, USA
haha, it's always a possibility he didn't actually read it.

Though a few questions:
1. Why not use salts for encryption and decryption as well?
The way I implemented it, it's not supposed to make it 100% infallible; just a pain in the rear for someone looking to forcefully decrypt it.

2. Why would the 25-character password fail?
I don't see a reason for it to; 100000/25 = 4000
30-4000 = ohhhhhhhhhhhhhhhhh
in that case, i'll check for a negative number and, if true, multiply it by -1 (-100*-1 = 100)
i'll also have to see how ord() handles ridiculously large numbers, and make corrections there if necessary
Well, thank you!

I read the wiki, and it seems (as I would have thought) that there is no problem in keeping the method a secret; as long as i'm not relying solely on that (which, thankfully, i'm not)
The point of this encryption is that it is simply (as wiki put it) another hurdle to overcome. It will not and should not ever be used in place of an encryption. I will be using it as an "add-in"

On a side note: I have just found out (in the last 2 seconds) that it seems that the host I will be working on supports mcrypt()
I'm going to toss this function completely, but I think I will keep the salt and pepper. True, they don't help much. However; they're not hurting anything, and it's kinda funny to watch my friend's faces when I encrypt "test" 3000 times and every single one is a different length. (that and i've already set up the register and login scripts to handle the "ever-changing" return)

My final question is on mcrypt():
Rijndael 256? Or something better?


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 6 posts ] 

All times are UTC - 5 hours


Who is online

Users browsing this forum: No registered users and 4 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Jump to:  
Powered by phpBB® Forum Software © phpBB Group