So let's say I have "site1.mysite.com", "site2.mysite.com", etc. I want people (developers) to access some of the data via PHP generated JSON, but I also don't want to have to set up user accounts, sign ins, blah blah blah.
I don't want it to be open for "everybody".
What I started doing was this:
Users need to add "&user=somethingigivethem" and "key=somethingelseigivethem". These are values I provide to the user.
The key is currently the MD5 hash of the "user" and something like "53CR37P$%%" so basically:
$key_validator = md5($_GET['user'].'53CR37P$%%');
if($_GET['key'] === $key_validator){
//show JSON
} else {
//show error
}
Are there any major flaws in doing it this way?
So basically, if Joe Developer wants access, you give him a username and a key (which is an MD5 hash of his name + your salt). Joe can then make requests to your data.
If Joe wants to (ie. takes the time) he can probably figure out your hashing scheme just by trying different combinations of his username & salt values. And once he does, he'll know your salt and can access any other user's data.
I guess the question is: how valuable is this data? If you don't really care if other people get access and you really just want to keep out people who aren't too motivated to get your data, then this will work.
You could always combine an md5 and sha1 values with a randomized salt and also include your original salt value.
Example:
$key_validator = md5(sha1($_GET['user'].rand(0,1000)).'53CR37P$%%');
A little bit harder to crack, but you get the picture.
If I understood well, you generate both user and key for the user.
So the user have not to register and not to create it's own combination.
Making a key based on the user may be predictable quite easily, and overall with MD5.
I would recommend 2 ways:
If you really do not want to use your own database, generate a password based on better encryption system so people cant peak around the seed and encryption formula
(after all, makeing a md5 with the seed inside is a sort of "having the key into the password itself", no good)
Better encryption system supported by php: mainly all :) (you may need to install mcrypt extension) (support tens of encryptions, including most current like DES, 3DES, CAST, 2FISH, etc)
If you have no problem in using a database (or why not, a local file having the username/password pairs) , just generate a random strong password and keep the pairs in your database, and then just check against your stored values to give access, you still dont ask to the user to "register"
Oh, and don't forget, MD5 is only one way encryption, while real encryption with 3DES etc is reversible, so you can also compare things against real value.
Related
User's content is encrypted, but needs to be decrypted. There are multiple files that need decryption to be viewed, and they will definitely not be viewed at the same time.
I am currently encrypting by using the user's plaintext password to encrypt a randomly-generated key, which encrypts the user's data. The password is hashed and verified normally before doing anything. I am using PHP's aes-128-gcm openssl_encrypt() function.
My current system requires a password every time the user wants to read a file.
I have thought about decrypting all of the content at one, but this doesn't scale well. I have also thought about storing the user's key as a cookie, but I'm worried about security.
Is there a standard way to do this?
Thanks!
The first thing to do is separate the users password out of this. You'll have to decrypt and re-encrypt all their files. There may be other ways around this such as allowing only new files to use this system. But that is very use case specific, such as how long do you keep their files, what is the turn over on them etc..
In any case this is a way to do that:
Encrypt the files they submit using a password you generate.
Store this password in another file we'll call it key.txt for now. Encrypt this file using the users password.
When user logs in (if they don't have it stored) take their password, decrypt key.txt and get the generated password.
Now you can save this generated password anywhere you want, without affecting the users account.
What they see (the end user experience) will look like always they go to downlaod a file, put their password in and get the file. They wont ever know you did this, which is nice for them.
So problem one is fixed.
Now where should we store this?
You could simply store it on the server in the DB. This sort of depends on how confidential the data is, and how secure your server is. Your ultimately responsible for the security of someone else's data, at least this way you can control it.
Make a table with these fields
user_id | ip | password | last_access
When a user goes to download a file, check their last access time and IP address to invalidate the password and make them refresh it. This is very easy to setup and totally under your control. If you save the encryption key, it will always have some level of vulnerability at least this way its all under your control.
Even if you don't want to store it in your DB, the biggest disadvantage here is if someone gets a hold of that table, but if they do that and your storing important data you probably have plenty of problems already.
At least use the first part as that solves a big problem with tying this to their actual account password. Even if a hacker gets the file password from the client (stolen cookies etc.) because it's separate, having that alone wont let them login to your site like the account password would. I am assuming here, a user must login to even get to the download part. Using the same password for both gives them them access to both the means of the getting this data and the method to download it.
To be clear, their is an argument to be made about storing it on the client side. Then if your site is compromised there is less chance someone could get a hold of the password as it (depending how you do it) only exist in memory on both the client and server etc. It puts the responsibility on them.
ASYMMETRIC ENCRYPTION
You could also use asymmetric encryption. Currently it looks you are using AES, which is fine, but it's a Symmetric Key block cypher. Basically there are three common forms of "encryption" (in vernacular):
Hashing (which really isn't encryption) - md5, sha1, sha256 - these are one way, can't be decoded. They have fixed lengths, and always encrypt to the same thing. It's common to see this for file checksum (for validating the contents of the file), Block Chain, Passwords or anything else where you need to compare two "encrypted" values.
Symmetric - AES, 3DES, Blowfish, Twofish - anything you need to encrypt and decrypt. The same key can do both. Generally these will encrypt the same thing to different values each time, because of the IV.
Asymmetric - SSL, DSA, RSA, PGP, used in Crypto currency wallets, TLS etc. With these you have 2 keys, a public one and a private one. The keys cannot decrypt their own encrypted data, only the other key can. So with this if you have one key on the server and the client has the other. You can encrypt their files using your key (decryptable by only their key) and you don't have to worry so much about someone getting your key as it won't allow them to decrypt the files. You can give one key to the client, who can use that key to decrypt their data you encrypted (even without your key). These also encrypt to different "Stuff" each time you use them.
So you can see Asymmetric form has a few advantages to use in a two(or more) party system. It also has the benefit that you don't need their key to encrypt a file. All you need is your part of the pair. So for example if you generate data for them and wan't to encrypt and later have them decrypt it with the same system, you can do that with no issues. This probably eliminates a step, as you would need to ask them, or keep track of their Symmetric anytime you wanted to encrypt something. Here you just need your part of the key pair.
It really isn't much harder to implement (on the server), its just harder to understand what it does. That's why I decided to add this, without this knowledge (which you may or may not already know) it's hard to use these terms and have them make sense. The only real disadvantage for you (if you call it that) if you used Asymmetric encryption, is if a client loses their key you would have no way to decrypt the file. So I would make sure they know to back them up in a secure place. It's the same problem that you see in the news when it comes to losing a crypto currency wallet which is encrypted Asymmetrically
As I said most of my knowledge has to do with encrypting and dealing with data on a server. So I am not sure how to tie that in to the "client experience". I do know for example how to use RSA keys for password less login for SSH etc. Which is kind of the same thing but not quite.
Hope it helps!
they will definitely not be viewed at the same time
Wouldn't the most secure answer here be to simply require the password every time? I would assume (although I'm sure this isn't the answer you're looking for) that simply asking for the password each time might be the best solution.
Although it may be tedious for the user, I would also assume it imparts some sense of security - since it's not quite as simple as logging in (as the files are encrypted).
From my perspective, I would argue that encrypted files should not be mass decrypted anyways?
Sorry, I know this isn't the answer you're looking for - but if you have more information about your motivation, maybe then a more reasonable solution can be found?
Don't do decryption on the server-side - do it client side. It is safe to keep the user's password in memory on their own device.
I'm using Mysql and I was assuming it was better to separate out a users personal information and their login and password into two different tables and then just reference them between the two.
Note : To clarify my post, I understand the techniques of securing the password (hash, salt, etc). I just know that if I'm following practices from other parts of my life (investing, data backup, even personal storage) that in the worst case scenario (comprised table or fire) that having information split among tables provides the potential to protect your additional data.
Don't store passwords. If it's ever sitting on a disk, it can be stolen. Instead, store password hashes. Use the right hashing algorithm, like bcrypt (which includes a salt).
EDIT: The OP has responded that he understands the above issue.
There's no need to store the password in a physically different table from the login. If one database table is compromised, it's not a large leap to access another table in that same database.
If you're sufficiently concerned about security and security-in-depth, you might consider storing the user credentials in a completely separate data store from your domain data. One approach, commonly done, is to store credentials in an LDAP directory server. This might also help with any single-sign-on work you do later.
The passwords should be stored as a cryptographic hash, which is a non-reversible operation that prevents reading the plain text. When authenticating users, the password input is subjected to the same hashing process and the hashes compared.
Avoid the use of a fast and cheap hash such as MD5 or SHA1; the objective is to make it expensive for an attacker to compute rainbow tables (based on hash collisions); a fast hash counteracts this. Use of an expensive hash is not a problem for authentication scenarios, since it will have no effect on a single run of the hash.
In addition to hashing, salt the hash with a randomly generated value; a nonce, which is then stored in the database and concatenated with the data prior to hashing. This increases the number of possible combinations which have to be generated when computing collisions, and thus increases the overall time complexity of generating rainbow tables.
Your password hash column can be a fixed length; your cryptographic hash should output values which can be encoded into a fixed length, which will be the same for all hashes.
Wherever possible, avoid rolling your own password authentication mechanism; use an existing solution, such as bcrypt.
An excellent explanation of how to handle passwords, and what you need to concern yourself with, can be found at http://www.matasano.com/log/958/enough-with-the-rainbow-tables-what-you-need-to-know-about-secure-password-schemes.
As a final note, please remember that if an attacker obtains access to your database, then your immediate concern should probably be with any sensitive or personally-identifying information they may have access to, and any damage they may have done.
There's nothing wrong with putting them in the same table. In fact, it would be much faster, so I'd highly recommend it. I don't know why you'd want to split it up.
I'll attempt to answer your original question. Having it all in one table is fine unless you just have a lot of personal information to gather. In that case it may make sense to split it up. That decision should be made based on the amount of personal information you're dealing with and how often it needs to be accessed.
I'd say most of the time I'd do something like this in a single table:
UserID, FirstName, LastName, Email, Password, TempPassword
But... if you're gathering much more than that. Say you're gathering phone, fax, birth date, biography, etc, etc. And if most of that information is rarely accessed then I'd probably put that in its own table and connect it with a one-to-one relationship. After all, the fewer columns you have on a table, the faster your queries against that table will be. And sometimes it makes sense to simplify the tables that are most accessed. There is a performance hit with the JOIN though whenever you do need to access that personal information, so that's something you'll have to consider.
EDIT -- You know what, I just thought of something. If you create an index on the username or email field (whichever you prefer), it'll almost completely eliminate the performance drawback of creating so many columns in a user table. I say that because whenever you login the WHERE clause will actually be extremely quick to find the username if it has an index and it won't matter if you have 100 columns in that table. So I've changed my opinion. I'd put it all in one table. ;)
In either case, since security seems to be a popular topic, the password should be a hash value. I'd suggest SHA1 (or SHA256 if you're really concerned about it). TempPassword should also use a hash and it's only there for the forgot password functionality. Obviously with a hash you can't decrypt and send the user their original password. So instead you generate a temporary password they can login with, and then force them to change their password again after login.
Will all of this data always have a 1:1 relationship with the user? If you can forsee allowing users to have multiple addresses, phone numbers, etc, then you may want to break out the personal info into a separate table.
First, to state the (hopefully) obvious, if you can in any way at all avoid storing usernames and passwords do so; it's a big responsibility and if your credential store is breached it may provide access to many other places for the same users (due to password sharing).
If you must store credentials:
Don't store a reversible form; store a hash using a recognized algorithm like SHA-256. Use cryptographic software from a reputable trustworthy source - DO NOT ATTEMPT TO ROLL YOUR OWN, YOU WILL LIKELY GET IT WRONG.
For each credential set, store a salt along with the hashed data; this is used to "prime" the hash such that two identical passwords do not produce the same hash - since that gives away that the passwords are the same.
Use a secure random generator. Weak randomness is the number one cause of encryption related security failures, not cipher algorithms.
If you must store reversible credentials:
Choose a good encryption algorithm - AES-256, 3DES (dated), or a public key cipher. Use cryptographic software from a reputable trustworthy source - DO NOT ATTEMPT TO ROLL YOUR OWN, YOU WILL LIKELY GET IT WRONG.
For each credential set, store a salt (unencrypted) along with the encrypted data; this is used to "prime" the encryption cipher such that two identical passwords do not produce the same cipher text - since that gives away that the passwords are the same.
Use a secure random generator. Weak randomness is the number one cause of encryption related security failures, not cipher algorithms.
Store the encryption/decryption key(s) separately from your database, in an O/S secured file, accessible only to your applications runtime profile. That way, if your DB is breached (e.g. through SQL injection) your key is not automatically vulnerable, since that would require access to to the HDD in general. If your O/S supports file encryption tied to a profile, use it - it can only help and it's generally transparent (e.g. NTFS encryption).
If practical, store the keys themselves encrypted with a primary password. This usually means your app. will need that password keyed in at startup - it does no good to supply it in a parameter from a script since if your HDD is breached you must assume that both the key file and the script can be viewed.
If the username is not necessary to locate the account record encrypt both the username and password.
In my personal experience, storing the personal information and the login information in individual databases is the best practice in this case. The reason being should an SQL injection take place, it is limited (unless the infiltrator knows the inner layout of your database(s)) to the table that the data pertains to, as opposed to providing access to the whole conglomerate of data.
However, do note that this may come at the expense of needing to perform more queries, hence a performance hit.
You ought to store them in the same table, and use one-way encryption. MD5 will work, but is weak, so you might consider something like SHA1 or another method. There's no benefit to storing the 2 items in seperate tables.
I've been studying/looking about on Google for TOO long and although I find many so-so tutorials, I'm wondering a bit about the "optional SALT" parameter in the (crypt) function within PHP. I have too many tabs open and getting nowhere so, at this point, I figured id just ask for help.
As far as the salt, I read somewhere that if you don't add it, it will be added for you but that this is not good practice. I can't seem to find the "why" it's good/not good. How should this be handled?
I've read a few things here and there about randomizing salts but others say it doesn't matter...again, confusing.
Also I'm having problems checking against the stored data as well. Obviously if I do something like
crypt("pass string here",salt here);
ill get a random string for the pass....so on a user log in, then the value of
$_POST['the entered name/pass etc '];
and checking against the db value for that users pass would always equal to false. So then I suppose that id have to rehash /salt the pass given upon user entry and then test against what's on the db?
Also, I've read throughout the net (but at this point I'm confused) that somehow the salt is stored in the db? and it doesn't have to be hidden?
I can keep going on and on, just lost honestly, I think I've read too much and not sure how to proceed. At this point, What id REALLY prefer is a GOOD link with tutorial if anyone has those resources.
You need to generate a secure random salt value when the user signs up, and store that salt in the database.
When the user logs in, fetch the salt and hash from the database, compute the hash of the password they typed using the original salt, and make sure the hash matches.
Also, don't use general-purpose hash algorithms (such as MD5 or SHA*); instead, use dedicated slow password-hashing algorithms, such as bcrypt or scrypt or PBKDFv2.
To maximize security, you never have a plaintext password in the database and leave it open to anyone who has/can get access to that database. So what you do is pick a predefined salt, take the user's desired password and encrypt it using the salt and a hash.
The salt is some extra random characters you add on to make the hashed password even more secure., you should keep track of this.
The hash then takes the salt + password and generates a random string based on it, such that you will always get that unique hash if you give it the same salt+password.
This seems like a fairly useful introduction to salting/hashing:
http://crackstation.net/hashing-security.htm
I'm looking to store (in mySQL) an obfuscated version of a phone number, where the number is used for authentication (I need to be able to get back the original number).
I've thought about an arbitrary scheme like storing the number * 15 or some constant only my app knows.
What are some better ways of doing this?
EDIT: Some things I'd like to clarify:
The phone numbers that are saved can be used to log into an iPhone app - so I want users to be able to see which number they have connected to the service incase they want to log into the app with a different number later. This means I cannot hash the value.
Essentially I am looking for a way to protect the data if someone lifts my database that they don't have a bunch of phone numbers in raw form. So I'd like to obfuscate them so I can use them for authentication, but be able to get one back in its original form without storing it raw.
EDIT: To clarify, I am not authenticating on JUST the phone number. If implemented, it would be phone number + a password! Enter a single string of digits that may exist and you're in? lol - my apologies if I have misled some folks.
Store where? In a database? Use an encryption function rather than rolling your own system.
In MySQL it'd be as simple as:
INSERT INTO users (phone) VALUES (AES_ENCRYPT('yourkey', '867-5309'));
of course, now you're changed the problem from hiding the phone numbers to "where the #$##$## can I hide this key?". Obvious solution: hide the key under a rock outside your server's front-door. Which changes the problem into "where the ####$###% can I hide this rock?". Obvious solution: cover your front yard with a steel cage with a padlock on the door. New problem: how to hide the padlock key... and so on.
How about actual encryption? In this scenario, a good symmetric encryption algorithm is trivial, since the length of the payload is limited to, what, 10 digits, so you can get by with a key that's also 10 decimal digits long; using such a key, all you need to do is something like XOR or increment / mod 10 on each digit. Of course, the weak link in this scheme then is the way you store the key.
I am curious, however, why you need to get them back out - if it's for authentication:
you shouldn't be using phone numbers, as these are easy to look up, even automatically
you should be storing secure one-way hashes with individual salts, so you couldn't even get them back out youself if you wanted to (except by brute-forcing)
Using the Cipher Class you can do this:
$phone = '...';
$key = 'secret.for.each.number';
$phone = Cipher::encrypt($phone, $key);
Before you store it in the database. Then later you can pull it out and do this:
$phone = Cipher::decrypt($phone, $key);
A better way would be not doing that. There is a reason one-way encryption is used to store passwords.
If you need to get back the original value, you should not be using it for authentication, since it will invariably be easy for an attacker to find it.
If you feel you need to hide the value by obfuscating it, you probably need to change something fundamental about how you're storing the data.
This isn't a very good approach to security. Several things jump out at me:
Phone numbers are very easy to guess: just program something to start guessing random combinations. Encrypted or not, your program is validating using these numbers, so it will eventually work on some. You need an extra layer of security like a password known only to the user in question. I would recommend anti-brute-force attack measures as well.
Any two-way encryption can be cracked, it is as simple as that. If you need to be able to decrypt data in the database easily, the only benefit from encrypting it is if someone hacks into your database and grabs the information. As others have pointed out, if that happens, you have bigger issues. The other scenario is for staffers who could have valid access to the DB. If you are hiding the data from them, it is important to encode the information in some way. But multiplying the phone number by a "unknown" constant is not ideal. Use a better method.
Surely I know my friend's numbers, so I could hack into anyone's account, correct? You need to add a password component if you haven't already. The password should be 1-way encryption using a strong and unique SALT. Once added, you only need to encrypt phone numbers in the DB if you don't want your staffers to see them. Otherwise you are wasting time encrypting them.
There is no point in this question.
Just leave these phone numbers as is. You will gain no security improvement from such obfuscation
I'm using Mysql and I was assuming it was better to separate out a users personal information and their login and password into two different tables and then just reference them between the two.
Note : To clarify my post, I understand the techniques of securing the password (hash, salt, etc). I just know that if I'm following practices from other parts of my life (investing, data backup, even personal storage) that in the worst case scenario (comprised table or fire) that having information split among tables provides the potential to protect your additional data.
Don't store passwords. If it's ever sitting on a disk, it can be stolen. Instead, store password hashes. Use the right hashing algorithm, like bcrypt (which includes a salt).
EDIT: The OP has responded that he understands the above issue.
There's no need to store the password in a physically different table from the login. If one database table is compromised, it's not a large leap to access another table in that same database.
If you're sufficiently concerned about security and security-in-depth, you might consider storing the user credentials in a completely separate data store from your domain data. One approach, commonly done, is to store credentials in an LDAP directory server. This might also help with any single-sign-on work you do later.
The passwords should be stored as a cryptographic hash, which is a non-reversible operation that prevents reading the plain text. When authenticating users, the password input is subjected to the same hashing process and the hashes compared.
Avoid the use of a fast and cheap hash such as MD5 or SHA1; the objective is to make it expensive for an attacker to compute rainbow tables (based on hash collisions); a fast hash counteracts this. Use of an expensive hash is not a problem for authentication scenarios, since it will have no effect on a single run of the hash.
In addition to hashing, salt the hash with a randomly generated value; a nonce, which is then stored in the database and concatenated with the data prior to hashing. This increases the number of possible combinations which have to be generated when computing collisions, and thus increases the overall time complexity of generating rainbow tables.
Your password hash column can be a fixed length; your cryptographic hash should output values which can be encoded into a fixed length, which will be the same for all hashes.
Wherever possible, avoid rolling your own password authentication mechanism; use an existing solution, such as bcrypt.
An excellent explanation of how to handle passwords, and what you need to concern yourself with, can be found at http://www.matasano.com/log/958/enough-with-the-rainbow-tables-what-you-need-to-know-about-secure-password-schemes.
As a final note, please remember that if an attacker obtains access to your database, then your immediate concern should probably be with any sensitive or personally-identifying information they may have access to, and any damage they may have done.
There's nothing wrong with putting them in the same table. In fact, it would be much faster, so I'd highly recommend it. I don't know why you'd want to split it up.
I'll attempt to answer your original question. Having it all in one table is fine unless you just have a lot of personal information to gather. In that case it may make sense to split it up. That decision should be made based on the amount of personal information you're dealing with and how often it needs to be accessed.
I'd say most of the time I'd do something like this in a single table:
UserID, FirstName, LastName, Email, Password, TempPassword
But... if you're gathering much more than that. Say you're gathering phone, fax, birth date, biography, etc, etc. And if most of that information is rarely accessed then I'd probably put that in its own table and connect it with a one-to-one relationship. After all, the fewer columns you have on a table, the faster your queries against that table will be. And sometimes it makes sense to simplify the tables that are most accessed. There is a performance hit with the JOIN though whenever you do need to access that personal information, so that's something you'll have to consider.
EDIT -- You know what, I just thought of something. If you create an index on the username or email field (whichever you prefer), it'll almost completely eliminate the performance drawback of creating so many columns in a user table. I say that because whenever you login the WHERE clause will actually be extremely quick to find the username if it has an index and it won't matter if you have 100 columns in that table. So I've changed my opinion. I'd put it all in one table. ;)
In either case, since security seems to be a popular topic, the password should be a hash value. I'd suggest SHA1 (or SHA256 if you're really concerned about it). TempPassword should also use a hash and it's only there for the forgot password functionality. Obviously with a hash you can't decrypt and send the user their original password. So instead you generate a temporary password they can login with, and then force them to change their password again after login.
Will all of this data always have a 1:1 relationship with the user? If you can forsee allowing users to have multiple addresses, phone numbers, etc, then you may want to break out the personal info into a separate table.
First, to state the (hopefully) obvious, if you can in any way at all avoid storing usernames and passwords do so; it's a big responsibility and if your credential store is breached it may provide access to many other places for the same users (due to password sharing).
If you must store credentials:
Don't store a reversible form; store a hash using a recognized algorithm like SHA-256. Use cryptographic software from a reputable trustworthy source - DO NOT ATTEMPT TO ROLL YOUR OWN, YOU WILL LIKELY GET IT WRONG.
For each credential set, store a salt along with the hashed data; this is used to "prime" the hash such that two identical passwords do not produce the same hash - since that gives away that the passwords are the same.
Use a secure random generator. Weak randomness is the number one cause of encryption related security failures, not cipher algorithms.
If you must store reversible credentials:
Choose a good encryption algorithm - AES-256, 3DES (dated), or a public key cipher. Use cryptographic software from a reputable trustworthy source - DO NOT ATTEMPT TO ROLL YOUR OWN, YOU WILL LIKELY GET IT WRONG.
For each credential set, store a salt (unencrypted) along with the encrypted data; this is used to "prime" the encryption cipher such that two identical passwords do not produce the same cipher text - since that gives away that the passwords are the same.
Use a secure random generator. Weak randomness is the number one cause of encryption related security failures, not cipher algorithms.
Store the encryption/decryption key(s) separately from your database, in an O/S secured file, accessible only to your applications runtime profile. That way, if your DB is breached (e.g. through SQL injection) your key is not automatically vulnerable, since that would require access to to the HDD in general. If your O/S supports file encryption tied to a profile, use it - it can only help and it's generally transparent (e.g. NTFS encryption).
If practical, store the keys themselves encrypted with a primary password. This usually means your app. will need that password keyed in at startup - it does no good to supply it in a parameter from a script since if your HDD is breached you must assume that both the key file and the script can be viewed.
If the username is not necessary to locate the account record encrypt both the username and password.
In my personal experience, storing the personal information and the login information in individual databases is the best practice in this case. The reason being should an SQL injection take place, it is limited (unless the infiltrator knows the inner layout of your database(s)) to the table that the data pertains to, as opposed to providing access to the whole conglomerate of data.
However, do note that this may come at the expense of needing to perform more queries, hence a performance hit.
You ought to store them in the same table, and use one-way encryption. MD5 will work, but is weak, so you might consider something like SHA1 or another method. There's no benefit to storing the 2 items in seperate tables.